提交 7f063300 authored 作者: yanpeng's avatar yanpeng

conflict

This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -19,10 +19,15 @@ ...@@ -19,10 +19,15 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.3.1", "@element-plus/icons-vue": "^2.3.1",
"@kangc/v-md-editor": "^2.3.18",
"@microsoft/fetch-event-source": "^2.0.1",
"@traptitech/markdown-it-katex": "^3.6.0",
"axios": "^1.12.2", "axios": "^1.12.2",
"echarts": "^5.4.3", "echarts": "^5.4.3",
"echarts-wordcloud": "^2.1.0", "echarts-wordcloud": "^2.1.0",
"element-plus": "^2.4.4", "element-plus": "^2.4.4",
"highlight.js": "^11.11.1",
"markdown-it": "^14.1.0",
"vue": "^3.4.0", "vue": "^3.4.0",
"vue-router": "^4.2.5" "vue-router": "^4.2.5"
}, },
......
<template> <template>
<div id="app"> <div id="app">
<el-container> <el-container class="wrapper">
<el-header> <el-header>
<nav class="navbar"> <nav class="navbar">
<div class="nav-brand"> <div class="nav-brand">
<el-icon class="brand-icon"><Monitor /></el-icon> <div class="brand-icon">
<span class="brand-text">某方向风险监测预警系统</span> <img src="@/assets/icons/header-logo.png" alt="" />
</div>
<div class="brand-text">
<div class="text-ch">某方向风险监测预警系统</div>
<div class="text-en">
National Science and Technology Security Risk Monitoring and Early Warning System
</div>
</div>
</div> </div>
<div class="nav-menu"> <div class="nav-menu">
<el-dropdown @command="handleHomeCommand" class="home-dropdown"> <el-dropdown @command="handleHomeCommand" class="home-dropdown">
...@@ -42,9 +49,13 @@ ...@@ -42,9 +49,13 @@
</div> </div>
</div> </div>
<div class="user-info"> <div class="user-info">
<el-icon><Message /></el-icon> <div class="email">
<el-icon><User /></el-icon> <img src="@/assets/icons/header-icon.png" alt="" />
<span>管理员</span> </div>
<div class="avator">
<img src="@/assets/icons/header-avator.png" alt="" />
</div>
<span class="user">管理员</span>
</div> </div>
</nav> </nav>
</el-header> </el-header>
...@@ -55,17 +66,38 @@ ...@@ -55,17 +66,38 @@
<el-main class="main-container"> <el-main class="main-container">
<router-view /> <router-view />
</el-main> </el-main>
<div class="ai-btn" @click="openAiBox">
<div class="icon">
<img src="@/assets/icons/ai-icon.png" alt="" />
</div>
<div class="text">智能问答</div>
</div>
<div class="ai-dialog" v-if="isShowAiBox">
<AiBox @close="closeAiBox" />
</div>
</el-container> </el-container>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from "vue";
import { Monitor, House, User, Location, Document, Bell, Message, ArrowDown } from "@element-plus/icons-vue"; import { Monitor, House, User, Location, Document, Bell, Message, ArrowDown } from "@element-plus/icons-vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import Breadcrumb from "@/components/BreadCrumb/index.vue"; import Breadcrumb from "@/components/BreadCrumb/index.vue";
import AiBox from "./components/AiBox.vue";
const router = useRouter(); const router = useRouter();
const isShowAiBox = ref(false);
const closeAiBox = () => {
isShowAiBox.value = false;
};
const openAiBox = () => {
isShowAiBox.value = true;
};
const handleHomeCommand = command => { const handleHomeCommand = command => {
router.push(command); router.push(command);
}; };
...@@ -90,20 +122,18 @@ body { ...@@ -90,20 +122,18 @@ body {
} }
</style> </style>
<style scoped> <style lang="scss" scoped>
#app { #app {
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif; font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
width: 100%; width: 100%;
height: 100vh; height: 100vh;
overflow-y: hidden; // overflow-y: hidden;
} }
/* 确保Element Plus容器组件占满宽度 */ /* 确保Element Plus容器组件占满宽度 */
.el-container { .el-container {
width: 100%; width: 100%;
/* min-height: 100vh; */
height: 100%; height: 100%;
margin-bottom: 20px;
} }
.navbar { .navbar {
...@@ -117,18 +147,30 @@ body { ...@@ -117,18 +147,30 @@ body {
border-bottom: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
position: relative; position: relative;
box-sizing: border-box;
height: 96px;
} }
.main-container { .main-container {
/* 移除宽度限制,让子页面自己控制布局 */ /* 移除宽度限制,让子页面自己控制布局 */
width: 100%; width: 100%;
height: 984px;
position: relative;
} }
.nav-brand { .nav-brand {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
position: absolute; position: absolute;
left: 24px; left: 160px;
.brand-icon {
width: 48px;
height: 48px;
img {
width: 100%;
height: 100%;
}
}
} }
.brand-icon { .brand-icon {
...@@ -137,9 +179,21 @@ body { ...@@ -137,9 +179,21 @@ body {
} }
.brand-text { .brand-text {
font-size: 18px; .text-ch {
font-weight: 600; height: 42px;
color: #333; color: rgba(10, 18, 30, 1);
font-family: Microsoft YaHei;
font-size: 32px;
font-weight: 700;
line-height: 42px;
}
.text-en {
color: rgba(10, 18, 30, 1);
font-family: Microsoft YaHei;
font-size: 10px;
font-weight: 400;
line-height: 13px;
}
} }
.nav-menu { .nav-menu {
...@@ -188,24 +242,80 @@ body { ...@@ -188,24 +242,80 @@ body {
.user-info { .user-info {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 20px;
padding: 8px 12px; padding: 8px 12px;
background: #f3f4f6;
border-radius: 6px; border-radius: 6px;
color: #333; color: #333;
position: absolute; position: absolute;
right: 24px; right: 159px;
.email {
width: 20px;
height: 20px;
img {
width: 100%;
height: 100%;
}
}
.avator {
width: 32px;
height: 32px;
img {
width: 100%;
height: 100%;
}
}
.user {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
}
}
.wrapper {
position: relative;
.ai-btn {
position: absolute;
top: 50%;
right: 46px;
cursor: pointer;
.icon {
width: 96px;
height: 96px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
text-align: center;
}
}
.ai-dialog {
position: absolute;
right: 100px;
top: 50px;
z-index: 9999;
}
} }
.el-header { .el-header {
padding: 0; padding: 0;
height: 60px; height: 96px;
position: relative;
z-index: 1;
} }
.el-main { .el-main {
padding: 0; padding: 0;
height: calc(100vh - 60px); height: calc(100vh - 96px);
background-color: rgba(246, 251, 255, 1); background-color: rgba(246, 251, 255, 1);
overflow-y: auto;
} }
</style> </style>
...@@ -7,7 +7,7 @@ import request from "@/api/request.js"; ...@@ -7,7 +7,7 @@ import request from "@/api/request.js";
export function getBillInfo(params) { export function getBillInfo(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billInfoBean/info/${params.id}`, url: `/api/billInfoBean/info/${params.id}`,
params, params,
}) })
} }
...@@ -20,7 +20,7 @@ export function getBillInfo(params) { ...@@ -20,7 +20,7 @@ export function getBillInfo(params) {
export function getBillPerson(params) { export function getBillPerson(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billInfoBean/person/${params.id}`, url: `/api/billInfoBean/person/${params.id}`,
params, params,
}) })
} }
...@@ -33,7 +33,7 @@ export function getBillPerson(params) { ...@@ -33,7 +33,7 @@ export function getBillPerson(params) {
export function getBillEvent(params) { export function getBillEvent(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billInfoBean/event/${params.id}`, url: `/api/billInfoBean/event/${params.id}`,
params, params,
}) })
} }
...@@ -46,7 +46,7 @@ export function getBillEvent(params) { ...@@ -46,7 +46,7 @@ export function getBillEvent(params) {
export function getBillDyqk(params) { export function getBillDyqk(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billInfoBean/dyqk/${params.id}`, url: `/api/billInfoBean/dyqk/${params.id}`,
params, params,
}) })
} }
...@@ -59,7 +59,7 @@ export function getBillDyqk(params) { ...@@ -59,7 +59,7 @@ export function getBillDyqk(params) {
export function getBillBackground(params) { export function getBillBackground(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billInfoBean/background/${params.id}`, url: `/api/billInfoBean/background/${params.id}`,
params, params,
}) })
} }
...@@ -72,7 +72,7 @@ export function getBillBackground(params) { ...@@ -72,7 +72,7 @@ export function getBillBackground(params) {
export function getBillPersonAnalyze(params) { export function getBillPersonAnalyze(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billInfoBean/personAnalyze/${params.id}`, url: `/api/billInfoBean/personAnalyze/${params.id}`,
params, params,
}) })
} }
...@@ -85,7 +85,7 @@ export function getBillPersonAnalyze(params) { ...@@ -85,7 +85,7 @@ export function getBillPersonAnalyze(params) {
export function getBillContentId(params) { export function getBillContentId(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billInfoBean/contentId/${params.id}`, url: `/api/billInfoBean/contentId/${params.id}`,
params, params,
}) })
} }
...@@ -98,7 +98,7 @@ export function getBillContentId(params) { ...@@ -98,7 +98,7 @@ export function getBillContentId(params) {
export function getBillContentTk(params) { export function getBillContentTk(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billInfoBean/content/tk/${params.id}`, url: `/api/billInfoBean/content/tk/${params.id}`,
params, params,
}) })
} }
...@@ -111,7 +111,7 @@ export function getBillContentTk(params) { ...@@ -111,7 +111,7 @@ export function getBillContentTk(params) {
export function getBillContentXzfs(params) { export function getBillContentXzfs(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billInfoBean/content/xzfs/${params.id}`, url: `/api/billInfoBean/content/xzfs/${params.id}`,
params, params,
}) })
} }
...@@ -124,7 +124,7 @@ export function getBillContentXzfs(params) { ...@@ -124,7 +124,7 @@ export function getBillContentXzfs(params) {
export function getBillHyly(params) { export function getBillHyly(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billInfoBean/content/hyly/${params.id}`, url: `/api/billInfoBean/content/hyly/${params.id}`,
params, params,
}) })
} }
\ No newline at end of file
import request from "@/api/chatRequest";
export function getChat(params) {
return request({
method: 'POST',
url: `/aichat/chat/chat/completions`,
data: params,
})
}
\ No newline at end of file
//引入axios请求
import axios from 'axios'
//引入element-plus里面的消息提示
import {
ElMessage
} from 'element-plus'
// Token管理
const TOKEN_KEY = 'auth_token'
// 获取token
const getToken = () => {
return 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw'
// return localStorage.getItem(TOKEN_KEY)
}
// 设置token
const setToken = (token) => {
localStorage.setItem(TOKEN_KEY, token)
}
// 移除token
const removeToken = () => {
localStorage.removeItem(TOKEN_KEY)
}
// 导出token管理方法
export { getToken, setToken, removeToken }
// const BASE_API = import.meta.env.VITE_BASE_API
// 创建axios实例
const service = axios.create({
// baseURL: BASE_API, //所有的后端接口请求地址前缀部分(没有后端请求不用写)
timeout: 60000*5 // 请求超时时间,这里15秒
//withCredentials: true,// 异步请求携带cookie,true为携带,false为不携带
//请求头里面设置通用传参类型
/*headers: {
//设置后端需要的传参类型
'Content-Type': 'application/json',
'token': 'x-auth-token',//一开始就要token
'X-Requested-With': 'XMLHttpRequest',
}*/
})
// request拦截器
service.interceptors.request.use(config => {
// 获取token并添加到请求头
// const token = getToken()
// if (token) {
// // 根据curl命令,后端接受的是token字段名,而不是Authorization
// config.headers['token'] = token
// // config.headers['Authorization'] = `Bearer ${token}` // 如果后端需要Bearer格式可以使用这个
// }
return config
}, error => {
console.log(error)
return Promise.reject(error)
})
// response拦截器
service.interceptors.response.use(
response => {
//对数据返回做什么
if (response.data.code == 0) {
ElMessage({
message: response.data.message,
type: 'error',
duration: 3 * 1000
})
}
return response.data
},
error => {
console.log('err' + error)
// 处理token过期或无效的情况
if (error.response && (error.response.status === 401 || error.response.status === 403)) {
ElMessage({
message: 'Token已过期,请重新登录',
type: 'error',
duration: 3 * 1000
})
// 清除无效的token
removeToken()
// 可以在这里跳转到登录页
// router.push('/login')
} else {
ElMessage({
message: error.message,
type: 'error',
duration: 3 * 1000
})
}
return Promise.reject(error)
}
)
export default service
\ No newline at end of file
...@@ -7,7 +7,7 @@ import request from "@/api/request.js"; ...@@ -7,7 +7,7 @@ import request from "@/api/request.js";
export function getBillTimeAnalyze(params) { export function getBillTimeAnalyze(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billDeepDive/processAnalyze/time/${params.id}`, url: `/api/billDeepDive/processAnalyze/time/${params.id}`,
params, params,
}) })
} }
...@@ -19,7 +19,7 @@ export function getBillTimeAnalyze(params) { ...@@ -19,7 +19,7 @@ export function getBillTimeAnalyze(params) {
export function getBillTotalXj(params) { export function getBillTotalXj(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billDeepDive/processAnalyze/totalxj/${params.id}`, url: `/api/billDeepDive/processAnalyze/totalxj/${params.id}`,
params, params,
}) })
} }
...@@ -31,7 +31,7 @@ export function getBillTotalXj(params) { ...@@ -31,7 +31,7 @@ export function getBillTotalXj(params) {
export function getBillTp(params) { export function getBillTp(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billDeepDive/processAnalyze/tp/${params.id}`, url: `/api/billDeepDive/processAnalyze/tp/${params.id}`,
params, params,
}) })
} }
...@@ -43,7 +43,7 @@ export function getBillTp(params) { ...@@ -43,7 +43,7 @@ export function getBillTp(params) {
export function getBillXj(params) { export function getBillXj(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billDeepDive/processAnalyze/xj/${params.id}`, url: `/api/billDeepDive/processAnalyze/xj/${params.id}`,
params, params,
}) })
} }
...@@ -55,7 +55,7 @@ export function getBillXj(params) { ...@@ -55,7 +55,7 @@ export function getBillXj(params) {
export function getProcessSummaryDetail(params) { export function getProcessSummaryDetail(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billDeepDive/processSummary/detail/${params.id}`, url: `/api/billDeepDive/processSummary/detail/${params.id}`,
params, params,
}) })
} }
...@@ -67,7 +67,7 @@ export function getProcessSummaryDetail(params) { ...@@ -67,7 +67,7 @@ export function getProcessSummaryDetail(params) {
export function getProcessSummaryTk(params) { export function getProcessSummaryTk(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billDeepDive/processSummary/tk/${params.id}`, url: `/api/billDeepDive/processSummary/tk/${params.id}`,
params, params,
}) })
} }
...@@ -79,7 +79,7 @@ export function getProcessSummaryTk(params) { ...@@ -79,7 +79,7 @@ export function getProcessSummaryTk(params) {
export function getProcessSummary(params) { export function getProcessSummary(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billDeepDive/processSummary/${params.id}`, url: `/api/billDeepDive/processSummary/${params.id}`,
params, params,
}) })
} }
\ No newline at end of file
...@@ -4,7 +4,7 @@ import request from "@/api/request.js"; ...@@ -4,7 +4,7 @@ import request from "@/api/request.js";
export function getHotBills() { export function getHotBills() {
return request({ return request({
method: 'GET', method: 'GET',
url: '/BillOverview/hotBills', url: '/api/BillOverview/hotBills',
}) })
} }
...@@ -15,7 +15,7 @@ export function getHotBills() { ...@@ -15,7 +15,7 @@ export function getHotBills() {
export function getBillsByType(params) { export function getBillsByType(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: '/BillOverview/bills', url: '/api/BillOverview/bills',
params, params,
}) })
} }
...@@ -24,6 +24,6 @@ export function getBillsByType(params) { ...@@ -24,6 +24,6 @@ export function getBillsByType(params) {
export function getHylyList() { export function getHylyList() {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billImpactAnalysis/industry/hylyList`, url: `/api/billImpactAnalysis/industry/hylyList`,
}) })
} }
\ No newline at end of file
...@@ -7,7 +7,7 @@ import request from "@/api/request.js"; ...@@ -7,7 +7,7 @@ import request from "@/api/request.js";
export function getCompanyList(params) { export function getCompanyList(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billImpactAnalysis/industry/company/${params.id}`, url: `/api/billImpactAnalysis/industry/company/${params.id}`,
params, params,
}) })
} }
...@@ -19,7 +19,7 @@ export function getCompanyList(params) { ...@@ -19,7 +19,7 @@ export function getCompanyList(params) {
export function getIndustryHyly(params) { export function getIndustryHyly(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billImpactAnalysis/industry/hyly/${params.id}`, url: `/api/billImpactAnalysis/industry/hyly/${params.id}`,
params, params,
}) })
} }
...@@ -28,6 +28,6 @@ export function getIndustryHyly(params) { ...@@ -28,6 +28,6 @@ export function getIndustryHyly(params) {
export function getHylyList() { export function getHylyList() {
return request({ return request({
method: 'GET', method: 'GET',
url: `/billImpactAnalysis/industry/hylyList`, url: `/api/billImpactAnalysis/industry/hylyList`,
}) })
} }
\ No newline at end of file
...@@ -27,10 +27,10 @@ const removeToken = () => { ...@@ -27,10 +27,10 @@ const removeToken = () => {
// 导出token管理方法 // 导出token管理方法
export { getToken, setToken, removeToken } export { getToken, setToken, removeToken }
const BASE_API = import.meta.env.VITE_BASE_API // const BASE_API = import.meta.env.VITE_BASE_API
// 创建axios实例 // 创建axios实例
const service = axios.create({ const service = axios.create({
baseURL: BASE_API, //所有的后端接口请求地址前缀部分(没有后端请求不用写) // baseURL: BASE_API, //所有的后端接口请求地址前缀部分(没有后端请求不用写)
timeout: 60000*5 // 请求超时时间,这里15秒 timeout: 60000*5 // 请求超时时间,这里15秒
//withCredentials: true,// 异步请求携带cookie,true为携带,false为不携带 //withCredentials: true,// 异步请求携带cookie,true为携带,false为不携带
//请求头里面设置通用传参类型 //请求头里面设置通用传参类型
......
<template>
<div class="ai-wrapper">
<div class="header">
<div class="icon">
<img src="@/assets/icons/aiBox/ai-bg.png" alt="" />
<div class="inner-icon">
<img src="@/assets/icons/aiBox/ai-logo.png" alt="" />
</div>
</div>
<div class="title">智能问答</div>
<div class="close" @click="handleClose">
<img src="@/assets/icons/aiBox/close.png" alt="" />
</div>
</div>
<div class="main">
<div class="chat-content" ref="contentContainer">
<!-- 消息列表 -->
<div class="message-list">
<div v-for="(message, index) in messages" :key="index" :class="['message-item', message.type]">
<!-- AI 消息 -->
<div v-if="message.type === 'ai'" class="message ai-message">
<div class="avatar">AI</div>
<div class="bubble">
<div class="content markdown-content" v-html="renderMarkdown(message.content)"></div>
</div>
</div>
<!-- 用户消息 -->
<div v-else class="message user-message">
<div class="bubble">
<div class="content">{{ message.content }}</div>
</div>
<div class="avatar"></div>
</div>
</div>
<!-- 加载状态 -->
<div v-if="isLoading" class="message-item ai">
<div class="message ai-message">
<div class="avatar">AI</div>
<div class="bubble">
<div class="loading-indicator">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer">
<el-input type="textarea" :rows="3" v-model="userInput" placeholder="请输入问题开启智能问答" />
<div class="btn">
<div class="icon">
<img src="@/assets/icons/aiBox/idea.png" alt="" />
</div>
<div class="text">概括页面内容</div>
</div>
<div class="submit" @click="sendMessage">
<img src="@/assets/icons/aiBox/submit.png" alt="" />
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, nextTick, onMounted, onUnmounted } from "vue";
import { fetchEventSource } from "@microsoft/fetch-event-source";
import MarkdownIt from "markdown-it";
import { ElMessage } from "element-plus";
import { getChat } from "@/api/chat";
const contentContainer = ref(null);
const userInput = ref("");
const isLoading = ref(false);
const abortController = ref(null);
// 消息数据
const messages = ref([
{
type: "user",
content: "你好"
},
{
type: "ai",
content: "您好!我是AI助手,有什么可以帮助您的吗?"
}
]);
// Markdown 渲染器
const md = new MarkdownIt();
// 渲染 markdown
const renderMarkdown = content => {
return md.render(content);
};
// 自动滚动到底部
const scrollToBottom = async () => {
await nextTick();
if (contentContainer.value) {
const container = contentContainer.value;
container.scrollTop = container.scrollHeight;
}
};
// 添加消息
const addMessage = (type, content) => {
messages.value.push({
type,
content,
timestamp: new Date().getTime()
});
scrollToBottom();
};
// 更新最后一条 AI 消息(用于流式输出)
const updateLastAIMessage = content => {
const lastMessage = messages.value[messages.value.length - 1];
if (lastMessage && lastMessage.type === "ai") {
lastMessage.content = content;
scrollToBottom();
}
};
// 使用 fetchEventSource 连接
const connectSSE = async question => {
// 添加用户消息
addMessage("user", question);
// 添加空的 AI 消息用于流式更新
addMessage("ai", "");
isLoading.value = true;
// 创建 AbortController 用于取消请求
abortController.value = new AbortController();
const params = {
query: "如何检索?",
knowledge_base_name: "kb_test251112",
top_k: 6,
score_threshold: 0.5,
metadata: { year: 2024 }
};
try {
await fetchEventSource("/chat/knowledge_base/search_docs", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params),
signal: abortController.value.signal,
onopen: async response => {
console.log("SSE 连接已建立", response.status);
if (response.status !== 200) {
throw new Error(`请求失败: ${response.status}`);
}
},
onmessage: event => {
try {
if (event.data === "[DONE]") {
// 流式输出结束
isLoading.value = false;
return;
}
const data = JSON.parse(event.data);
if (data.type === "content" && data.content) {
// 流式更新内容
updateLastAIMessage(prev => prev + data.content);
} else if (data.type === "error") {
throw new Error(data.message || "请求失败");
}
} catch (error) {
console.error("解析 SSE 数据错误:", error);
}
},
onclose: () => {
console.log("SSE 连接已关闭");
isLoading.value = false;
},
onerror: error => {
console.error("SSE 连接错误:", error);
ElMessage.error("连接失败,请重试");
isLoading.value = false;
// 不要抛出错误,否则会重试
}
});
} catch (error) {
console.error("SSE 请求失败:", error);
if (error.name !== "AbortError") {
ElMessage.error(error.message || "请求失败");
}
isLoading.value = false;
}
};
const chat = async () => {
const params = {
query: "如何检索?",
knowledge_base_name: "kb_test251112",
top_k: 6,
score_threshold: 0.5,
metadata: { year: 2024 }
};
try {
const res = await getChat(params);
console.log("chat", res);
} catch (error) {
console.error(error);
}
};
// 发送消息
const sendMessage = async () => {
const question = userInput.value.trim();
if (!question) {
ElMessage.warning("请输入问题");
return;
}
if (isLoading.value) {
ElMessage.warning("请等待上一条消息回复完成");
return;
}
userInput.value = "";
// await connectSSE(question);
chat();
};
// 停止生成
const stopGenerate = () => {
if (abortController.value) {
abortController.value.abort();
abortController.value = null;
isLoading.value = false;
ElMessage.info("已停止生成");
}
};
const emit = defineEmits(["close"]);
const handleClose = () => {
emit("close");
};
onMounted(() => {
scrollToBottom();
});
onUnmounted(() => {
if (abortController.value) {
abortController.value.abort();
}
});
</script>
<style lang="scss" scoped>
.ai-wrapper {
width: 548px;
height: 1048px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
background: rgba(255, 255, 255, 1);
.header {
position: relative;
display: flex;
height: 50px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
.icon {
width: 30px;
height: 28px;
margin-top: 11px;
margin-left: 14px;
position: relative;
img {
width: 100%;
height: 100%;
}
.inner-icon {
position: absolute;
top: 3px;
left: 6px;
width: 15px;
height: 11px;
img {
width: 100%;
height: 100%;
}
}
}
.title {
margin-top: 10px;
margin-left: 12px;
height: 30px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 30px;
}
.close {
position: absolute;
right: 22px;
top: 21px;
width: 12px;
height: 12px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
}
.main {
height: 830px;
// background: rgba(225, 225, 225, 0.5);
width: 520px;
margin: 10px auto;
overflow-x: hidden;
overflow-y: auto;
}
.footer {
position: absolute;
left: 22px;
bottom: 20px;
width: 504px;
height: 120px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
overflow: hidden;
.btn {
position: absolute;
left: 20px;
bottom: 15px;
width: 160px;
height: 36px;
box-sizing: border-box;
border: 1px solid rgba(5, 95, 194, 1);
border-radius: 18px;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
.icon {
width: 14px;
height: 14px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 30px;
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
}
}
.submit {
position: absolute;
right: 19px;
bottom: 15px;
width: 36px;
height: 36px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
}
}
:deep(.el-textarea__inner) {
border: none;
/* 去掉右下角斜线(调整 resize) */
resize: none;
/* 去掉焦点边框 */
outline: none;
box-shadow: none;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
}
:deep(.el-textarea__inner::placeholder) {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
}
/* 确保获得焦点时也没有边框 */
:deep(.el-textarea__inner:focus) {
border: none;
outline: none;
box-shadow: none;
}
/* 确保获得焦点时也没有边框 */
:deep(.el-textarea__inner:hover) {
border: none;
outline: none;
box-shadow: none;
}
/* 对话内容区域 */
.chat-content {
flex: 1;
overflow-y: auto;
padding: 20px;
background: #fff;
}
.message-list {
max-width: 900px;
margin: 0 auto;
}
.message-item {
margin-bottom: 24px;
}
.message {
display: flex;
align-items: flex-start;
gap: 12px;
max-width: 100%;
}
.user-message {
justify-content: flex-end;
}
.ai-message {
justify-content: flex-start;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 600;
flex-shrink: 0;
}
.user-message .avatar {
background: #409eff;
color: white;
order: 2;
}
.ai-message .avatar {
background: #8ac4ff;
color: white;
}
.bubble {
max-width: 100%;
padding: 10px 12px;
border-radius: 12px;
position: relative;
}
.user-message .bubble {
background: rgba(231, 243, 255, 1);
color: white;
border-radius: 20px 0 20px 20px;
}
.ai-message .bubble {
background: #f0f2f5;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
border-radius: 0 20px 20px 20px;
}
.content {
line-height: 1.6;
word-wrap: break-word;
}
.user-message .content {
color: rgba(5, 95, 194, 1);
}
/* Markdown 内容样式 */
.markdown-content :deep(h1) {
font-size: 1.4em;
margin: 0.8em 0 0.4em 0;
font-weight: 600;
}
.markdown-content :deep(h2) {
font-size: 1.2em;
margin: 0.8em 0 0.4em 0;
font-weight: 600;
}
.markdown-content :deep(h3) {
font-size: 1.1em;
margin: 0.8em 0 0.4em 0;
font-weight: 600;
}
.markdown-content :deep(p) {
margin: 0.4em 0;
}
.markdown-content :deep(code) {
background: rgba(175, 184, 193, 0.2);
padding: 0.2em 0.4em;
border-radius: 3px;
font-size: 0.9em;
font-family: "SFMono-Regular", Consolas, monospace;
}
.markdown-content :deep(pre) {
background: #f6f8fa;
padding: 12px;
border-radius: 6px;
overflow: auto;
margin: 1em 0;
}
.markdown-content :deep(pre code) {
background: none;
padding: 0;
}
.markdown-content :deep(blockquote) {
border-left: 4px solid #dfe2e5;
padding-left: 16px;
margin: 1em 0;
color: #6a737d;
}
.markdown-content :deep(ul),
.markdown-content :deep(ol) {
padding-left: 2em;
margin: 1em 0;
}
/* 加载指示器 */
.loading-indicator {
display: flex;
gap: 4px;
padding: 8px 0;
}
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #999;
animation: bounce 1.4s infinite ease-in-out;
}
.dot:nth-child(1) {
animation-delay: -0.32s;
}
.dot:nth-child(2) {
animation-delay: -0.16s;
}
@keyframes bounce {
0%,
80%,
100% {
transform: scale(0.8);
opacity: 0.5;
}
40% {
transform: scale(1);
opacity: 1;
}
}
/* 滚动条样式 */
.chat-content::-webkit-scrollbar {
width: 6px;
}
.chat-content::-webkit-scrollbar-track {
background: #f1f1f1;
}
.chat-content::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.chat-content::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
</style>
\ No newline at end of file
<template>
<div class="header-wrapper">
<div class="icon"></div>
<div class="title"></div>
<div class="btn-box"></div>
</div>
</template>
\ No newline at end of file
// composables/useMarkdownStream.js
import { ref, computed, nextTick } from 'vue'
import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'
// 引入 highlight.js 样式
import 'highlight.js/styles/github.css'
import mdKatex from '@traptitech/markdown-it-katex'
export function useMarkdownStream() {
const rawContent = ref('')
const createMd = () => {
const md = new MarkdownIt(
{
html: true,
breaks: true, // 将换行符转换为 <br>
linkify: true, // 自动链接 URL
typographer: true, // 启用排版扩展
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return '<pre class="hljs" style="fontSize:14px"><code class="language-' + lang + '">' +
hljs.highlight(str, {
language: lang,
ignoreIllegals: true
}).value +
'</code></pre>'
} catch (err) {
console.warn(`代码高亮错误 (${lang}):`, err)
}
}
// 默认处理
return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>'
}
}
)
// 自定义代码块渲染规则
md.renderer.rules.fence = (tokens, idx, options, env, self) => {
const token = tokens[idx]
const lang = token.info.trim()
const code = token.content
// 使用 highlight.js 进行高亮
if (lang && hljs.getLanguage(lang)) {
try {
const highlighted = hljs.highlight(code, {
language: lang,
ignoreIllegals: true
})
return `
<div class="code-block-wrapper">
<div class="code-header">
<span class="code-lang">${lang}</span>
</div>
<pre class="hljs"><code class="language-${lang}">${highlighted.value}</code></pre>
</div>
`
} catch (err) {
console.warn(`代码高亮错误 (${lang}):`, err)
}
}
// 默认代码块
return `
<div class="code-block-wrapper">
<div class="code-header">
<span class="code-lang">${lang || 'text'}</span>
<button class="copy-btn" onclick="copyCode(this)">复制</button>
</div>
<pre class="hljs"><code>${md.utils.escapeHtml(code)}</code></pre>
</div>
`
}
// md.use(mila, { attrs: { target: '_blank', rel: 'noopener' } })
// md.use(mdKatex, { blockClass: 'katexmath-block rounded-md p-[10px]', errorColor: ' #cc0000' })
// // 自定义渲染规则 - 修复中文排版
// md.renderer.rules.paragraph_open = (tokens, idx, options, env, self) => {
// return '<p style="margin: 1em 0; line-height: 1.6;">'
// }
// md.renderer.rules.heading_open = (tokens, idx, options, env, self) => {
// const token = tokens[idx]
// const level = token.tag.slice(1)
// const styles = {
// '1': 'font-size: 1.8em; margin: 1.2em 0 0.6em 0; font-weight: 700; border-bottom: 1px solid #eaecef; padding-bottom: 0.3em;',
// '2': 'font-size: 1.5em; margin: 1.2em 0 0.6em 0; font-weight: 600; border-bottom: 1px solid #eaecef; padding-bottom: 0.3em;',
// '3': 'font-size: 1.3em; margin: 1.2em 0 0.6em 0; font-weight: 600;',
// '4': 'font-size: 1.2em; margin: 1.2em 0 0.6em 0; font-weight: 600;',
// '5': 'font-size: 1.1em; margin: 1.2em 0 0.6em 0; font-weight: 600;',
// '6': 'font-size: 1em; margin: 1.2em 0 0.6em 0; font-weight: 600; color: #666;'
// }
// return `<${token.tag} style="${styles[level] || ''}">`
// }
// md.renderer.rules.list_item_open = (tokens, idx, options, env, self) => {
// return '<li style="margin: 0.5em 0; line-height: 1.6;">'
// }
// md.renderer.rules.table_open = (tokens, idx, options, env, self) => {
// return '<table style="border-collapse: collapse; width: 100%; margin: 1em 0; border: 1px solid #dfe2e5;">'
// }
// md.renderer.rules.th_open = (tokens, idx, options, env, self) => {
// return '<th style="border: 1px solid #dfe2e5; padding: 8px 12px; background: #f6f8fa; font-weight: 600; text-align: left;">'
// }
// md.renderer.rules.td_open = (tokens, idx, options, env, self) => {
// return '<td style="border: 1px solid #dfe2e5; padding: 8px 12px;">'
// }
// md.renderer.rules.blockquote_open = (tokens, idx, options, env, self) => {
// return '<blockquote style="border-left: 4px solid #dfe2e5; margin: 1em 0; padding-left: 1em; color: #666; background: #f8f9fa; padding: 12px 16px 12px 20px; border-radius: 4px;">'
// }
// md.renderer.rules.code_inline = (tokens, idx, options, env, self) => {
// const token = tokens[idx]
// return `<code style="background: #f6f8fa; padding: 2px 6px; border-radius: 3px; font-size: 0.9em; font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; color: #e74c3c;">${md.utils.escapeHtml(token.content)}</code>`
// }
// // 链接处理
// md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
// const token = tokens[idx]
// const hrefIndex = token.attrIndex('href')
// if (hrefIndex >= 0) {
// const href = token.attrs[hrefIndex][1]
// token.attrPush(['target', '_blank'])
// token.attrPush(['rel', 'noopener noreferrer'])
// token.attrPush(['style', 'color: #1890ff; text-decoration: none;'])
// }
// return self.renderToken(tokens, idx, options)
// }
// 预处理:修复带空格的强调符号
// const originalParse = md.parse.bind(md)
// md.parse = function (src, env) {
// // 预处理:修复 **文本 ** 这种带空格的粗体
// let processedSrc = src
// // 修复 **文本 ** -> **文本**
// .replace(/\*\*([^*]+?)\s+\*\*/g, '**$1**')
// // // 修复 __文本 __ -> __文本__
// // .replace(/__([^_]+?)\s+__/g, '__$1__')
// // // 修复 *文本 * -> *文本*
// // .replace(/\*([^*]+?)\s+\*/g, '*$1*')
// // // 修复 _文本 _ -> _文本_
// // .replace(/_([^_]+?)\s+_/g, '_$1_')
// return originalParse(processedSrc, env)
// }
// // 自定义渲染规则 - 支持所有 Markdown 格式
// md.renderer.rules.strong_open = () => '<strong style="font-weight: 600;">'
// md.renderer.rules.em_open = () => '<em style="font-style: italic;">'
// md.renderer.rules.heading_open = (tokens, idx) => {
// const token = tokens[idx]
// const level = token.tag.slice(1)
// const styles = {
// '1': 'font-size: 2em; margin: 0.67em 0; font-weight: 700; border-bottom: 2px solid #eaecef; padding-bottom: 0.3em;',
// '2': 'font-size: 1.5em; margin: 0.83em 0; font-weight: 600; border-bottom: 1px solid #eaecef; padding-bottom: 0.3em;',
// '3': 'font-size: 1.17em; margin: 1em 0; font-weight: 600;',
// '4': 'font-size: 1em; margin: 1.33em 0; font-weight: 600;',
// '5': 'font-size: 0.83em; margin: 1.67em 0; font-weight: 600;',
// '6': 'font-size: 0.67em; margin: 2.33em 0; font-weight: 600; color: #666;'
// }
// return `<${token.tag} style="${styles[level] || ''}">`
// }
// md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
// const token = tokens[idx]
// const hrefIndex = token.attrIndex('href')
// if (hrefIndex >= 0) {
// token.attrPush(['target', '_blank'])
// token.attrPush(['rel', 'noopener noreferrer'])
// token.attrPush(['style', 'color: #1890ff; text-decoration: none;'])
// }
// return self.renderToken(tokens, idx, options)
// }
// md.renderer.rules.blockquote_open = () =>
// '<blockquote style="border-left: 4px solid #dfe2e5; margin: 1em 0; padding: 0.5em 1em; background: #f8f9fa; border-radius: 4px;">'
// md.renderer.rules.code_inline = (tokens, idx) => {
// const token = tokens[idx]
// return `<code style="background: #f3f4f6; padding: 0.2em 0.4em; border-radius: 3px; font-family: 'SFMono-Regular', Consolas, monospace; font-size: 0.9em; color: #e53e3e;">${md.utils.escapeHtml(token.content)}</code>`
// }
// 自定义表格渲染规则
md.renderer.rules.table_open = () =>
'<div class="table-container"><table style="border-collapse: collapse; width: 100%; margin: 1em 0; border: 1px solid #dfe2e5;background: rgb(239 241 243); border-radius: 5px">'
md.renderer.rules.table_close = () => '</table></div>'
md.renderer.rules.thead_open = () => '<thead style="background: #e6e7e8">'
md.renderer.rules.th_open = () =>
'<th style="border: 1px solid #dfe2e5; padding: 12px; text-align: left; font-weight: 600;">'
md.renderer.rules.td_open = () =>
'<td style="border: 1px solid #dfe2e5; padding: 12px; text-align: left; vertical-align: top;">'
md.renderer.rules.th_close = () => '</th>'
md.renderer.rules.td_close = () => '</td>'
md.renderer.rules.tr_open = () => '<tr>'
md.renderer.rules.tr_close = () => '</tr>'
md.renderer.rules.thead_close = () => '</thead>'
md.renderer.rules.tbody_open = () => '<tbody>'
md.renderer.rules.tbody_close = () => '</tbody>'
return md
}
function preprocessMarkdown(content) {
if (!content) return ''
return content
// 1. 修复带空格的强调符号
.replace(/\*\*(\S.*?\S?)\s*\*\*/g, '**$1**')
.replace(/\*(\S.*?\S?)\s*\*/g, '*$1*')
.replace(/__(\S.*?\S?)\s*__/g, '__$1__')
.replace(/_(\S.*?\S?)\s*_/g, '_$1_')
// 2. 修复不配对的符号
.replace(/(\S)\*\*(\S)/g, '$1 **$2') // 文本**文本 -> 文本 **文本
.replace(/(\S)\*(\S)/g, '$1 *$2') // 文本*文本 -> 文本 *文本
// 3. 处理流式输出中的不完整标记
.replace(/\*\*([^*]*)$/, '**$1**') // 补全未闭合的粗体
.replace(/\*([^*]*)$/, '*$1*') // 补全未闭合的斜体
.replace(/__([^_]*)$/, '__$1__') // 补全未闭合的粗体(下划线)
.replace(/_([^_]*)$/, '_$1_') // 补全未闭合的斜体(下划线)
// 4. 统一换行符
.replace(/\\n/g, '\n')
.replace(/\r\n/g, '\n')
}
// 渲染 markdown
const renderedContent = computed(() => {
const md = createMd()
// 预处理内容
// const processedContent = preprocessMarkdown(rawContent.value)
return md.render(rawContent.value)
})
// 自动滚动
const scrollToBottom = async (scrollContainer) => {
await nextTick()
if (scrollContainer) {
scrollContainer.scrollTop = scrollContainer.scrollHeight
}
}
// 更新内容并滚动
const updateContent = async (newContent, scrollContainer) => {
rawContent.value = newContent
await scrollToBottom(scrollContainer)
}
// 清空内容
const clearContent = () => {
rawContent.value = ''
}
return {
rawContent,
renderedContent,
updateContent,
clearContent
}
}
\ No newline at end of file
import { ref, onMounted, onUnmounted } from 'vue'
export function useContainerScroll(containerRef, options = {}) {
const {
scrollThreshold = 0,
showOnScrollDown = true,
hideOnTop = true,
useAnimationFrame = true
} = options
const isShow = ref(false)
const lastScrollTop = ref(0)
const ticking = ref(false)
const updateShowState = () => {
const container = containerRef.value
if (!container) return
const currentScrollTop = container.scrollTop
if (showOnScrollDown && currentScrollTop > lastScrollTop.value && currentScrollTop > scrollThreshold) {
isShow.value = true
}
if (hideOnTop && currentScrollTop === 0) {
isShow.value = false
}
lastScrollTop.value = currentScrollTop
ticking.value = false
}
const handleScroll = () => {
if (useAnimationFrame) {
if (!ticking.value) {
requestAnimationFrame(updateShowState)
ticking.value = true
}
} else {
updateShowState()
}
}
onMounted(() => {
const container = containerRef.value
if (container) {
container.addEventListener('scroll', handleScroll, { passive: true })
}
})
onUnmounted(() => {
const container = containerRef.value
if (container) {
container.removeEventListener('scroll', handleScroll)
}
})
return {
isShow
}
}
\ No newline at end of file
import { createRouter, createWebHistory } from "vue-router"; import { createRouter, createWebHistory } from "vue-router";
//中美博弈概览
import overView from '@/views/overView/index.vue'
// 智库相关 // 智库相关
import thinkTank from "../views/thinkTank/index.vue"; import thinkTank from "../views/thinkTank/index.vue";
import ThinkTankDetail from "@/views/thinkTank/ThinkTankDetail/index.vue"; import ThinkTankDetail from "@/views/thinkTank/ThinkTankDetail/index.vue";
...@@ -15,7 +17,7 @@ import BillTemplate from '@/views/bill/template/index.vue' ...@@ -15,7 +17,7 @@ import BillTemplate from '@/views/bill/template/index.vue'
import BillDeepDigLayout from '@/views/bill/deepDig/index.vue' import BillDeepDigLayout from '@/views/bill/deepDig/index.vue'
import BillDeepDigProcessOverview from '@/views/bill/deepDig/processOverview/index.vue' import BillDeepDigProcessOverview from '@/views/bill/deepDig/processOverview/index.vue'
import BillDeepDigProcessAnalysis from '@/views/bill/deepDig/processAnalysis/index.vue' import BillDeepDigProcessAnalysis from '@/views/bill/deepDig/processAnalysis/index.vue'
import BillDeepDigProgressOverview from '@/views/bill/deepDig/progressAnalysis/index.vue' import BillDeepDigPoliContribution from '@/views/bill/deepDig/poliContribution/index.vue'
import BillInfluenceLayout from '@/views/bill/influence/index.vue' import BillInfluenceLayout from '@/views/bill/influence/index.vue'
import BillInfluenceIndustry from '@/views/bill/influence/industry/index.vue' import BillInfluenceIndustry from '@/views/bill/influence/industry/index.vue'
import BillInfluenceScientificResearch from '@/views/bill/influence/scientificResearch/index.vue' import BillInfluenceScientificResearch from '@/views/bill/influence/scientificResearch/index.vue'
...@@ -42,13 +44,39 @@ import MarketSingleCaseLayout from "@/views/marketAccessRestrictions/singleCaseL ...@@ -42,13 +44,39 @@ import MarketSingleCaseLayout from "@/views/marketAccessRestrictions/singleCaseL
import MarketSingleCaseOverview from "@/views/marketAccessRestrictions/singleCaseLayout/overview/index.vue"; import MarketSingleCaseOverview from "@/views/marketAccessRestrictions/singleCaseLayout/overview/index.vue";
import MarketSingleCaseDeepdig from "@/views/marketAccessRestrictions/singleCaseLayout/deepdig/index.vue"; import MarketSingleCaseDeepdig from "@/views/marketAccessRestrictions/singleCaseLayout/deepdig/index.vue";
// 智能写报
import WrittingAsstaint from '@/views/writtingAsstaint/index.vue'
// 门户
import Portal1 from '@/views/portals/portal1/index.vue';
import Portal2 from '@/views/portals/portal2/index.vue';
const routes = [ const routes = [
// 智能写报
{
path: "/writtingAsstaint",
name: "writtingAsstaint",
component: WrittingAsstaint,
meta: {
title: "智能写报"
}
},
{ {
path: '/', path: '/',
redirect: '/billHome' redirect: '/billHome'
}, },
// 中美博弈概览页面路由
{
path: '/overView',
name: 'overView',
component: overView,
meta: {
title: '法案首页'
},
},
// 智库系统的主要路由 // 智库系统的主要路由
{ {
path: "/thinkTank", path: "/thinkTank",
...@@ -146,10 +174,10 @@ const routes = [ ...@@ -146,10 +174,10 @@ const routes = [
meta: { title: '流程分析' } meta: { title: '流程分析' }
}, },
{ {
path: 'progressAnalysis', path: 'poliContribution',
name: 'DeepDigProgressAnalysis', name: 'BillDeepDigPoliContribution',
component: BillDeepDigProgressOverview, component: BillDeepDigPoliContribution,
meta: { title: '进程分析' } meta: { title: '政治献金' }
}, },
] ]
}, },
...@@ -368,11 +396,25 @@ const routes = [ ...@@ -368,11 +396,25 @@ const routes = [
meta: { meta: {
title: "科研资助" title: "科研资助"
} }
} },
// 门户路由放在这块 // 门户路由放在这块
{
path: "/portal1",
name: "portal1",
component: Portal1,
meta: {
title: "门户1"
}
},
{
path: "/portal2",
name: "portal2",
component: Portal2,
meta: {
title: "门户2"
}
},
]; ];
......
// 绘制echarts图表
import * as echarts from 'echarts'
const setChart = (option, chartId) => {
let chartDom = document.getElementById(chartId);
chartDom.removeAttribute("_echarts_instance_");
let chart = echarts.init(chartDom);
chart.setOption(option);
return chart;
};
export default setChart
\ No newline at end of file
<template> <template>
<div class="home-wrapper"> <div class="home-wrapper">
<div class="home-header"> <div class="search-header" v-show="isShow">
<div class="home-main-header-center">
<el-input v-model="input" style="width: 680px; height: 100%" placeholder="搜索科技法案" />
<div class="search">
<div class="search-icon">
<img src="./assets/images/search-icon.png" alt="" />
</div>
<div class="search-text">搜索</div>
</div>
</div>
<div class="home-main-header-btn-box">
<div class="btn">
<div class="btn-text">{{ "最新动态" }}</div>
<div class="btn-icon">{{ ">" }}</div>
</div>
<div class="btn">
<div class="btn-text">{{ "资讯要闻" }}</div>
<div class="btn-icon">{{ ">" }}</div>
</div>
<div class="btn">
<div class="btn-text">{{ "统计概览" }}</div>
<div class="btn-icon">{{ ">" }}</div>
</div>
<div class="btn">
<div class="btn-text">{{ "资源库" }}</div>
<div class="btn-icon">{{ ">" }}</div>
</div>
</div>
</div>
<div class="home-box" :class="{ scrollHomeBox: isShow }" ref="containerRef">
<div class="home-header" v-show="!isShow">
<span>国家科技安全 </span>> <span>中美博弈概览 </span>> <span>国家科技安全 </span>> <span>中美博弈概览 </span>>
<span>科技法案 </span> <span>科技法案 </span>
</div> </div>
<div class="home-main"> <div class="home-main">
<div class="home-main-header"> <div class="home-main-header" v-show="!isShow">
<div class="home-main-header-center"> <div class="home-main-header-center">
<el-input v-model="input" style="width: 800px; height: 100%" placeholder="搜索科技法案" /> <el-input v-model="input" style="width: 800px; height: 100%" placeholder="搜索科技法案" />
<div class="search"> <div class="search">
...@@ -158,7 +188,6 @@ ...@@ -158,7 +188,6 @@
<div class="text">{{ "风险信号" }}</div> <div class="text">{{ "风险信号" }}</div>
<div class="num">{{ warningList.length }}</div> <div class="num">{{ warningList.length }}</div>
</div> </div>
<div class="more">{{ "更多 +" }}</div>
</div> </div>
<div class="box2-main"> <div class="box2-main">
<div class="box2-main-item" v-for="(item, index) in warningList" :key="index"> <div class="box2-main-item" v-for="(item, index) in warningList" :key="index">
...@@ -196,6 +225,7 @@ ...@@ -196,6 +225,7 @@
<img src="./assets/images/box3-header-icon.png" alt="" /> <img src="./assets/images/box3-header-icon.png" alt="" />
</div> </div>
<div class="box3-header-title">{{ "新闻资讯" }}</div> <div class="box3-header-title">{{ "新闻资讯" }}</div>
<div class="more">{{ "更多 +" }}</div>
</div> </div>
</div> </div>
<div class="box3-main"> <div class="box3-main">
...@@ -219,6 +249,7 @@ ...@@ -219,6 +249,7 @@
<img src="./assets/images/box4-header-icon.png" alt="" /> <img src="./assets/images/box4-header-icon.png" alt="" />
</div> </div>
<div class="header-title">{{ "社交媒体" }}</div> <div class="header-title">{{ "社交媒体" }}</div>
<div class="more">{{ "更多 +" }}</div>
</div> </div>
<div class="box4-main"> <div class="box4-main">
<div class="box4-main-item" v-for="(item, index) in messageList" :key="index"> <div class="box4-main-item" v-for="(item, index) in messageList" :key="index">
...@@ -237,7 +268,6 @@ ...@@ -237,7 +268,6 @@
</div> </div>
</div> </div>
<DivideHeader class="divide3" :titleText="'统计概览'"></DivideHeader> <DivideHeader class="divide3" :titleText="'统计概览'"></DivideHeader>
<div class="center-footer"> <div class="center-footer">
<div class="box5"> <div class="box5">
<div class="box5-header"> <div class="box5-header">
...@@ -248,14 +278,10 @@ ...@@ -248,14 +278,10 @@
<div class="box5-header-title">{{ "涉华法案数量" }}</div> <div class="box5-header-title">{{ "涉华法案数量" }}</div>
</div> </div>
<div class="box5-header-right"> <div class="box5-header-right">
<div class="right-box"> <div class="header-right-icon">
<div class="icon1"></div> <img src="./assets/images/tips-icon.png" alt="" />
<div class="text">{{ "提出法案" }}</div>
</div>
<div class="right-box">
<div class="icon2"></div>
<div class="text">{{ "通过法案" }}</div>
</div> </div>
<div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div>
</div> </div>
</div> </div>
<div class="box5-main" id="chart1"></div> <div class="box5-main" id="chart1"></div>
...@@ -266,10 +292,118 @@ ...@@ -266,10 +292,118 @@
<img src="./assets/images/box6-header-icon.png" alt="" /> <img src="./assets/images/box6-header-icon.png" alt="" />
</div> </div>
<div class="header-title">{{ "关键条款" }}</div> <div class="header-title">{{ "关键条款" }}</div>
<div class="box6-header-right">
<div class="header-right-icon">
<img src="./assets/images/tips-icon.png" alt="" />
</div>
<div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div>
</div>
</div> </div>
<div class="box6-main" id="wordCloudChart"></div> <div class="box6-main" id="wordCloudChart"></div>
</div> </div>
</div> </div>
<div class="center-footer1">
<div class="box7">
<div class="box7-header">
<div class="box7-header-left">
<div class="box7-header-icon">
<img src="./assets/images/box7-header-icon.png" alt="" />
</div>
<div class="box7-header-title">{{ "法案提出部门" }}</div>
</div>
<div class="box7-header-right">
<div class="header-right-icon">
<img src="./assets/images/tips-icon.png" alt="" />
</div>
<div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div>
</div>
</div>
<div class="box-center">
<el-select v-model="box7selectetedTime" placeholder="选择时间" style="width: 90px">
<el-option
v-for="item in box7YearList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div class="box7-main" id="box7Chart"></div>
</div>
<div class="box8">
<div class="box8-header">
<div class="box8-header-left">
<div class="box8-header-icon">
<img src="./assets/images/box7-header-icon.png" alt="" />
</div>
<div class="box8-header-title">{{ "关键议员提案" }}</div>
</div>
<div class="box8-header-right">
<div class="header-right-icon">
<img src="./assets/images/tips-icon.png" alt="" />
</div>
<div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div>
</div>
</div>
<div class="box-center">
<el-select v-model="box8selectetedTime" placeholder="选择时间" style="width: 90px">
<el-option
v-for="item in box8YearList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div class="box8-main">
<div class="box8-main-item" v-for="(item, index) in box8Data" :key="index">
<div class="box8-main-item-left">
<img :src="item.img" alt="" />
<div class="left-icon1">
<img :src="item.dangpai" alt="" />
</div>
<div class="left-icon2">
<img :src="item.yuan" alt="" />
</div>
</div>
<div class="box8-main-item-center">
<div class="box8-main-item-center-top">{{ item.name }}</div>
<div class="box8-main-item-center-footer">{{ item.zhiwei }}</div>
</div>
<div class="box8-main-item-right">
{{ `${item.num}项提案 >` }}
</div>
</div>
</div>
</div>
<div class="box9">
<div class="box9-header">
<div class="box9-header-left">
<div class="box9-header-icon">
<img src="./assets/images/box7-header-icon.png" alt="" />
</div>
<div class="box9-header-title">{{ "涉华法案领域分布" }}</div>
</div>
<div class="box9-header-right">
<div class="header-right-icon">
<img src="./assets/images/tips-icon.png" alt="" />
</div>
<div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div>
</div>
</div>
<div class="box-center">
<el-select v-model="box9selectetedTime" placeholder="选择时间" style="width: 90px">
<el-option
v-for="item in box9YearList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div class="box9-main" id="box9Chart"></div>
</div>
</div>
</div> </div>
</div> </div>
<div class="home-main-footer"> <div class="home-main-footer">
...@@ -291,7 +425,12 @@ ...@@ -291,7 +425,12 @@
<div class="select-box"> <div class="select-box">
<el-select v-model="releaseTime" placeholder="选择发布时间" style="width: 120px"> <el-select v-model="releaseTime" placeholder="选择发布时间" style="width: 120px">
<el-option v-for="item in releaseTimeList" :key="item.value" :label="item.label" :value="item.value" /> <el-option
v-for="item in releaseTimeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<!-- <el-select <!-- <el-select
v-model="releaseTime" v-model="releaseTime"
...@@ -309,6 +448,33 @@ ...@@ -309,6 +448,33 @@
</div> </div>
<div class="home-main-footer-main"> <div class="home-main-footer-main">
<div class="main-item" v-for="(bill, index) in curBillList" :key="index"> <div class="main-item" v-for="(bill, index) in curBillList" :key="index">
<div
class="status-box"
:class="{
statusBox1: bill.status === '特别重大风险',
statusBox2: bill.status === '重大风险',
statusBox3: bill.status === '一般风险'
}"
>
<div
class="status-icon"
:class="{
statusIcon1: bill.status === '特别重大风险',
statusIcon2: bill.status === '重大风险',
statusIcon3: bill.status === '一般风险'
}"
></div>
<div
class="status-text"
:class="{
status1: bill.status === '特别重大风险',
status2: bill.status === '重大风险',
status3: bill.status === '一般风险'
}"
>
{{ bill.status }}
</div>
</div>
<div class="main-item-box1"> <div class="main-item-box1">
<img :src="bill.img" alt="" /> <img :src="bill.img" alt="" />
</div> </div>
...@@ -316,14 +482,29 @@ ...@@ -316,14 +482,29 @@
{{ bill.billName }} {{ bill.billName }}
</div> </div>
<div class="main-item-box3">{{ bill.introductionDate }}</div> <div class="main-item-box3">{{ bill.introductionDate }}</div>
<div class="main-item-box4">
<span>{{ bill.yuan }}</span
><span>{{ bill.dangpai }}</span>
</div>
<div class="main-item-box5">
<div class="tag" v-for="(tag, idx) in bill.tagList" :key="idx">{{ tag }}</div>
</div>
</div> </div>
</div> </div>
<div class="home-main-footer-footer"> <div class="home-main-footer-footer">
<div class="footer-left"> <div class="footer-left">
{{ `共${curBillList.length}项调查` }} {{ `共${billList.length}项调查` }}
</div> </div>
<div class="footer-right"> <div class="footer-right">
<el-pagination background layout="prev, pager, next" :total="curBillList.length" /> <el-pagination
@current-change="handleCurrentChange"
:pageSize="12"
:current-page="currentPage"
background
layout="prev, pager, next"
:total="billList.length"
/>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -331,13 +512,15 @@ ...@@ -331,13 +512,15 @@
</template> </template>
<script setup> <script setup>
import { onMounted, ref } from "vue"; import { onMounted, ref, computed } from "vue";
import * as echarts from "echarts"; import * as echarts from "echarts";
import router from "@/router/index"; import router from "@/router/index";
import { getHotBills, getBillsByType, getHylyList } from "@/api/home"; import { getHotBills, getBillsByType, getHylyList } from "@/api/home";
import DivideHeader from "@/components/DivideHeader.vue"; import DivideHeader from "@/components/DivideHeader.vue";
import { useContainerScroll } from "@/hooks/useScrollShow";
import headerIcon1 from "./assets/icons/header-icon1.png"; import headerIcon1 from "./assets/icons/header-icon1.png";
import headerIcon2 from "./assets/icons/header-icon2.png"; import headerIcon2 from "./assets/icons/header-icon2.png";
import headerIcon3 from "./assets/icons/header-icon3.png"; import headerIcon3 from "./assets/icons/header-icon3.png";
...@@ -346,6 +529,8 @@ import headerIcon5 from "./assets/icons/header-icon5.png"; ...@@ -346,6 +529,8 @@ import headerIcon5 from "./assets/icons/header-icon5.png";
import getMultiLineChart from "./utils/multiLineChart"; import getMultiLineChart from "./utils/multiLineChart";
import getWordCloudChart from "./utils/worldCloudChart"; import getWordCloudChart from "./utils/worldCloudChart";
import getPieChart from "./utils/piechart";
import getDoublePieChart from "./utils/doublePieChart";
import bill1 from "./assets/images/bill1.png"; import bill1 from "./assets/images/bill1.png";
import bill2 from "./assets/images/bill2.png"; import bill2 from "./assets/images/bill2.png";
...@@ -370,24 +555,45 @@ import Message1 from "./assets/images/message-icon1.png"; ...@@ -370,24 +555,45 @@ import Message1 from "./assets/images/message-icon1.png";
import Message2 from "./assets/images/message-icon2.png"; import Message2 from "./assets/images/message-icon2.png";
import Message3 from "./assets/images/message-icon3.png"; import Message3 from "./assets/images/message-icon3.png";
const billList = ref([]); import Box8Img1 from "./assets/images/box8-icon1.png";
const curBillListIndex = ref(0); import Box8Img2 from "./assets/images/box8-icon2.png";
import Box8Img3 from "./assets/images/box8-icon3.png";
import Box8Img4 from "./assets/images/box8-icon4.png";
import Box8Img5 from "./assets/images/box8-icon5.png";
import Cyy from "@/assets/icons/cyy.png";
import Zyy from "@/assets/icons/zyy.png";
import Ghd from "@/assets/icons/ghd.png";
import Mzd from "@/assets/icons/mzd.png";
const currentPage = ref(1);
// 处理页码改变事件
const handleCurrentChange = page => {
currentPage.value = page;
};
const containerRef = ref(null);
const { isShow } = useContainerScroll(containerRef);
const hotBillList = ref([]); // 热门法案列表
const curHotBillListIndex = ref(0); // 当前热门法案索引
// 切换热门法案
const handleSwithCurBill = name => { const handleSwithCurBill = name => {
if (name === "left") { if (name === "left") {
if (curBillListIndex.value === 0) { if (curHotBillListIndex.value === 0) {
curBillListIndex.value = billList.value.length - 1; curHotBillListIndex.value = hotBillList.value.length - 1;
} else { } else {
curBillListIndex.value--; curHotBillListIndex.value--;
} }
} else { } else {
if (curBillListIndex.value === billList.value.length - 1) { if (curHotBillListIndex.value === hotBillList.value.length - 1) {
curBillListIndex.value = 0; curHotBillListIndex.value = 0;
} else { } else {
curBillListIndex.value++; curHotBillListIndex.value++;
} }
} }
curBill.value = billList.value[curBillListIndex.value]; curBill.value = hotBillList.value[curHotBillListIndex.value];
}; };
// 当前法案 // 当前法案
...@@ -400,54 +606,13 @@ const curBill = ref({ ...@@ -400,54 +606,13 @@ const curBill = ref({
introductionDate: "" introductionDate: ""
}); });
// 查看详情
const handleClickToDetail = () => { const handleClickToDetail = () => {
window.sessionStorage.setItem("billId", curBill.value.billId); window.sessionStorage.setItem("billId", curBill.value.billId);
router.push("/billLayout"); router.push("/billLayout");
}; };
const billTrendList = ref([ // 风险信号
{
title: "限制与中国合作",
no: "H.R.2670"
},
{
title: "限制中国获取技术",
no: "H.R.2471"
},
{
title: "禁止在中国建设半导体产能",
no: "H.R.5895"
},
{
title: "限制中国产燃油进口",
no: "S.870"
},
{
title: "禁止政府部门采购受控半导体或服务",
no: "H.R.6395"
},
{
title: "禁止向部分中国实体提供资金",
no: "H.R.3935"
},
{
title: "限制采购中国生产电池",
no: "H.R.7776"
},
{
title: "重视新兴中国技术公司威胁",
no: "H.R.3935"
},
{
title: "禁止卫星出口至中国",
no: "S.870"
},
{
title: "禁购华为设备",
no: "H.R.5895"
}
]);
const warningList = ref([ const warningList = ref([
{ {
title: "美国大而美法案落地,总统签署通过", title: "美国大而美法案落地,总统签署通过",
...@@ -476,121 +641,195 @@ const warningList = ref([ ...@@ -476,121 +641,195 @@ const warningList = ref([
} }
]); ]);
const timelineList = ref([ // 资源库 法案列表
{ const billList = ref([
title: "成为公法 No: 119-21。",
time: "2025-07-04",
status: 1
},
{
title: "总统签署",
time: "2025-07-04",
status: 0
},
{
title: "提交总统",
time: "2025-07-03",
status: 0
},
{
title: "重新审议动议搁置案无异议通过。",
time: "2025-07-03 14:31",
status: 0
},
{
title: "关于‘众议院同意参议院修正案’...",
time: "2025-07-02 14:31",
status: 0
}
]);
const areaList = ref([
{
name: "跨境电商",
status: 2
},
{
name: "新能源产业",
status: 4
},
{
name: "半导体产业",
status: 1
},
{
name: "关税",
status: 3
},
{
name: "光伏产业",
status: 2
}
]);
const curBillList = ref([
{ {
billName: "大而美法案", billName: "大而美法案",
introductionDate: "2025年7月4日", introductionDate: "2025年7月4日",
img: bill1 status: "特别重大风险",
tagList: ["集成电路", "人工智能"],
img: bill1,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "GENIUS稳定币法案", billName: "GENIUS稳定币法案",
introductionDate: "2025年7月5日", introductionDate: "2025年7月5日",
img: bill2 status: "",
tagList: ["集成电路", "人工智能"],
img: bill2,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "美越贸易协议", billName: "美越贸易协议",
introductionDate: "2025年7月6日", introductionDate: "2025年7月6日",
img: bill3 status: "",
tagList: ["集成电路", "人工智能"],
img: bill3,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "美越贸易协议", billName: "美越贸易协议",
introductionDate: "2025年7月7日", introductionDate: "2025年7月7日",
img: bill4 status: "特别重大风险",
tagList: ["集成电路", "人工智能"],
img: bill4,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "汽车零部件25%关税实施规则", billName: "汽车零部件25%关税实施规则",
introductionDate: "2025年7月10日", introductionDate: "2025年7月10日",
img: bill5 status: "重大风险",
tagList: ["集成电路", "人工智能"],
img: bill5,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "汽车零部件25%关税实施规则", billName: "汽车零部件25%关税实施规则",
introductionDate: "2025年7月12日", introductionDate: "2025年7月12日",
img: bill6 status: "",
tagList: ["集成电路", "人工智能"],
img: bill6,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "小额豁免包裹政策调整", billName: "小额豁免包裹政策调整",
introductionDate: "2025年7月14日", introductionDate: "2025年7月14日",
img: bill7 status: "特别重大风险",
tagList: ["集成电路", "人工智能"],
img: bill7,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "NIH预算否决案", billName: "NIH预算否决案",
introductionDate: "2025年7月15日", introductionDate: "2025年7月15日",
img: bill8 status: "重大风险",
tagList: ["集成电路", "人工智能"],
img: bill8,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "得州国会选区重划法案", billName: "得州国会选区重划法案",
introductionDate: "2025年7月17日", introductionDate: "2025年7月17日",
img: bill9 status: "一般风险",
tagList: ["集成电路", "人工智能"],
img: bill9,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "美越贸易协议", billName: "美越贸易协议",
introductionDate: "2025年7月24日", introductionDate: "2025年7月24日",
img: bill10 status: "",
tagList: ["集成电路", "人工智能"],
img: bill10,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "美越贸易协议", billName: "美越贸易协议",
introductionDate: "2025年8月4日", introductionDate: "2025年8月4日",
img: bill11 status: "",
tagList: ["集成电路", "人工智能"],
img: bill11,
yuan: "众议院",
dangpai: "共和党"
},
{
billName: "美越贸易协议",
introductionDate: "2025年8月8日",
status: "特别重大风险",
tagList: ["集成电路", "人工智能"],
img: bill12,
yuan: "众议院",
dangpai: "共和党"
}, },
{ {
billName: "美越贸易协议", billName: "美越贸易协议",
introductionDate: "2025年8月8日", introductionDate: "2025年8月8日",
img: bill12 status: "特别重大风险",
tagList: ["集成电路", "人工智能"],
img: bill12,
yuan: "众议院",
dangpai: "共和党"
}
]);
// 当前展示法案列表
const curBillList = computed(() => {
const startIndex = (currentPage.value - 1) * 12;
const endIndex = startIndex + 12;
return billList.value.slice(startIndex, endIndex);
});
const box7selectetedTime = ref("2025");
const box7YearList = ref([
{
label: "2025",
value: "2025"
},
{
label: "2024",
value: "2024"
},
{
label: "2023",
value: "2023"
},
{
label: "2022",
value: "2022"
}
]);
const box8selectetedTime = ref("2025");
const box8YearList = ref([
{
label: "2025",
value: "2025"
},
{
label: "2024",
value: "2024"
},
{
label: "2023",
value: "2023"
},
{
label: "2022",
value: "2022"
}
]);
const box9selectetedTime = ref("2025");
const box9YearList = ref([
{
label: "2025",
value: "2025"
},
{
label: "2024",
value: "2024"
},
{
label: "2023",
value: "2023"
},
{
label: "2022",
value: "2022"
} }
]); ]);
const releaseTime = ref("近一年发布"); const releaseTime = ref("近一年发布"); // 发布时间
const releaseTimeList = ref([ const releaseTimeList = ref([
{ {
...@@ -655,46 +894,6 @@ const handleClickCate = cate => { ...@@ -655,46 +894,6 @@ const handleClickCate = cate => {
handleGetBillsByType(); handleGetBillsByType();
}; };
const navList = ref([
{
icon: headerIcon1,
activeIcno: headerIcon1,
name: "首页",
path: "/home"
},
{
icon: headerIcon2,
activeIcno: headerIcon2,
name: "国家",
path: "/country"
},
{
icon: headerIcon3,
activeIcno: headerIcon3,
name: "领域",
path: "/area"
},
{
icon: headerIcon4,
activeIcno: headerIcon4,
name: "要素",
path: "/home"
},
{
icon: headerIcon5,
activeIcno: headerIcon5,
name: "事件",
path: "/home"
}
]);
const activeNavIndex = ref(0);
const handleClickNav = (index, item) => {
activeNavIndex.value = index;
router.push(item.path);
};
// 绘制echarts图表 // 绘制echarts图表
const setChart = (option, chartId) => { const setChart = (option, chartId) => {
let chartDom = document.getElementById(chartId); let chartDom = document.getElementById(chartId);
...@@ -792,7 +991,7 @@ const handleGetHotBills = async () => { ...@@ -792,7 +991,7 @@ const handleGetHotBills = async () => {
try { try {
const res = await getHotBills(); const res = await getHotBills();
console.log("热门法案", res); console.log("热门法案", res);
billList.value = res.data; hotBillList.value = res.data;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
...@@ -806,7 +1005,7 @@ const handleGetBillsByType = async () => { ...@@ -806,7 +1005,7 @@ const handleGetBillsByType = async () => {
try { try {
const res = await getBillsByType(params); const res = await getBillsByType(params);
console.log("根据法案类型获取法案列表", res); console.log("根据法案类型获取法案列表", res);
curBillList.value = res.data.map(item => { billList.value = res.data.map(item => {
return { return {
billId: item.billId, billId: item.billId,
billName: item.billName, billName: item.billName,
...@@ -840,38 +1039,298 @@ const wordCloudData = ref([ ...@@ -840,38 +1039,298 @@ const wordCloudData = ref([
{ name: "加强供应链风险管理", value: 73 } { name: "加强供应链风险管理", value: 73 }
]); ]);
onMounted(async () => { const box9ChartData = ref([
handleGetHylyList(); {
await handleGetHotBills(); name: "半导体",
curBill.value = billList.value[0]; value: 50
// handleGetBillsByType(); },
let chart1 = getMultiLineChart(chart1Data.value.title, chart1Data.value.data[0].value, chart1Data.value.data[1].value); {
setChart(chart1, "chart1"); name: "电子设备",
value: 46
const wordCloudChart = getWordCloudChart(wordCloudData.value); },
setChart(wordCloudChart, "wordCloudChart"); {
}); name: "显示技术",
</script> value: 40
},
{
name: "新能源",
value: 32
},
{
name: "通信设备",
value: 31
},
{
name: "汽车",
value: 30
},
{
name: "其他",
value: 24
}
]);
<style lang="scss" scoped> const box7Data = ref([
:deep(.el-input__wrapper) { [
box-shadow: none; {
} name: '众议院',
.home-wrapper { value: 298
.home-header { },
height: 64px; {
color: #fff; name: '参议院',
font-family: Microsoft YaHei; value: 149
font-size: 20px;
font-weight: 700;
line-height: 26px;
line-height: 64px;
background: url("./assets/images/header-bg.png");
box-sizing: border-box;
padding-left: 160px;
} }
.home-main {
width: 1600px; ],
[
{
name: '拨款委员会',
value: 50,
type: '众议院'
},
{
name: '筹款委员会',
value: 50,
type: '众议院'
},
{
name: '外交事务委员会',
value: 46,
type: '众议院'
},
{
name: '国土安全委员会',
value: 40,
type: '众议院'
},
{
name: '司法委员会',
value: 40,
type: '众议院'
},
{
name: '军事委员会',
value: 40,
type: '众议院'
},
{
name: '能源和商业委员会',
value: 32,
type: '众议院'
},
{
name: '拨款委员会1',
value: 32,
type: '参议院'
},
{
name: '财政委员会',
value: 31,
type: '参议院'
},
{
name: '能源',
value: 30,
type: '参议院'
},
{
name: '能源1',
value: 30,
type: '参议院'
},
{
name: '其他',
value: 24,
type: '参议院'
}
]
])
const box8Data = ref([
{
name: "汤姆·科顿",
zhiwei: "参议院情报委员会主席",
img: Message3,
dangpai: Cyy,
yuan: Ghd,
num: 8
},
{
name: "吉姆·里施",
zhiwei: "参议院外交关系委员会主席",
img: Message3,
dangpai: Cyy,
yuan: Ghd,
num: 4
},
{
name: "特德·克鲁兹",
zhiwei: "参议院商务、科学和交通委员会主席",
img: Message3,
dangpai: Cyy,
yuan: Ghd,
num: 2
},
{
name: "里克·克劳福德",
zhiwei: "众议院美中战略竞争特设委员会主席",
img: Message3,
dangpai: Cyy,
yuan: Ghd,
num: 2
},
{
name: "布莱恩·马斯特",
zhiwei: "众议院情报委员会主席",
img: Message3,
dangpai: Cyy,
yuan: Ghd,
num: 2
}
]);
const box9ChartColorList = ref(["#4096FF", "#FFA39E", "#ADC6FF", "#FFC069", "#B5F5EC", "#B37FEB", "#D6E4FF"]);
onMounted(async () => {
handleGetHylyList();
await handleGetHotBills();
curBill.value = hotBillList.value[0];
// handleGetBillsByType();
let chart1 = getMultiLineChart(chart1Data.value.title, chart1Data.value.data[0].value, chart1Data.value.data[1].value);
setChart(chart1, "chart1");
const wordCloudChart = getWordCloudChart(wordCloudData.value);
setChart(wordCloudChart, "wordCloudChart");
const box7Chart = getDoublePieChart(box7Data.value[0], box7Data.value[1])
setChart(box7Chart, 'box7Chart')
const box9Chart = getPieChart(box9ChartData.value, box9ChartColorList.value);
setChart(box9Chart, "box9Chart");
});
</script>
<style lang="scss" scoped>
:deep(.el-input__wrapper) {
box-shadow: none;
}
.home-wrapper {
width: 100%;
height: calc(100vh - 96px);
position: relative;
overflow-y: hidden;
.search-header {
width: 100%;
height: 144px;
background: #fff;
overflow: hidden;
.home-main-header-center {
margin-top: 20px;
margin-left: 200px;
width: 800px;
height: 48px;
border-radius: 10px;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
padding: 1px;
position: relative;
.search {
position: absolute;
right: 1px;
top: 2px;
width: 120px;
height: 44px;
border-radius: 10px;
background: var(--color-main-active);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.search-icon {
width: 18px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
.search-text {
margin-left: 8px;
height: 22px;
color: #fff;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 22px;
}
}
}
.home-main-header-btn-box {
margin-top: 20px;
margin-left: 200px;
display: flex;
gap: 16px;
.btn {
display: flex;
width: 140px;
height: 36px;
border: 1px solid #aed6ff;
box-sizing: border-box;
border-radius: 18px;
justify-content: center;
background: #e7f3ff;
position: relative;
cursor: pointer;
&:hover {
background: #cae3fc;
}
.btn-text {
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
line-height: 36px;
margin-left: 5px;
}
.btn-icon {
height: 20px;
line-height: 20px;
position: absolute;
top: 6px;
right: 8px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
}
}
}
}
.scrollHomeBox {
width: 100%;
height: calc(100% - 144px);
overflow-y: auto;
}
.home-box {
width: 100%;
height: 100%;
overflow-y: auto;
.home-header {
height: 64px;
color: #fff;
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
line-height: 64px;
background: url("./assets/images/header-bg.png");
box-sizing: border-box;
padding-left: 160px;
}
.home-main {
width: 1600px;
margin: 0 auto; margin: 0 auto;
margin-top: 48px; margin-top: 48px;
background: url("./assets/images/background.png"); background: url("./assets/images/background.png");
...@@ -894,12 +1353,13 @@ onMounted(async () => { ...@@ -894,12 +1353,13 @@ onMounted(async () => {
right: 1px; right: 1px;
top: 2px; top: 2px;
width: 120px; width: 120px;
height: 42px; height: 44px;
border-radius: 10px; border-radius: 10px;
background: var(--color-main-active); background: var(--color-main-active);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
cursor: pointer;
.search-icon { .search-icon {
width: 18px; width: 18px;
height: 18px; height: 18px;
...@@ -1336,6 +1796,7 @@ onMounted(async () => { ...@@ -1336,6 +1796,7 @@ onMounted(async () => {
.num { .num {
width: 24px; width: 24px;
height: 20px; height: 20px;
line-height: 20px;
text-align: center; text-align: center;
color: rgba(255, 255, 255, 1); color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
...@@ -1347,19 +1808,11 @@ onMounted(async () => { ...@@ -1347,19 +1808,11 @@ onMounted(async () => {
background: rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.3);
} }
} }
.more {
margin-top: 19px;
margin-left: 224px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 16px;
}
} }
.box2-main { .box2-main {
height: 330px; height: 330px;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden;
box-sizing: border-box; box-sizing: border-box;
padding-right: 20px; padding-right: 20px;
.box2-main-item { .box2-main-item {
...@@ -1468,6 +1921,7 @@ onMounted(async () => { ...@@ -1468,6 +1921,7 @@ onMounted(async () => {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: 0 20px; padding: 0 20px;
position: relative;
.box3-header-left { .box3-header-left {
display: flex; display: flex;
.box3-header-icon { .box3-header-icon {
...@@ -1489,6 +1943,19 @@ onMounted(async () => { ...@@ -1489,6 +1943,19 @@ onMounted(async () => {
font-weight: 700; font-weight: 700;
line-height: 22px; line-height: 22px;
} }
.more {
width: 49px;
height: 24px;
position: absolute;
top: 14px;
right: 27px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
cursor: pointer;
}
} }
} }
.box3-main { .box3-main {
...@@ -1572,6 +2039,7 @@ onMounted(async () => { ...@@ -1572,6 +2039,7 @@ onMounted(async () => {
display: flex; display: flex;
box-sizing: border-box; box-sizing: border-box;
padding-left: 22px; padding-left: 22px;
position: relative;
.header-icon { .header-icon {
margin-top: 15px; margin-top: 15px;
width: 20px; width: 20px;
...@@ -1591,6 +2059,19 @@ onMounted(async () => { ...@@ -1591,6 +2059,19 @@ onMounted(async () => {
font-weight: 700; font-weight: 700;
line-height: 22px; line-height: 22px;
} }
.more {
width: 49px;
height: 24px;
position: absolute;
top: 14px;
right: 27px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
cursor: pointer;
}
} }
.box4-main { .box4-main {
height: 402px; height: 402px;
...@@ -1694,36 +2175,24 @@ onMounted(async () => { ...@@ -1694,36 +2175,24 @@ onMounted(async () => {
.box5-header-right { .box5-header-right {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
width: 178px; gap: 8px;
height: 22px; height: 24px;
.right-box { margin-top: 12px;
display: flex; .header-right-icon {
margin-top: 16px; margin-top: 4px;
width: 89px; width: 14px;
height: 22px; height: 16px;
justify-content: flex-end; img {
.icon1 { width: 100%;
margin-top: 5px; height: 100%;
width: 12px;
height: 12px;
border-radius: 6px;
background: rgba(20, 89, 187, 1);
} }
.icon2 {
margin-top: 5px;
width: 12px;
height: 12px;
border-radius: 6px;
background: rgba(250, 140, 22, 1);
} }
.text { .header-right-text {
margin-left: 5px; color: rgba(132, 136, 142, 1);
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 14px; font-size: 16px;
font-weight: 400; font-weight: 400;
line-height: 22px; line-height: 24px;
}
} }
} }
} }
...@@ -1763,31 +2232,356 @@ onMounted(async () => { ...@@ -1763,31 +2232,356 @@ onMounted(async () => {
font-weight: 700; font-weight: 700;
line-height: 22px; line-height: 22px;
} }
.box6-header-right {
margin-left: 130px;
display: flex;
justify-content: flex-end;
gap: 8px;
height: 24px;
margin-top: 12px;
.header-right-icon {
margin-top: 4px;
width: 14px;
height: 16px;
img {
width: 100%;
height: 100%;
} }
.box6-main {
width: 452px;
height: 402px;
} }
.header-right-text {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
} }
} }
} }
.box6-main {
width: 452px;
height: 402px;
} }
.home-main-footer {
width: 100%;
height: 1000px;
background: rgba(248, 249, 250, 1);
margin-bottom: 20px;
overflow: hidden;
margin-top: 36px;
.divide4 {
margin: 0 auto;
margin-top: 52px;
margin-bottom: 36px;
} }
.home-main-footer-header { }
width: 1600px; .center-footer1 {
margin: 0 auto; display: flex;
gap: 16px;
margin-top: 16px;
.box7 {
width: 520px;
height: 450px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.box7-header {
height: 53px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
margin: 0 auto;
display: flex;
justify-content: space-between;
padding: 0 20px;
.box7-header-left {
display: flex;
.box7-header-icon {
margin-top: 16px;
width: 19px;
height: 19px;
img {
width: 100%;
height: 100%;
}
}
.box7-header-title {
margin-top: 16px;
margin-left: 19px;
height: 22px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 22px;
}
}
.box7-header-right {
display: flex;
justify-content: flex-end;
gap: 8px;
height: 24px;
margin-top: 12px;
.header-right-icon {
margin-top: 4px;
width: 14px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.header-right-text {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
}
.box-center {
height: 45px;
padding-right: 20px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.box7-main{
height: 340px;
}
}
.box8 {
width: 527px;
height: 450px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.box8-header {
height: 53px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
margin: 0 auto;
display: flex;
justify-content: space-between;
padding: 0 20px;
.box8-header-left {
display: flex;
.box8-header-icon {
margin-top: 16px;
width: 19px;
height: 19px;
img {
width: 100%;
height: 100%;
}
}
.box8-header-title {
margin-top: 16px;
margin-left: 19px;
height: 22px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 22px;
}
}
.box8-header-right {
display: flex;
justify-content: flex-end;
gap: 8px;
height: 24px;
margin-top: 12px;
.header-right-icon {
margin-top: 4px;
width: 14px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.header-right-text {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
}
.box-center {
height: 45px;
padding-right: 20px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.box8-main {
height: 340px;
.box8-main-item {
margin: 0 auto;
width: 458px;
height: 51px;
margin-bottom: 16px;
display: flex;
align-items: center;
position: relative;
.box8-main-item-left {
position: relative;
width: 42px;
height: 42px;
img {
width: 100%;
height: 100%;
}
.left-icon1 {
position: absolute;
left: 2px;
bottom: -6px;
width: 20px;
height: 20px;
border-radius: 10px;
background: (255, 255, 255, 0.8);
box-sizing: border-box;
padding: 2px;
img {
width: 100%;
height: 100%;
}
}
.left-icon2 {
position: absolute;
right: 2px;
bottom: -6px;
width: 20px;
height: 20px;
border-radius: 10px;
background: (255, 255, 255, 0.8);
box-sizing: border-box;
padding: 2px;
img {
width: 100%;
height: 100%;
}
}
}
.box8-main-item-center {
height: 48px;
margin-left: 12px;
.box8-main-item-center-top {
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
.box8-main-item-center-footer {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
.box8-main-item-right {
position: absolute;
top: 0;
right: 0;
width: 92px;
height: 51px;
text-align: right;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 51px;
}
}
}
}
.box9 {
width: 521px;
height: 450px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.box9-header {
height: 53px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
margin: 0 auto;
display: flex;
justify-content: space-between;
padding: 0 20px;
.box9-header-left {
display: flex;
.box9-header-icon {
margin-top: 16px;
width: 19px;
height: 19px;
img {
width: 100%;
height: 100%;
}
}
.box9-header-title {
margin-top: 16px;
margin-left: 19px;
height: 22px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 22px;
}
}
.box9-header-right {
display: flex;
justify-content: flex-end;
gap: 8px;
height: 24px;
margin-top: 12px;
.header-right-icon {
margin-top: 4px;
width: 14px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.header-right-text {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
}
.box-center {
height: 45px;
padding-right: 20px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.box9-main {
height: 340px;
}
}
}
}
}
.home-main-footer {
width: 100%;
height: 1160px;
background: rgba(248, 249, 250, 1);
margin-bottom: 20px;
overflow: hidden;
margin-top: 36px;
.divide4 {
margin: 0 auto;
margin-top: 52px;
margin-bottom: 36px;
}
.home-main-footer-header {
width: 1600px;
margin: 0 auto;
margin-top: 37px; margin-top: 37px;
margin-bottom: 36px; margin-bottom: 36px;
// width: 1600px; // width: 1600px;
...@@ -1853,34 +2647,89 @@ onMounted(async () => { ...@@ -1853,34 +2647,89 @@ onMounted(async () => {
.main-item { .main-item {
width: 240px; width: 240px;
height: 320px; height: 320px;
border-radius: 4px; border-radius: 10px;
background: linear-gradient(0deg, rgba(255, 255, 255, 1) 44%, rgba(255, 255, 255, 0) 100%); background: linear-gradient(0deg, rgba(255, 255, 255, 1) 44%, rgba(255, 255, 255, 0) 100%);
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1); box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: #fff; background: #fff;
margin-bottom: 24px; margin-bottom: 24px;
margin-right: 25px; margin-right: 25px;
position: relative;
.status-box {
position: absolute;
top: 15px;
right: 16px;
height: 28px;
padding: 0 8px;
border-radius: 20px;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
.status-icon {
width: 4px;
height: 4px;
border-radius: 2px;
}
.statusIcon1 {
background: rgba(206, 79, 81, 1);
}
.statusIcon2 {
background: rgba(255, 149, 77, 1);
}
.statusIcon3 {
background: rgba(33, 129, 57, 1);
}
.status-text {
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
height: 28px;
line-height: 28px;
}
.status1 {
color: rgba(206, 79, 81, 1);
}
.status2 {
color: rgba(255, 149, 77, 1);
}
.status3 {
color: rgba(33, 129, 57, 1);
}
}
.statusBox1 {
background: rgba(206, 79, 81, 0.1);
}
.statusBox2 {
background: rgba(255, 149, 77, 0.1);
}
.statusBox3 {
background: rgba(33, 129, 57, 0.1);
}
.main-item-box1 { .main-item-box1 {
margin-top: 20px; margin-top: 20px;
margin-left: 45px; margin-left: 45px;
width: 150px; width: 150px;
height: 200px; height: 200px;
box-sizing: border-box; box-sizing: border-box;
border: 1px solid rgba(240, 242, 244, 1);
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
.main-item-box2 { .main-item-box2 {
margin-top: 26px; width: 188px;
height: 50px;
display: flex;
align-items: flex-end;
justify-content: center;
text-align: center; text-align: center;
height: 30px; margin: 0 auto;
margin-top: -45px;
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 16px; font-size: 18px;
font-weight: 700; font-weight: 700;
line-height: 30px; line-height: 25px;
} }
.main-item-box3 { .main-item-box3 {
text-align: center; text-align: center;
...@@ -1891,6 +2740,38 @@ onMounted(async () => { ...@@ -1891,6 +2740,38 @@ onMounted(async () => {
font-weight: 400; font-weight: 400;
line-height: 30px; line-height: 30px;
} }
.main-item-box4 {
text-align: center;
height: 30px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
gap: 15px;
display: flex;
justify-content: center;
}
.main-item-box5 {
display: flex;
width: 188px;
height: 24px;
margin: 0 auto;
overflow: hidden;
justify-content: center;
gap: 8px;
.tag {
height: 24px;
border-radius: 4px;
background: rgba(231, 243, 255, 1);
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 24px;
padding: 0 8px;
}
}
} }
} }
.home-main-footer-footer { .home-main-footer-footer {
...@@ -1909,5 +2790,6 @@ onMounted(async () => { ...@@ -1909,5 +2790,6 @@ onMounted(async () => {
} }
} }
} }
}
} }
</style> </style>
\ No newline at end of file
const getDoublePieChart = (data1, data2) => {
const colorList = ['#8AC4FF', '#FFD591']
const colorList1 = ['#055FC2', '#FFA940']
let option = {
series: [
{
type: 'pie',
radius: [25, 68],
// height: '100%',
left: 'center',
// width: '100%',
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
label: {
position: 'inside',
textStyle: {
fontSize: '16px',
fontWeight: 700,
// color: '#333'
}
},
data: data1.map(item => {
return {
name: item.name,
value: item.value,
itemStyle: {
color: item.name === '参议院' ? '#055FC2' : '#FFA940'
}
}
})
},
{
type: 'pie',
radius: [70, 100],
height: '100%',
left: 'center',
width: '80%',
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
label: {
alignTo: 'edge',
formatter: '{name|{b}}\n{time|{c} 条 {d}%}',
minMargin: 5,
edgeDistance: 10,
lineHeight: 15,
rich: {
time: {
fontSize: 10,
color: '#999'
}
}
},
labelLine: {
length: 15,
length2: 0,
maxSurfaceAngle: 80
},
labelLayout: function (params) {
const isLeft = params.labelRect.x < 556 / 2;
const points = params.labelLinePoints;
// Update the end point.
points[2][0] = isLeft
? params.labelRect.x
: params.labelRect.x + params.labelRect.width;
return {
labelLinePoints: points
};
},
data: data2.map(item => {
return {
name: item.name,
value: item.value,
itemStyle: {
color: item.type === '参议院' ? '#8AC4FF' : '#FFD591'
}
}
})
}
]
}
return option
}
export default getDoublePieChart;
\ No newline at end of file
...@@ -20,7 +20,12 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => { ...@@ -20,7 +20,12 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => {
}, },
legend: { legend: {
data: ['提出法案', '通过法案'], data: ['提出法案', '通过法案'],
show: false show: true,
textStyle: {
color: 'rgba(95, 101, 108, 1)',
fontFamily: 'Microsoft YaHei',
fontSize: '16px',
}
}, },
color: ['#1459bb', '#fa8c16'], color: ['#1459bb', '#fa8c16'],
xAxis: [ xAxis: [
......
const getPieChart = (data,colorList) => {
let option = {
color: colorList,
series: [
{
type: 'pie',
radius: [70, 100],
height: '100%',
left: 'center',
width: '100%',
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
label: {
alignTo: 'edge',
formatter: '{name|{b}}\n{time|{c} 条 {d}%}',
minMargin: 5,
edgeDistance: 10,
lineHeight: 15,
rich: {
time: {
fontSize: 10,
color: '#999'
}
}
},
labelLine: {
length: 15,
length2: 0,
maxSurfaceAngle: 80
},
labelLayout: function (params) {
const isLeft = params.labelRect.x < 556 / 2;
const points = params.labelLinePoints;
// Update the end point.
points[2][0] = isLeft
? params.labelRect.x
: params.labelRect.x + params.labelRect.width;
return {
labelLinePoints: points
};
},
data: data
}]
}
return option
}
export default getPieChart;
\ No newline at end of file
...@@ -38,9 +38,9 @@ const siderBtnList = ref([ ...@@ -38,9 +38,9 @@ const siderBtnList = ref([
path: "/billLayout/deepDig/processAnalysis", path: "/billLayout/deepDig/processAnalysis",
}, },
{ {
name: "进程分析", name: "政治献金",
isActive: false, isActive: false,
path: "/billLayout/deepDig/progressAnalysis", path: "/billLayout/deepDig/poliContribution",
}, },
]); ]);
......
<template>
<div class="wrapper">
<div class="left">
<div class="box1">
<div class="box-header">
<div class="icon"></div>
<div class="title">{{ "主要议员" }}</div>
<div class="btn-box">
<div class="btn" :class="{ btnActive: activeBtnIndex === 0 }">{{ "参议院" }}</div>
<div class="btn" :class="{ btnActive: activeBtnIndex === 1 }">{{ "众议院" }}</div>
</div>
<div class="header-right">
<div class="right-icon">
<img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="right-icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div>
<div class="box1-main">
<div class="box1-main-top">
<div class="top-item" v-for="(item, index) in majorList[activeBtnIndex].data1" :key="index">
<div class="icon">
<img :src="item.img" alt="" />
</div>
<div class="name">{{ item.name }}</div>
<div class="line" :class="{ line1: index === 0, line2: index === 1 }"></div>
<div class="num" :class="{ num1: index === 0, num2: index === 1 }">{{ item.num }}</div>
</div>
</div>
<div class="box1-main-main">
<div
class="item"
:class="{ itemActive: itemActiveIndex === index }"
v-for="(item, index) in majorList[activeBtnIndex].data2"
:key="index"
>
<div class="item-left">
<img :src="item.img" alt="" />
</div>
<div class="item-center">
<div class="center-top">
<div class="name">{{ item.name }}</div>
<div class="icon1">
<img :src="item.dangpai" alt="" />
</div>
<div class="icon2">
<img :src="item.yuanbie" alt="" />
</div>
</div>
<div class="center-footer">
{{ item.zhiwei }}
</div>
</div>
<div class="item-right">
{{ item.num }}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="right">
<div class="box2">
<div class="box-header">
<div class="icon"></div>
<div class="title">{{ "政治献金流向" }}</div>
<div class="header-right">
<div class="right-icon">
<img src="@/assets/icons/box-header-icon1.png" alt="" />
</div>
<div class="right-icon">
<img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="right-icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div>
<div class="box2-main" id="chart1"></div>
<div class="box-footer">
<div class="box-footer-left">
<img src="@/assets/icons/box-footer-left-icon.png" alt="" />
</div>
<div class="box-footer-center">
{{
"马尔科·卢比奥的政治资金主要依赖于一个由亿万富翁、特定行业利益集团及通过​“超级政治行动委员会”​​ 运作的大额捐款网络。"
}}
</div>
<div class="box-footer-right">
<img src="@/assets/icons/box-footer-right-icon.png" alt="" />
</div>
</div>
</div>
<div class="box3">
<div class="box-header">
<div class="icon"></div>
<div class="title">{{ "政治献金领域分布" }}</div>
<div class="header-right">
<div class="right-icon">
<img src="@/assets/icons/box-header-icon1.png" alt="" />
</div>
<div class="right-icon">
<img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="right-icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div>
<div class="box3-main">
<div class="box3-main-left" id="chart2"></div>
<div class="box3-main-right">
<div class="box3-main-right-item" v-for="(item, index) in areaList" :key="index">
<div class="id">{{ index + 1 }}</div>
<div class="name">{{ item.name }}</div>
<div class="line">
<div class="inner-line" :style="{width: (item.num / areaList[0].num)* 100 + '%' }"></div>
</div>
<div class="num">{{ item.numtext }}</div>
<div class="more">{{ `${item.insNum}家机构 >` }}</div>
</div>
</div>
</div>
<div class="box-footer">
<div class="box-footer-left">
<img src="@/assets/icons/box-footer-left-icon.png" alt="" />
</div>
<div class="box-footer-center">
{{
"马尔科·卢比奥的政治资金主要依赖于一个由亿万富翁、特定行业利益集团及通过​“超级政治行动委员会”​​ 运作的大额捐款网络。"
}}
</div>
<div class="box-footer-right">
<img src="@/assets/icons/box-footer-right-icon.png" alt="" />
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import setChart from "@/utils/setChart";
import getPieChart from "./utils/piechart";
import getSankeyChart from "./utils/sankey"
import Img1 from "./assets/images/1.png";
import Img2 from "./assets/images/2.png";
import Img3 from "./assets/images/3.png";
import Img4 from "./assets/images/4.png";
import Img5 from "./assets/images/5.png";
import Img6 from "./assets/images/6.png";
import Img7 from "./assets/images/7.png";
import Img8 from "./assets/images/8.png";
import Img9 from "./assets/images/9.png";
import Img10 from "./assets/images/10.png";
import Cyy from "@/assets/icons/cyy.png";
import Zyy from "@/assets/icons/zyy.png";
import Ghd from "@/assets/icons/ghd.png";
import Mzd from "@/assets/icons/mzd.png";
const activeBtnIndex = ref(0);
const itemActiveIndex = ref(0);
const majorList = ref([
{
name: "参议院",
data1: [
{
name: "共和党",
img: Ghd,
num: "$1,550,000"
},
{
name: "民主党",
img: Mzd,
num: "$298,000"
}
],
data2: [
{
img: Img1,
name: "马尔科·卢比奥",
dangpai: Ghd,
yuanbie: Cyy,
zhiwei: "众议院预算委员会主席",
num: "$1,550,000"
},
{
img: Img2,
name: "史蒂夫·戴恩斯",
dangpai: Ghd,
yuanbie: Cyy,
zhiwei: "众议院预算委员会主席",
num: "$820,000"
},
{
img: Img3,
name: "伯尼·莫雷诺",
dangpai: Ghd,
yuanbie: Cyy,
zhiwei: "众议院预算委员会主席",
num: "$50,000"
},
{
img: Img4,
name: "戴夫·麦考密克",
dangpai: Ghd,
yuanbie: Cyy,
zhiwei: "众议院预算委员会主席",
num: "$50,000"
},
{
img: Img5,
name: "蒂姆·希伊",
dangpai: Ghd,
yuanbie: Cyy,
zhiwei: "众议院预算委员会主席",
num: "$35,000"
},
{
img: Img6,
name: "史蒂夫·戴恩斯",
dangpai: Ghd,
yuanbie: Cyy,
zhiwei: "众议院预算委员会主席",
num: "$35,000"
},
{
img: Img7,
name: "皮特·赫格塞思",
dangpai: Ghd,
yuanbie: Cyy,
zhiwei: "众议院预算委员会主席",
num: "$35,000"
},
{
img: Img8,
name: "安妮·海瑟薇",
dangpai: Ghd,
yuanbie: Cyy,
zhiwei: "众议院预算委员会主席",
num: "$35,000"
},
{
img: Img9,
name: "贾米森·格里尔",
dangpai: Ghd,
yuanbie: Cyy,
zhiwei: "众议院预算委员会主席",
num: "$35,000"
},
{
img: Img10,
name: "迈克·华尔兹",
dangpai: Ghd,
yuanbie: Cyy,
zhiwei: "众议院预算委员会主席",
num: "$35,000"
}
]
}
]);
const chart1Data = ref(
)
const areaList = ref([
{
name: "半导体",
num: 186000,
numtext: "$186,000",
insNum: 8
},
{
name: "电子设备",
num: 180000,
numtext: "$180,000",
insNum: 5
},
{
name: "显示技术",
num: 171000,
numtext: "$171,000",
insNum: 2
},
{
name: "新能源",
num: 75000,
numtext: "$75,000",
insNum: 3
},
{
name: "通信设备",
num: 70000,
numtext: "$70,000",
insNum: 2
},
{
name: "汽车",
num: 52000,
numtext: "$52,000",
insNum: 2
},
{
name: "其他",
num: 36000,
numtext: "$36,000",
insNum: 1
}
]);
const chart2Data = ref([
{
name: "半导体",
value: 50
},
{
name: "电子设备",
value: 46
},
{
name: "显示技术",
value: 40
},
{
name: "新能源",
value: 32
},
{
name: "通信设备",
value: 31
},
{
name: "汽车",
value: 30
},
{
name: "其他",
value: 24
}
]);
const chart2ColorList = ref(["#4096FF", "#FFA39E", "#ADC6FF", "#FFC069", "#B5F5EC", "#B37FEB", "#D6E4FF"]);
onMounted(() => {
let chart1 = getSankeyChart()
setChart(chart1, 'chart1')
let chart2 = getPieChart(chart2Data.value, chart2ColorList.value);
setChart(chart2, "chart2");
});
</script>
<style lang="scss" scoped>
.wrapper {
display: flex;
gap: 16px;
.box-header {
height: 51px;
width: 100%;
display: flex;
position: relative;
.icon {
width: 8px;
height: 20px;
margin-top: 18px;
border-radius: 0 4px 4px 0;
background: rgba(5, 95, 194, 1);
}
.title {
margin-left: 14px;
margin-top: 14px;
height: 26px;
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
}
.btn-box {
display: flex;
gap: 8px;
position: absolute;
right: 84px;
top: 15px;
.btn {
height: 28px;
padding: 0 8px;
box-sizing: border-box;
color: var(--btn-plain-text-color);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 28px;
border-radius: 4px;
background: var(--btn-plain-bg-color);
border: 1px solid var(--btn-plain-border-color);
}
.btnActive {
color: var(--btn-active-text-color);
background: var(--btn-active-bg-color);
border: 1px solid var(--btn-active-border-color);
}
}
.header-right {
position: absolute;
right: 12px;
top: 14px;
display: flex;
gap: 4px;
.right-icon {
width: 28px;
height: 28px;
img {
width: 100%;
height: 100%;
}
}
}
}
.box-footer {
margin: 0 auto;
display: flex;
width: 1034px;
height: 40px;
box-sizing: border-box;
border: 1px solid rgba(231, 243, 255, 1);
border-radius: 4px;
background: rgba(246, 250, 255, 1);
.box-footer-left {
width: 19px;
height: 20px;
margin-top: 10px;
margin-left: 12px;
img {
width: 100%;
height: 100%;
}
}
.box-footer-center {
margin-left: 13px;
width: 941px;
height: 40px;
line-height: 40px;
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.box-footer-right {
margin-left: 13px;
margin-top: 8px;
width: 24px;
height: 24px;
img {
width: 100%;
height: 100%;
}
}
}
.left {
margin-top: 16px;
width: 520px;
height: 846px;
.box1 {
width: 520px;
height: 846px;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.box1-main {
.box1-main-top {
width: 486px;
height: 110px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px;
background: rgba(247, 248, 249, 1);
margin: 8px auto;
.top-item {
display: flex;
align-items: center;
width: 450px;
height: 30px;
margin: 15px auto;
.icon {
width: 30px;
height: 30px;
img {
width: 100%;
height: 100%;
}
}
.name {
height: 30px;
margin-left: 10px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 700;
line-height: 30px;
}
.line {
margin-left: 10px;
width: 202px;
height: 8px;
border-radius: 0px 4px 4px 0px;
}
.line1 {
background: linear-gradient(270deg, rgba(206, 79, 81, 1), rgba(206, 79, 81, 0) 100%);
}
.line2 {
background: linear-gradient(270deg, rgba(5, 95, 194, 1), rgba(5, 95, 194, 0) 100%);
}
.num {
margin-left: 10px;
width: 120px;
height: 24px;
text-align: right;
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 700;
line-height: 24px;
}
.num1 {
color: rgba(206, 79, 81, 1);
}
.num2 {
color: rgba(5, 95, 194, 1);
}
}
}
.box1-main-main {
margin: 0 auto;
margin-top: 6px;
width: 498px;
height: 640px;
.item {
display: flex;
position: relative;
height: 64px;
box-sizing: border-box;
border-radius: 4px;
border: 1px soild transparent;
border-bottom: 1px solid rgba(234, 236, 238, 1);
.item-left {
width: 40px;
height: 40px;
margin-top: 11px;
margin-left: 14px;
img {
width: 100%;
height: 100%;
}
}
.item-center {
margin-left: 11px;
.center-top {
display: flex;
.name {
height: 24px;
margin-top: 7px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
.icon1 {
width: 16px;
height: 16px;
margin-left: 7px;
margin-top: 11px;
img {
width: 100%;
height: 100%;
}
}
.icon2 {
width: 16px;
height: 16px;
margin-left: 2px;
margin-top: 11px;
img {
width: 100%;
height: 100%;
}
}
}
.center-footer {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 24px;
}
}
.item-right {
position: absolute;
right: 16px;
top: 19px;
height: 24px;
text-align: right;
color: rgba(206, 79, 81, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
}
.itemActive {
background: rgba(246, 250, 255, 1);
border: 1px solid rgba(174, 214, 255, 1);
}
}
}
}
}
.right {
margin-top: 16px;
width: 1064px;
height: 846px;
.box2 {
width: 1064px;
height: 415px;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.box2-main {
width: 1020px;
height: 302px;
margin: 0 auto;
margin-bottom: 9px;
}
}
.box3 {
margin-top: 16px;
width: 1064px;
height: 415px;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.box3-main {
width: 1020px;
height: 300px;
margin: 0 auto;
margin-top: 3px;
margin-bottom: 9px;
display: flex;
.box3-main-left {
width: 492px;
}
.box3-main-right {
width: 518px;
margin-left: 10px;
overflow: hidden;
.box3-main-right-item {
height: 60px;
width: 518px;
box-sizing: border-box;
display: flex;
align-items: center;
.id {
margin-left: 15px;
width: 24px;
height: 24px;
background: #e7f3ff;
border-radius: 12px;
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 12px;
font-weight: 400;
line-height: 24px;
text-align: center;
}
.name {
margin-left: 13px;
width: 80px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
.line {
margin-left: 25px;
width: 166px;
height: 8px;
.inner-line {
height: 8px;
border-radius: 0px 4px 4px 0px;
background: linear-gradient(270deg, rgba(5, 95, 194, 1), rgba(5, 95, 194, 0) 100%);
}
}
.num {
margin-left: 17px;
width: 75px;
height: 30px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
}
.more {
margin-left: 25px;
width: 80px;
height: 30px;
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
}
&:nth-child(2n-1) {
border-top: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px;
background: rgba(247, 248, 249, 1);
}
}
}
}
}
}
}
</style>
const getPieChart = (data,colorList) => {
let option = {
color: colorList,
series: [
{
type: 'pie',
radius: [70, 100],
height: '100%',
left: 'center',
width: '100%',
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
label: {
alignTo: 'edge',
formatter: '{name|{b}}\n{time|{c} 条 {d}%}',
minMargin: 5,
edgeDistance: 10,
lineHeight: 15,
rich: {
time: {
fontSize: 10,
color: '#999'
}
}
},
labelLine: {
length: 15,
length2: 0,
maxSurfaceAngle: 80
},
labelLayout: function (params) {
const isLeft = params.labelRect.x < 556 / 2;
const points = params.labelLinePoints;
// Update the end point.
points[2][0] = isLeft
? params.labelRect.x
: params.labelRect.x + params.labelRect.width;
return {
labelLinePoints: points
};
},
data: data
}]
}
return option
}
export default getPieChart;
\ No newline at end of file
const getSankeyChart = () => {
const option = {
series: {
type: 'sankey',
layout: 'none',
left: '5%',
right: '5%',
top: '5%',
bottom: '5%',
emphasis: {
focus: 'adjacency'
},
nodeWidth: 50,
label: {
show: true,
formatter: function (params) {
return `${params.name} $${params.value}`;
},
position: 'right',
textStyle: {
fontSize: '16px',
color: '#555'
}
},
data: [
{
name: '马尔科·卢比奥',
label: {
position: 'left'
}
},
{
name: '成长俱乐部'
},
{
name: '埃利奥特管理公司'
},
{
name: '高盛集团'
},
{
name: '黑石集团'
},
{
name: '佛罗里达水晶'
},
{
name: '美国银行'
}
],
links: [
{
source: '成长俱乐部',
target: '马尔科·卢比奥',
value: 680751
},
{
source: '埃利奥特管理公司',
target: '马尔科·卢比奥',
value: 440120
},
{
source: '高盛集团',
target: '马尔科·卢比奥',
value: 371517
},
{
source: '黑石集团',
target: '马尔科·卢比奥',
value: 259321
},
{
source: '佛罗里达水晶',
target: '马尔科·卢比奥',
value: 203775
},
{
source: '美国银行',
target: '马尔科·卢比奥',
value: 150892
}
]
}
};
return option
}
export default getSankeyChart
\ No newline at end of file
<template>
<div>我是进程分析</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
</style>
<template> <template>
<div class="home-wrapper"> <div class="home-wrapper">
<div class="home-main"> <div class="search-header" v-show="isShow">
<div class="home-main-header-center">
<el-input v-model="input" style="width: 680px; height: 100%" placeholder="搜索科技政令" />
<div class="search">
<div class="search-icon">
<img src="./assets/images/search-icon.png" alt="" />
</div>
<div class="search-text">搜索</div>
</div>
</div>
<div class="home-main-header-btn-box">
<div class="btn">
<div class="btn-text">{{ "最新动态" }}</div>
<div class="btn-icon">{{ ">" }}</div>
</div>
<div class="btn">
<div class="btn-text">{{ "资讯要闻" }}</div>
<div class="btn-icon">{{ ">" }}</div>
</div>
<div class="btn">
<div class="btn-text">{{ "统计概览" }}</div>
<div class="btn-icon">{{ ">" }}</div>
</div>
<div class="btn">
<div class="btn-text">{{ "资源库" }}</div>
<div class="btn-icon">{{ ">" }}</div>
</div>
</div>
</div>
<div class="home-main" :class="{ scrollHomeMain: isShow }" ref="containerRef">
<div class="home-main-header"> <div class="home-main-header">
<div class="home-main-header-top"> <div class="home-main-header-top" v-show="!isShow">
<span>国家科技安全 </span>> <span>中美博弈概览 </span>> <span>国家科技安全 </span>> <span>中美博弈概览 </span>>
<span>科技政令</span> <span>科技政令</span>
</div> </div>
<div class="home-main-header-center"> <div class="home-main-header-center" v-show="!isShow">
<el-input v-model="input" style="width: 838px; height: 100%" placeholder="搜索科技政令" /> <el-input v-model="input" style="width: 838px; height: 100%" placeholder="搜索科技政令" />
<div class="search"> <div class="search">
<div class="search-icon"> <div class="search-icon">
...@@ -15,7 +44,7 @@ ...@@ -15,7 +44,7 @@
<div class="search-text">搜索</div> <div class="search-text">搜索</div>
</div> </div>
</div> </div>
<div class="home-main-header-footer"> <div class="home-main-header-footer" v-show="!isShow">
<div class="home-main-header-footer-item"> <div class="home-main-header-footer-item">
<div class="item-top">3.8T</div> <div class="item-top">3.8T</div>
<div class="item-footer">数据量</div> <div class="item-footer">数据量</div>
...@@ -37,7 +66,7 @@ ...@@ -37,7 +66,7 @@
<div class="item-footer">分析报告</div> <div class="item-footer">分析报告</div>
</div> </div>
</div> </div>
<div class="home-main-header-btn-box"> <div class="home-main-header-btn-box" v-show="!isShow">
<div class="btn"> <div class="btn">
<div class="btn-text">{{ "最新动态" }}</div> <div class="btn-text">{{ "最新动态" }}</div>
<div class="btn-icon">{{ ">" }}</div> <div class="btn-icon">{{ ">" }}</div>
...@@ -170,7 +199,57 @@ ...@@ -170,7 +199,57 @@
</div> </div>
</div> </div>
</div> </div>
<div class="center-center1"> <DivideHeader class="divide2" :titleText="'资讯要闻'"></DivideHeader>
<div class="center-center">
<div class="box3">
<div class="box3-header">
<div class="box3-header-left">
<div class="box3-header-icon">
<img src="./assets/images/box3-header-icon.png" alt="" />
</div>
<div class="box3-header-title">{{ "新闻资讯" }}</div>
</div>
</div>
<div class="box3-main">
<div class="box3-item" v-for="(news, index) in newsList" :key="index">
<div class="left">
<img :src="news.img" alt="" />
</div>
<div class="right">
<div class="right-top">
<div class="title">{{ news.title }}</div>
<div class="time">{{ news.from }}</div>
</div>
<div class="right-footer">{{ news.content }}</div>
</div>
</div>
</div>
</div>
<div class="box4">
<div class="box4-header">
<div class="header-icon">
<img src="./assets/images/box4-header-icon.png" alt="" />
</div>
<div class="header-title">{{ "社交媒体" }}</div>
<div class="more">{{ "更多 +" }}</div>
</div>
<div class="box4-main">
<div class="box4-main-item" v-for="(item, index) in messageList" :key="index">
<div class="left">
<img :src="item.img" alt="" />
</div>
<div class="right">
<div class="right-top">
<div class="name">{{ item.name }}</div>
<div class="time">{{ item.time }}</div>
</div>
<div class="content">{{ item.content }}</div>
</div>
</div>
</div>
</div>
</div>
<!-- <div class="center-center1">
<div <div
class="center1-item" class="center1-item"
:class="{ center1ItemActive: center1ActiveIndex === 0 }" :class="{ center1ItemActive: center1ActiveIndex === 0 }"
...@@ -239,8 +318,8 @@ ...@@ -239,8 +318,8 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div> -->
<div class="center-center2"> <!-- <div class="center-center2">
<div class="center2-header"> <div class="center2-header">
<div class="center2-header-left"> <div class="center2-header-left">
<div class="left"> <div class="left">
...@@ -356,7 +435,8 @@ ...@@ -356,7 +435,8 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div> -->
<DivideHeader class="divide3" :titleText="'数据总览'"></DivideHeader>
<div class="center-footer"> <div class="center-footer">
<div class="box3"> <div class="box3">
<div class="box3-header"> <div class="box3-header">
...@@ -422,6 +502,7 @@ ...@@ -422,6 +502,7 @@
</div> </div>
</div> </div>
<div class="home-main-footer"> <div class="home-main-footer">
<DivideHeader class="divide4" :titleText="'资源库'"></DivideHeader>
<div class="home-main-footer-header"> <div class="home-main-footer-header">
<div class="btn-box"> <div class="btn-box">
<div <div
...@@ -458,6 +539,13 @@ ...@@ -458,6 +539,13 @@
</div> </div>
</div> </div>
<div class="home-main-footer-main"> <div class="home-main-footer-main">
<div class="content-header">
<div class="icon">
<img src="./assets/images/box1-header-icon.png" alt="" />
</div>
<div class="title">{{ "政令库" }}</div>
</div>
<div class="content-box">
<div class="main-item" v-for="(decree, index) in curDecreeList" :key="index"> <div class="main-item" v-for="(decree, index) in curDecreeList" :key="index">
<div class="main-item-left"> <div class="main-item-left">
<div <div
...@@ -483,23 +571,41 @@ ...@@ -483,23 +571,41 @@
</div> </div>
</div> </div>
</div> </div>
<div class="footer-box">
<div class="footer-left">
{{ `共${decreeList.length}项调查` }}
</div>
<div class="footer-right">
<el-pagination
@current-change="handleCurrentChange"
:pageSize="10"
:current-page="currentPage"
background
layout="prev, pager, next"
:total="decreeList.length"
/>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { onMounted, ref } from "vue"; import { onMounted, ref, computed } from "vue";
import * as echarts from "echarts"; import * as echarts from "echarts";
import router from "@/router"; import router from "@/router";
import WordCloudMap from "./WordCloudMap.vue"; import WordCloudMap from "./WordCloudMap.vue";
import DivideHeader from "@/components/DivideHeader.vue"; import DivideHeader from "@/components/DivideHeader.vue";
import { useContainerScroll } from "@/hooks/useScrollShow";
import getMultiLineChart from "./utils/multiLineChart"; import getMultiLineChart from "./utils/multiLineChart";
import getBarChart from "./utils/barChart"; import getBarChart from "./utils/barChart";
import getPieChart from "./utils/piechart"; import getPieChart from "./utils/piechart";
import getCalendarHeatChart from "./utils/cleandarHeat"; import getCalendarHeatChart from "./utils/cleandarHeat";
import setChart from "@/utils/setChart";
import p1 from "./assets/images/iconp1.png"; import p1 from "./assets/images/iconp1.png";
import p2 from "./assets/images/iconp2.png"; import p2 from "./assets/images/iconp2.png";
import p3 from "./assets/images/iconp3.png"; import p3 from "./assets/images/iconp3.png";
...@@ -522,12 +628,26 @@ import Gov8 from "./assets/images/gov8.png"; ...@@ -522,12 +628,26 @@ import Gov8 from "./assets/images/gov8.png";
import Gov9 from "./assets/images/gov9.png"; import Gov9 from "./assets/images/gov9.png";
import Gov10 from "./assets/images/gov10.png"; import Gov10 from "./assets/images/gov10.png";
const center1ActiveIndex = ref(0); import News1 from "./assets/images/news1.png";
import News2 from "./assets/images/news2.png";
import News3 from "./assets/images/news3.png";
import News4 from "./assets/images/news4.png";
import News5 from "./assets/images/news5.png";
import Message1 from "./assets/images/message-icon1.png";
import Message2 from "./assets/images/message-icon2.png";
import Message3 from "./assets/images/message-icon3.png";
const handleClickCenter1Item = index => { const containerRef = ref(null);
center1ActiveIndex.value = index; const { isShow } = useContainerScroll(containerRef);
const currentPage = ref(1);
const pageSize = ref(10);
// 处理页码改变事件
const handleCurrentChange = page => {
currentPage.value = page;
}; };
// 页面 header
const govInsList = ref([ const govInsList = ref([
{ {
img: Gov1, img: Gov1,
...@@ -571,165 +691,172 @@ const govInsList = ref([ ...@@ -571,165 +691,172 @@ const govInsList = ref([
} }
]); ]);
const personList = ref([ // 最新科技政令
{ const tagList = ref([
name: "詹姆斯·JD·万斯",
posi: "副总统",
avator: p1
},
{
name: "马尔科·卢比奥",
posi: "国务卿",
avator: p2
},
{
name: "斯科特·贝森特",
posi: "财政部长",
avator: p3
},
{ {
name: "皮特·赫格塞斯", name: "互联网",
posi: "国防部长", status: 2
avator: p4
}, },
{ {
name: "帕姆·邦迪", name: "人工智能",
posi: "司法部长", status: 4
avator: p5 }
}, ]);
// 点击查看详情
const handleClickToDetail = () => {
router.push("/decreeLayout");
};
// 风险信号
const warningList = ref([
{ {
name: "霍华德·卢特尼克", title: "关于对中华人民共和国合成阿片类药物供应链...",
posi: "商务部长", time: "一天前",
avator: p6 status: "特别重大"
}, },
{ {
name: "苏西·威尔斯", title: "关于调整汽车及汽车零部件进口的公告",
posi: "白宫办公厅主任", time: "一天前",
avator: p7 status: "特别重大"
}, },
{ {
name: "克里斯蒂·诺姆", title: "关于调整钢铁进口的公告",
posi: "国土安全部长", time: "一天前",
avator: p8 status: "重大风险"
}, },
{ {
name: "道格·伯古姆", title: "关于使用互惠关税规范进口以纠正导致大规模...",
posi: "内政部长", time: "一天前",
avator: p9 status: "重大风险"
}, },
{ {
name: "克里斯·赖特", title: "关于修订对中华人民共和国低价值进口商品适...",
posi: "能源部长", time: "一天前",
avator: p10 status: "一般风险"
} }
]); ]);
const tabActiveIndex = ref(0); // 新闻资讯
const newsList = ref([
const list = [
{
title: "内政情况",
data: [
{ {
title: "司法与法律政策", img: News1,
tag: "司法改革", title: "美政府停摆仍持续,拨款法案存缺陷,但两党磋商露曙光",
content: `继续任命保守派法官至联邦各级范元、可能利用司法部调查政治对手,破坏司法部独立性传统。` content: `美国政府停摆已持续34天,距离历史上最长的停摆纪录仅差一天,参议院已先后13次尝试...`,
from: "11-4 · 华盛顿邮报"
}, },
{ {
title: "移民政策", img: News2,
tag: "边境安全", title: "美参议院通过决议,要求终止特朗普全球关税政策",
content: `重启并扩大美墨边境墙建设,启动大规模非法移民驱逐行动。恢复并加强"留在墨西哥"政策,限制庇护申请。` content: `参议院以51票赞成、47票反对通过一项决议,旨在终止特朗普实施的全面关税政策,四名......`,
from: "11-4 · 纽约时报"
}, },
{ {
title: "能源政策", img: News3,
tag: "能源独立", title: "美众院通过950亿美元对外援助法案,包含对台军援",
content: `推行"钻探、钻探、钻探"政策,全力扩大化石燃料(石油、天然气、煤炭)的生产,撤销清洁能源补贴和环保法规。` content: `国会众议院在4月通过了大规模对外援助法案,其中包括为“印太安全”提供资金的条款,......`,
from: "11-3 · 洛杉矶时报"
}, },
{ {
title: "关税政策", img: News4,
tag: "能征关税", title: "“大而美”法案在激烈争议中通过",
content: `全面加征关税,推行“对等关税”,将关税收入作为弥补减税造成的财政收入缺口的手段之一。` content: `特朗普力推的大规模税收与支出法案在国会以微弱优势通过。该法案因大幅削减医疗补助和......`,
from: "11-3 · 今日美国"
}, },
{ {
title: "外交政策", img: News5,
tag: "能华强硬", title: "美政府“停摆”追平历史最长纪录,民生多领域受重创",
content: `采取单边主义和交易性做法,对国际多边体系构成挑战,要求盟友承担更多成本,对华政策更趋强硬。` content: `联邦政府“停摆”进入第35天,追平历史纪录。食品救济项目资金中断,数百万低收入民......`,
from: "11-2 · ​福克斯新闻网"
} }
] ]);
},
{ // 社交媒体
title: "外交情况", const messageList = ref([
data: [
{ {
title: "司法与法律政策1", img: Message1,
tag: "司法改革", name: "唐纳德·特朗普",
content: `继续任命保守派法官至联邦各级范元、可能利用司法部调查政治对手,破坏司法部独立性传统。` time: "15:23 · 发布于真实社交",
content: `埃隆·马斯克在强力支持我竞选总统之前,早就知道我强烈反对‘电动汽车强制令’。这太荒谬了,这一直是我竞选活动的主要部分。电动汽车没问题,但不应该强迫每个人都拥有一辆。埃隆获得的补贴可能远远超过历史上任何一个人。如果没有补贴,埃隆可能不得不关门大吉,回到南非老家。`
}, },
{ {
title: "移民政策", img: Message2,
tag: "边境安全", name: "埃隆·马斯克",
content: `重启并扩大美墨边境墙建设,启动大规模非法移民驱逐行动。恢复并加强"留在墨西哥"政策,限制庇护申请。` time: "14:49 · 发布于X",
content: `如果这个疯狂的支出法案获得通过,‘美国党’将在第二天成立。`
}, },
{ {
title: "能源政策", img: Message3,
tag: "能源独立", name: "塞巴斯蒂安·马拉比",
content: `推行"钻探、钻探、钻探"政策,全力扩大化石燃料(石油、天然气、煤炭)的生产,撤销清洁能源补贴和环保法规。` time: "11:05 · 发布于X",
}, content: `提出特朗普政府的AI政策强调技术开放与快速应用,但可能以牺牲安全防范为代价,开启了“潘多拉魔盒”。`
}
]);
// 政令发布频度
const chart1Data = ref({
dataX: ["2019", "2020", "2021", "2022", "2023", "2024", "2025"],
dataY: [219, 228, 129, 159, 152, 157, 78]
});
// 政令涉及领域
const chart2Data = ref([
{ {
title: "关税政策", name: "集成电路",
tag: "能征关税", value: 50
content: `全面加征关税,推行“对等关税”,将关税收入作为弥补减税造成的财政收入缺口的手段之一。`
}, },
{ {
title: "外交政策", name: "人工智能",
tag: "能华强硬", value: 46
content: `采取单边主义和交易性做法,对国际多边体系构成挑战,要求盟友承担更多成本,对华政策更趋强硬。`
}
]
}, },
{ {
title: "经济情况", name: "通信网络",
data: [ value: 40
{
title: "司法与法律政策2",
tag: "司法改革",
content: `继续任命保守派法官至联邦各级范元、可能利用司法部调查政治对手,破坏司法部独立性传统。`
}, },
{ {
title: "移民政策", name: "量子科技",
tag: "边境安全", value: 32
content: `重启并扩大美墨边境墙建设,启动大规模非法移民驱逐行动。恢复并加强"留在墨西哥"政策,限制庇护申请。`
}, },
{ {
title: "能源政策", name: "能源",
tag: "能源独立", value: 31
content: `推行"钻探、钻探、钻探"政策,全力扩大化石燃料(石油、天然气、煤炭)的生产,撤销清洁能源补贴和环保法规。`
}, },
{ {
title: "关税政策", name: "生物科技",
tag: "能征关税", value: 30
content: `全面加征关税,推行“对等关税”,将关税收入作为弥补减税造成的财政收入缺口的手段之一。`
}, },
{ {
title: "外交政策", name: "航空航天",
tag: "能华强硬", value: 24
content: `采取单边主义和交易性做法,对国际多边体系构成挑战,要求盟友承担更多成本,对华政策更趋强硬。`
}
]
} }
]; ]);
const colorList = ["#69B1FF", "#FFC069", "#87E8DE", "#85A5FF", "#FF7875", "#B37FEB", "#4096FF"];
const tagList = ref([ // 关键政令及举措
const keyDecreeList = ref([
{ {
name: "互联网", title: "关于“对等关税”的行政令",
status: 2 time: "2025年4月",
content: `对所有贸易伙伴设立10%的“最低基准关税”,并对中国商品加征高达34%​​ 的额外关税,使针对中国的总关税水平大幅提升。`
}, },
{ {
name: "人工智能", title: "《美国优先投资政策》备忘录",
status: 4 time: "2025年2月",
content: `将中国列为“外国对手”,系统性收紧中美在半导体、人工智能、量子技术等前沿科技领域的双向投资,构建对华科技封锁体系。`
},
{
title: "针对TikTok的行政令",
time: "2025年2月",
content: `以所谓“信息安全”为由,要求字节跳动剥离TikTok在美业务,并禁止通过微信、支付宝等中国应用程序进行交易。`
},
{
title: "签署《外国投资风险审查现代化法》",
time: "2025年2月",
content: `极大加强了美国外国投资委员会(CFIUS)的权限,重点关注来自中国的投资。`
} }
]); ]);
// 政令重点条款
const wordCloudData = [ const wordCloudData = [
{ name: "与马斯克公开冲突", value: 100 }, { name: "与马斯克公开冲突", value: 100 },
{ name: "传统能源", value: 5 }, { name: "传统能源", value: 5 },
...@@ -751,131 +878,109 @@ const wordCloudData = [ ...@@ -751,131 +878,109 @@ const wordCloudData = [
{ name: "高压游说", value: 51 } { name: "高压游说", value: 51 }
]; ];
const handleClickToDetail = () => { // 资源库
router.push("/decreeLayout"); const decreeList = ref([
};
const warningList = ref([
{
title: "关于对中华人民共和国合成阿片类药物供应链...",
time: "一天前",
status: "特别重大"
},
{
title: "关于调整汽车及汽车零部件进口的公告",
time: "一天前",
status: "特别重大"
},
{ {
title: "关于调整钢铁进口的公告", type: "总统政令",
time: "一天前", status: 1,
status: "重大风险" title: "关于进一步延长TikTok执法宽限期的行政令",
time: "2025年9月16日"
}, },
{ {
title: "关于使用互惠关税规范进口以纠正导致大规模...", type: "总统政令",
time: "一天前", status: 1,
status: "重大风险" title: "为国家安全部署先进核反应堆技术",
time: "2025年9月16日"
}, },
{ {
title: "关于修订对中华人民共和国低价值进口商品适...", type: "总统政令",
time: "一天前", status: 1,
status: "一般风险" title: "修改对等关税税率以反映与中华人民共和国会谈情况的行政令",
} time: "2025年9月15日"
]);
const timelineList = ref([
{
title: "成为公法 No: 119-21。",
time: "2025-07-04",
status: 1
}, },
{ {
title: "总统签署", type: "总统政令",
time: "2025-07-04", status: 1,
status: 0 title: "调整互惠关税范围,并制定实施贸易和安全协议的程序",
time: "2025年9月15日"
}, },
{ {
title: "提交总统", type: "总统政令",
time: "2025-07-03", status: 1,
status: 0 title: "持续努力加强国家网络安全,并修订第13694号行政命令和第14144号行政命令",
time: "2025年9月14日"
}, },
{ {
title: "重新审议动议搁置案无异议通过。", type: "总统备忘录",
time: "2025-07-03 14:31", status: 3,
status: 0 title: "通过第232条款行动确保加工关键矿物及衍生产品的国家安全与经济韧性",
time: "2025年9月14日"
}, },
{ {
title: "关于‘众议院同意参议院修正案’...", type: "提名与任命",
time: "2025-07-02 14:31", status: 2,
status: 0 title: "终止对不可靠、非受控能源的市场扭曲补贴",
} time: "2025年9月11日"
]);
const areaList = ref([
{
name: "跨境电商",
status: 2
}, },
{ {
name: "新能源产业", type: "总统政令",
status: 4 status: 1,
title: "对所有国家暂停免关税待遇",
time: "2025年9月6日"
}, },
{ {
name: "半导体产业", type: "总统政令",
status: 1 status: 1,
title: "对所有国家暂停免关税待遇",
time: "2025年9月6日"
}, },
{ {
name: "关税", type: "总统政令",
status: 3 status: 1,
title: "对所有国家暂停免关税待遇",
time: "2025年9月6日"
}, },
{
name: "光伏产业",
status: 2
}
]);
const curDecreeList = ref([
{ {
type: "总统政令", type: "总统政令",
status: 1, status: 1,
title: "关于进一步延长TikTok执法宽限期的行政令", title: "对所有国家暂停免关税待遇",
time: "2025年9月16日" time: "2025年9月6日"
}, },
{ {
type: "总统政令", type: "总统政令",
status: 1, status: 1,
title: "为国家安全部署先进核反应堆技术", title: "对所有国家暂停免关税待遇",
time: "2025年9月16日" time: "2025年9月6日"
}, },
{ {
type: "总统政令", type: "总统政令",
status: 1, status: 1,
title: "修改对等关税税率以反映与中华人民共和国会谈情况的行政令", title: "对所有国家暂停免关税待遇",
time: "2025年9月15日" time: "2025年9月6日"
}, },
{ {
type: "总统政令", type: "总统政令",
status: 1, status: 1,
title: "调整互惠关税范围,并制定实施贸易和安全协议的程序", title: "对所有国家暂停免关税待遇",
time: "2025年9月15日" time: "2025年9月6日"
}, },
{ {
type: "总统政令", type: "总统政令",
status: 1, status: 1,
title: "持续努力加强国家网络安全,并修订第13694号行政命令和第14144号行政命令", title: "对所有国家暂停免关税待遇",
time: "2025年9月14日" time: "2025年9月6日"
}, },
{ {
type: "总统备忘录", type: "总统政令",
status: 3, status: 1,
title: "通过第232条款行动确保加工关键矿物及衍生产品的国家安全与经济韧性", title: "对所有国家暂停免关税待遇",
time: "2025年9月14日" time: "2025年9月6日"
}, },
{ {
type: "提名与任命", type: "总统政令",
status: 2, status: 1,
title: "终止对不可靠、非受控能源的市场扭曲补贴", title: "对所有国家暂停免关税待遇",
time: "2025年9月11日" time: "2025年9月6日"
}, },
{ {
type: "总统政令", type: "总统政令",
...@@ -884,9 +989,12 @@ const curDecreeList = ref([ ...@@ -884,9 +989,12 @@ const curDecreeList = ref([
time: "2025年9月6日" time: "2025年9月6日"
} }
]); ]);
const curDecreeList = computed(() => {
const startIndex = (currentPage.value - 1) * pageSize.value;
const endIndex = startIndex + pageSize.value;
return decreeList.value.slice(startIndex, endIndex);
});
const releaseTime = ref("近一年发布"); const releaseTime = ref("近一年发布");
const releaseTimeList = ref([ const releaseTimeList = ref([
{ {
label: "近半年发布", label: "近半年发布",
...@@ -909,126 +1017,13 @@ const releaseTimeList = ref([ ...@@ -909,126 +1017,13 @@ const releaseTimeList = ref([
value: "近五年发布" value: "近五年发布"
} }
]); ]);
const categoryList = ref(["全部分类", "总统政令", "提名与任命", "总统备忘录", "声明"]); const categoryList = ref(["全部分类", "总统政令", "提名与任命", "总统备忘录", "声明"]);
const activeCate = ref("全部分类"); const activeCate = ref("全部分类");
const activeHylyId = ref("");
// // 获取领域分类
// const handleGetHylyList = async () => {
// try {
// const res = await getHylyList();
// console.log("行业领域列表");
// categoryList.value = res.data;
// const obj = {
// id: 0,
// hylyid: "",
// hylymc: "全部分类",
// };
// categoryList.value = [obj, ...categoryList.value];
// } catch (error) {}
// };
const handleClickCate = cate => { const handleClickCate = cate => {
activeCate.value = cate; activeCate.value = cate;
}; };
const activeNavIndex = ref(0);
const handleClickNav = (index, item) => {
activeNavIndex.value = index;
router.push(item.path);
};
// 绘制echarts图表
const setChart = (option, chartId) => {
let chartDom = document.getElementById(chartId);
chartDom.removeAttribute("_echarts_instance_");
let chart = echarts.init(chartDom);
chart.setOption(option);
return chart;
};
const chart1Data = ref({
dataX: ["2019", "2020", "2021", "2022", "2023", "2024", "2025"],
dataY: [219, 228, 129, 159, 152, 157, 78]
});
const chart2Data = ref([
{
name: "集成电路",
value: 50
},
{
name: "人工智能",
value: 46
},
{
name: "通信网络",
value: 40
},
{
name: "量子科技",
value: 32
},
{
name: "能源",
value: 31
},
{
name: "生物科技",
value: 30
},
{
name: "航空航天",
value: 24
}
]);
const colorList = ["#69B1FF", "#FFC069", "#87E8DE", "#85A5FF", "#FF7875", "#B37FEB", "#4096FF"];
// 根据法案类型获取法案列表
// const handleGetBillsByType = async () => {
// const params = {
// type: activeHylyId.value,
// };
// try {
// const res = await getBillsByType(params);
// console.log("根据法案类型获取法案列表", res);
// curDecreeList.value = res.data.map((item) => {
// return {
// billId: item.billId,
// billName: item.billName,
// introductionDate: item.introductionDate,
// img: bill1,
// };
// });
// } catch (error) {}
// };
const keyDecreeList = ref([
{
title: "关于“对等关税”的行政令",
time: "2025年4月",
content: `对所有贸易伙伴设立10%的“最低基准关税”,并对中国商品加征高达34%​​ 的额外关税,使针对中国的总关税水平大幅提升。`
},
{
title: "《美国优先投资政策》备忘录",
time: "2025年2月",
content: `将中国列为“外国对手”,系统性收紧中美在半导体、人工智能、量子技术等前沿科技领域的双向投资,构建对华科技封锁体系。`
},
{
title: "针对TikTok的行政令",
time: "2025年2月",
content: `以所谓“信息安全”为由,要求字节跳动剥离TikTok在美业务,并禁止通过微信、支付宝等中国应用程序进行交易。`
},
{
title: "签署《外国投资风险审查现代化法》",
time: "2025年2月",
content: `极大加强了美国外国投资委员会(CFIUS)的权限,重点关注来自中国的投资。`
}
]);
const calendarData = ref([ const calendarData = ref([
["2025-01-01", 20], ["2025-01-01", 20],
...@@ -1089,10 +1084,106 @@ onMounted(async () => { ...@@ -1089,10 +1084,106 @@ onMounted(async () => {
box-shadow: none; box-shadow: none;
} }
.home-wrapper { .home-wrapper {
width: 100%;
height: calc(100vh - 96px);
position: relative;
overflow-y: hidden;
.search-header {
width: 100%;
height: 144px;
background: #fff;
overflow: hidden;
.home-main-header-center {
margin-top: 20px;
margin-left: 200px;
width: 800px;
height: 48px;
border-radius: 10px;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
padding: 1px;
position: relative;
.search {
position: absolute;
right: 1px;
top: 2px;
width: 120px;
height: 44px;
border-radius: 10px;
background: var(--color-main-active);
display: flex;
justify-content: center;
align-items: center;
.search-icon {
width: 18px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
.search-text {
margin-left: 8px;
height: 22px;
color: #fff;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 22px;
}
}
}
.home-main-header-btn-box {
margin-top: 20px;
margin-left: 200px;
display: flex;
gap: 16px;
.btn {
display: flex;
width: 140px;
height: 36px;
border: 1px solid #aed6ff;
box-sizing: border-box;
border-radius: 18px;
justify-content: center;
background: #e7f3ff;
position: relative;
cursor: pointer;
&:hover {
background: #cae3fc;
}
.btn-text {
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
line-height: 36px;
margin-left: 5px;
}
.btn-icon {
height: 20px;
line-height: 20px;
position: absolute;
top: 6px;
right: 8px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
}
}
}
}
.scrollHomeMain {
width: 100%;
height: calc(100% - 144px);
overflow-y: auto;
}
.home-main { .home-main {
// width: 1400px;
width: 100%; width: 100%;
margin: 0 auto; height: 100%;
overflow-y: auto;
background: url("./assets/images/background.png"); background: url("./assets/images/background.png");
background-size: 100% 100%; background-size: 100% 100%;
.home-main-header { .home-main-header {
...@@ -1128,11 +1219,11 @@ onMounted(async () => { ...@@ -1128,11 +1219,11 @@ onMounted(async () => {
.search { .search {
position: absolute; position: absolute;
right: 1px; right: 1px;
top: 1px; top: 2px;
width: 120px; width: 120px;
height: 42px; height: 44px;
border-radius: 4px; border-radius: 10px;
background: rgba(22, 119, 255, 1); background: var(--color-main-active);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
...@@ -1236,7 +1327,8 @@ onMounted(async () => { ...@@ -1236,7 +1327,8 @@ onMounted(async () => {
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1); box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 0.65); background: rgba(255, 255, 255, 0.65);
align-items: center; align-items: center;
margin:0 6px 16px 6px; margin: 0 6px 16px 6px;
cursor: pointer;
.item-left { .item-left {
width: 48px; width: 48px;
height: 48px; height: 48px;
...@@ -1605,6 +1697,225 @@ onMounted(async () => { ...@@ -1605,6 +1697,225 @@ onMounted(async () => {
} }
} }
} }
.divide2 {
width: 1600px;
margin: 0 auto;
margin-top: 68px;
margin-bottom: 36px;
}
.center-center {
width: 1600px;
margin: 0 auto;
margin-top: 21px;
height: 450px;
display: flex;
.box3 {
width: 792px;
height: 450px;
box-shadow: 0px 0px 15px 0px rgba(25, 69, 130, 0.2);
background: rgba(255, 255, 255, 1);
.box3-header {
height: 48px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
margin: 0 auto;
display: flex;
justify-content: space-between;
padding: 0 20px;
.box3-header-left {
display: flex;
.box3-header-icon {
margin-top: 16px;
width: 19px;
height: 19px;
img {
width: 100%;
height: 100%;
}
}
.box3-header-title {
margin-top: 16px;
margin-left: 19px;
height: 22px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 22px;
}
}
}
.box3-main {
height: 402px;
overflow-y: auto;
overflow-x: hidden;
padding-top: 6px;
.box3-item {
display: flex;
height: 77px;
width: 749px;
margin-left: 21px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
.left {
width: 72px;
height: 48px;
margin-top: 15px;
img {
width: 100%;
height: 100%;
}
}
.right {
width: 657px;
margin-left: 20px;
.right-top {
width: 657px;
display: flex;
justify-content: space-between;
.title {
margin-top: 13px;
width: 520px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.time {
flex: 1;
text-align: right;
height: 22px;
margin-top: 19px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
}
.right-footer {
width: 657px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
}
.box4 {
margin-left: 20px;
width: 792px;
height: 450px;
box-shadow: 0px 0px 15px 0px rgba(25, 69, 130, 0.2);
background: rgba(255, 255, 255, 1);
.box4-header {
width: 792px;
height: 48px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
display: flex;
box-sizing: border-box;
padding-left: 22px;
position: relative;
.header-icon {
margin-top: 15px;
width: 20px;
height: 20px;
img {
width: 100%;
height: 100%;
}
}
.header-title {
margin-top: 16px;
margin-left: 18px;
height: 22px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 22px;
}
.more {
width: 49px;
height: 24px;
position: absolute;
top: 14px;
right: 27px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
cursor: pointer;
}
}
.box4-main {
height: 402px;
overflow-y: auto;
box-sizing: border-box;
padding-top: 8px;
.box4-main-item {
margin-top: 16px;
display: flex;
margin-left: 21px;
.left {
margin-top: 5px;
width: 36px;
height: 36px;
img {
width: 100%;
height: 100%;
}
}
.right {
margin-left: 10px;
width: 690px;
box-sizing: border-box;
border: 1px solid rgba(231, 243, 255, 1);
background: rgba(246, 250, 255, 1);
padding: 10px 15px;
.right-top {
display: flex;
justify-content: space-between;
.name {
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
.time {
height: 30px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
}
}
.content {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
}
}
}
}
.center-center1 { .center-center1 {
margin: 0 auto; margin: 0 auto;
margin-top: 24px; margin-top: 24px;
...@@ -2030,6 +2341,12 @@ onMounted(async () => { ...@@ -2030,6 +2341,12 @@ onMounted(async () => {
} }
} }
} }
.divide3 {
width: 1600px;
margin: 0 auto;
margin-top: 68px;
margin-bottom: 36px;
}
.center-footer { .center-footer {
margin-top: 21px; margin-top: 21px;
height: 452px; height: 452px;
...@@ -2267,9 +2584,15 @@ onMounted(async () => { ...@@ -2267,9 +2584,15 @@ onMounted(async () => {
} }
} }
.home-main-footer { .home-main-footer {
// width: 100%; margin-top: 34px;
height: 911px; height: 1379px;
background: rgba(248, 249, 250, 1); background: rgba(248, 249, 250, 1);
overflow: hidden;
.divide4 {
margin: 0 auto;
margin-top: 52px;
margin-bottom: 36px;
}
.home-main-footer-header { .home-main-footer-header {
width: 1600px; width: 1600px;
height: 42px; height: 42px;
...@@ -2317,13 +2640,39 @@ onMounted(async () => { ...@@ -2317,13 +2640,39 @@ onMounted(async () => {
} }
.home-main-footer-main { .home-main-footer-main {
width: 1600px; width: 1600px;
height: 685px; height: 999px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2); box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
margin: 0 auto; margin: 0 auto;
box-sizing: border-box; box-sizing: border-box;
padding: 10px 20px 0 20px; border-radius: 10px;
overflow-y: auto; .content-header {
height: 48px;
display: flex;
border-bottom: 1px solid rgba(234, 236, 238, 1);
.icon {
width: 20px;
height: 20px;
margin-top: 14px;
margin-left: 19px;
img {
width: 100%;
height: 100%;
}
}
.title {
height: 48px;
margin-left: 21px;
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 48px;
}
}
.content-box {
height: 850px;
margin: 0 30px;
.main-item { .main-item {
display: flex; display: flex;
height: 84px; height: 84px;
...@@ -2407,11 +2756,26 @@ onMounted(async () => { ...@@ -2407,11 +2756,26 @@ onMounted(async () => {
} }
} }
} }
.footer-box {
margin: 0 30px;
height: 32px;
margin-top: 30px;
display: flex;
justify-content: space-between;
.footer-left {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 32px;
}
}
}
} }
} }
} }
.divide{ .divide {
margin: 0 auto; margin: 0 auto;
} }
</style> </style>
\ No newline at end of file
<template> <template>
<div class="wrap"> <div class="wrap">
<div class="box1"> <!-- <div class="box1">
<div class="box-header"> <div class="box-header">
<div class="header-left"></div> <div class="header-left"></div>
<div class="title">政令时序及战略里程碑</div> <div class="title">政令时序及战略里程碑</div>
...@@ -46,13 +46,18 @@ ...@@ -46,13 +46,18 @@
<img src="./assets/icons/box1-icon3.png" alt="" /> <img src="./assets/icons/box1-icon3.png" alt="" />
</div> </div>
</div> </div>
</div> </div> -->
<div class="box2"> <div class="box2">
<div class="box-header"> <div class="box-header">
<div class="header-left"></div> <div class="header-left"></div>
<div class="title">相关政令关联分析</div> <div class="title">相关政令关联分析</div>
<div class="header-right"> <div class="header-right">
<img src="./assets/icons/header-icon.png" alt="" /> <div class="icon">
<img src="../assets/icons/header-right-icon1.png" alt="" />
</div>
<div class="icon">
<img src="../assets/icons/header-right-icon2.png" alt="" />
</div>
</div> </div>
</div> </div>
<div class="box2-main"> <div class="box2-main">
...@@ -113,11 +118,7 @@ ...@@ -113,11 +118,7 @@
<div class="title">{{ "政令主要内容" }}</div> <div class="title">{{ "政令主要内容" }}</div>
</div> </div>
<div class="list-main"> <div class="list-main">
<div <div class="list-item" v-for="(val, idx) in decreeList[box2LeftActiveIndex].list" :key="idx">
class="list-item"
v-for="(val, idx) in decreeList[box2LeftActiveIndex].list"
:key="idx"
>
<div class="id">{{ idx + 1 }}</div> <div class="id">{{ idx + 1 }}</div>
<div class="title">{{ val.title }}</div> <div class="title">{{ val.title }}</div>
<div class="open"> <div class="open">
...@@ -126,6 +127,21 @@ ...@@ -126,6 +127,21 @@
</div> </div>
</div> </div>
</div> </div>
<div class="list-footer">
<div class="footer-left">
{{ `共${decreeList[box2LeftActiveIndex].list.length}项动态` }}
</div>
<div class="footer-right">
<el-pagination
@current-change="handleCurrentChange"
:pageSize="pageSize"
:current-page="currentPage"
background
layout="prev, pager, next"
:total="decreeList[box2LeftActiveIndex].list.length"
/>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -136,35 +152,38 @@ ...@@ -136,35 +152,38 @@
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import box2InfoImg from "./assets/icons/box2-info.png"; import box2InfoImg from "./assets/icons/box2-info.png";
const pageSize = ref(10);
const currentPage = ref(1);
const box1BtnActive = ref(1); const box1BtnActive = ref(1);
const timeLineList = ref([ const timeLineList = ref([
{ {
time: "2025年1月", time: "2025年1月",
title: "《AI扩散暂行最终规则》发布", title: "《AI扩散暂行最终规则》发布",
content: "拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。", content: "拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。"
}, },
{ {
time: "2025年5月", time: "2025年5月",
title: "特朗普宣布撤销拜登AI规则", title: "特朗普宣布撤销拜登AI规则",
content: "特朗普政府宣布撤销拜登AI规则,计划推出新规。", content: "特朗普政府宣布撤销拜登AI规则,计划推出新规。"
}, },
{ {
time: "2025年7月23日", time: "2025年7月23日",
title: "特朗普签署EO 14320", title: "特朗普签署EO 14320",
content: "特朗普签署EO 14320,推动美国AI技术栈出口。", content: "特朗普签署EO 14320,推动美国AI技术栈出口。"
}, },
{ {
time: "2025年7月31日", time: "2025年7月31日",
title: "中国网信办约谈英伟达", title: "中国网信办约谈英伟达",
content: content: "中国网信办约谈英伟达,要求就H20算力芯片漏洞后门安全风险问题进行说明。"
"中国网信办约谈英伟达,要求就H20算力芯片漏洞后门安全风险问题进行说明。",
}, },
{ {
time: "2025年8月", time: "2025年8月",
title: "英伟达H20发放出口许可证", title: "英伟达H20发放出口许可证",
content: "美国商务部为4月份被实质禁售的英伟达H20发放出口许可证。", content: "美国商务部为4月份被实质禁售的英伟达H20发放出口许可证。"
}, }
]); ]);
const decreeList = ref([ const decreeList = ref([
...@@ -173,43 +192,41 @@ const decreeList = ref([ ...@@ -173,43 +192,41 @@ const decreeList = ref([
title: "拜登人工智能政令", title: "拜登人工智能政令",
img: box2InfoImg, img: box2InfoImg,
totalTitle: "关于安全、可靠和可信地开发和使用人工智能的行政命令", totalTitle: "关于安全、可靠和可信地开发和使用人工智能的行政命令",
eTotalTitle: eTotalTitle: "Executive Order on the Safe, Secure, and Trustworthy Development and Use of Artificial Intelligence",
"Executive Order on the Safe, Secure, and Trustworthy Development and Use of Artificial Intelligence",
signTime: "2025年7月23日", signTime: "2025年7月23日",
signPerson: "乔·拜登(Joe Biden)", signPerson: "乔·拜登(Joe Biden)",
list: [ list: [
{ {
title: title: "要求强大AI系统开发者与政府分享安全测试结果(“红队测试”);制定生物合成筛查标准防范风险;建立AI生成内容鉴别标准"
"要求强大AI系统开发者与政府分享安全测试结果(“红队测试”);制定生物合成筛查标准防范风险;建立AI生成内容鉴别标准", },
{
title: "优先支持隐私保护技术(PET)研发;评估各机构如何收集和使用商业信息;制定评估隐私保护技术有效性的指南。"
}, },
{ {
title: title: "为解决算法歧视提供明确指导;确保刑事司法系统中AI使用的公平性;协调调查和起诉AI相关的民权侵犯行为。"
"优先支持隐私保护技术(PET)研发;评估各机构如何收集和使用商业信息;制定评估隐私保护技术有效性的指南。",
}, },
{ {
title: title: "推动医疗保健领域负责任地使用AI;创造资源支持教育工作者部署AI教育工具。"
"为解决算法歧视提供明确指导;确保刑事司法系统中AI使用的公平性;协调调查和起诉AI相关的民权侵犯行为。",
}, },
{ {
title: title: "制定减轻AI对工人潜在危害的原则和最佳实践;编写AI对劳动力市场潜在影响的报告。"
"推动医疗保健领域负责任地使用AI;创造资源支持教育工作者部署AI教育工具。",
}, },
{ {
title: title: "通过“国家AI研究资源”(NAIRR)试点促进研究;为小型开发者和企业家提供技术援助和资源;简化相关领域高技能人才的签证流程。"
"制定减轻AI对工人潜在危害的原则和最佳实践;编写AI对劳动力市场潜在影响的报告。",
}, },
{ {
title: title: "扩大在AI领域的国际合作;与国际伙伴和标准组织加速制定AI标准。"
"通过“国家AI研究资源”(NAIRR)试点促进研究;为小型开发者和企业家提供技术援助和资源;简化相关领域高技能人才的签证流程。",
}, },
{ {
title: "扩大在AI领域的国际合作;与国际伙伴和标准组织加速制定AI标准。", title: "发布政府机构使用AI的指南;加快招聘AI专业人才并为相关领域员工提供培训。"
}, },
{ {
title: title: "发布政府机构使用AI的指南;加快招聘AI专业人才并为相关领域员工提供培训。"
"发布政府机构使用AI的指南;加快招聘AI专业人才并为相关领域员工提供培训。",
}, },
], {
title: "发布政府机构使用AI的指南;加快招聘AI专业人才并为相关领域员工提供培训。"
}
]
}, },
{ {
time: "2023", time: "2023",
...@@ -219,7 +236,7 @@ const decreeList = ref([ ...@@ -219,7 +236,7 @@ const decreeList = ref([
eTotalTitle: "", eTotalTitle: "",
signTime: "", signTime: "",
signPerson: "", signPerson: "",
list: [], list: []
}, },
{ {
time: "2025", time: "2025",
...@@ -229,7 +246,7 @@ const decreeList = ref([ ...@@ -229,7 +246,7 @@ const decreeList = ref([
eTotalTitle: "", eTotalTitle: "",
signTime: "", signTime: "",
signPerson: "", signPerson: "",
list: [], list: []
}, },
{ {
time: "2023", time: "2023",
...@@ -239,7 +256,7 @@ const decreeList = ref([ ...@@ -239,7 +256,7 @@ const decreeList = ref([
eTotalTitle: "", eTotalTitle: "",
signTime: "", signTime: "",
signPerson: "", signPerson: "",
list: [], list: []
}, },
{ {
time: "2024", time: "2024",
...@@ -249,8 +266,8 @@ const decreeList = ref([ ...@@ -249,8 +266,8 @@ const decreeList = ref([
eTotalTitle: "", eTotalTitle: "",
signTime: "", signTime: "",
signPerson: "", signPerson: "",
list: [], list: []
}, }
]); ]);
const box2LeftActiveIndex = ref(0); const box2LeftActiveIndex = ref(0);
...@@ -293,14 +310,19 @@ const box2LeftActiveIndex = ref(0); ...@@ -293,14 +310,19 @@ const box2LeftActiveIndex = ref(0);
position: absolute; position: absolute;
top: 14px; top: 14px;
right: 12px; right: 12px;
width: 32px; height: 28px;
height: 32px; display: flex;
gap: 4px;
.icon {
width: 28px;
height: 28px;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
} }
}
.box1 { .box1 {
margin: 27px auto 16px; margin: 27px auto 16px;
width: 1600px; width: 1600px;
...@@ -453,9 +475,9 @@ const box2LeftActiveIndex = ref(0); ...@@ -453,9 +475,9 @@ const box2LeftActiveIndex = ref(0);
} }
} }
.box2 { .box2 {
margin: 0 auto 10px; margin: 16px auto;
width: 1600px; width: 1600px;
height: 751px; height: 898px;
border-radius: 4px; border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2); box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
...@@ -514,7 +536,6 @@ const box2LeftActiveIndex = ref(0); ...@@ -514,7 +536,6 @@ const box2LeftActiveIndex = ref(0);
.right { .right {
margin-left: 36px; margin-left: 36px;
.info-box { .info-box {
margin-top: 25px;
margin-left: 28px; margin-left: 28px;
width: 1180px; width: 1180px;
height: 188px; height: 188px;
...@@ -610,7 +631,7 @@ const box2LeftActiveIndex = ref(0); ...@@ -610,7 +631,7 @@ const box2LeftActiveIndex = ref(0);
} }
} }
.list-main { .list-main {
height: 400px; height: 540px;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
.list-item { .list-item {
...@@ -655,6 +676,20 @@ const box2LeftActiveIndex = ref(0); ...@@ -655,6 +676,20 @@ const box2LeftActiveIndex = ref(0);
} }
} }
} }
.list-footer {
margin-left: 35px;
height: 32px;
margin-top: 10px;
display: flex;
justify-content: space-between;
.footer-left {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 32px;
}
}
} }
} }
} }
......
...@@ -7,28 +7,25 @@ ...@@ -7,28 +7,25 @@
<div class="title">提出背景</div> <div class="title">提出背景</div>
<div class="header-btn-box"> <div class="header-btn-box">
<div class="btn" @click="handleClickBox1Btn(1)"> <div class="btn" @click="handleClickBox1Btn(1)">
<el-button type="primary" plain v-if="box1BtnActive === 1" <el-button type="primary" plain v-if="box1BtnActive === 1">涉华背景</el-button>
>涉华背景</el-button
>
<el-button type="info" plain v-else>涉华背景</el-button> <el-button type="info" plain v-else>涉华背景</el-button>
</div> </div>
<div class="btn" @click="handleClickBox1Btn(2)"> <div class="btn" @click="handleClickBox1Btn(2)">
<el-button type="primary" plain v-if="box1BtnActive === 2" <el-button type="primary" plain v-if="box1BtnActive === 2">全部背景</el-button>
>全部背景</el-button
>
<el-button type="info" plain v-else>全部背景</el-button> <el-button type="info" plain v-else>全部背景</el-button>
</div> </div>
</div> </div>
<div class="header-right"> <div class="header-right">
<img src="../assets/icons/header-icon.png" alt="" /> <div class="icon">
<img src="../assets/icons/header-right-icon1.png" alt="" />
</div>
<div class="icon">
<img src="../assets/icons/header-right-icon2.png" alt="" />
</div>
</div> </div>
</div> </div>
<div class="box1-main"> <div class="box1-main">
<div <div class="box1-item" v-for="(item, index) in backgroundList" :key="index">
class="box1-item"
v-for="(item, index) in backgroundList"
:key="index"
>
<div class="id">{{ index + 1 }}</div> <div class="id">{{ index + 1 }}</div>
<div class="title">{{ item.title }}</div> <div class="title">{{ item.title }}</div>
<div class="open"> <div class="open">
...@@ -39,12 +36,7 @@ ...@@ -39,12 +36,7 @@
<div class="box1-footer"> <div class="box1-footer">
<div class="box1-footer-left">{{ "共计10条指令" }}</div> <div class="box1-footer-left">{{ "共计10条指令" }}</div>
<div class="box1-footer-right"> <div class="box1-footer-right">
<el-pagination <el-pagination :page-size="5" background layout="prev, pager, next" :total="10" />
:page-size="5"
background
layout="prev, pager, next"
:total="10"
/>
</div> </div>
</div> </div>
</div> </div>
...@@ -53,15 +45,16 @@ ...@@ -53,15 +45,16 @@
<div class="header-left"></div> <div class="header-left"></div>
<div class="title">相关事件</div> <div class="title">相关事件</div>
<div class="header-right"> <div class="header-right">
<img src="../assets/icons/header-icon.png" alt="" /> <div class="icon">
<img src="../assets/icons/header-right-icon1.png" alt="" />
</div>
<div class="icon">
<img src="../assets/icons/header-right-icon2.png" alt="" />
</div>
</div> </div>
</div> </div>
<div class="box2-main"> <div class="box2-main">
<div <div class="box2-item" v-for="(item, index) in relatedEvents" :key="index">
class="box2-item"
v-for="(item, index) in relatedEvents"
:key="index"
>
<div class="item-left"> <div class="item-left">
<img :src="item.image" alt="" /> <img :src="item.image" alt="" />
</div> </div>
...@@ -84,7 +77,12 @@ ...@@ -84,7 +77,12 @@
<div class="title">法律依据</div> <div class="title">法律依据</div>
<div class="header-right"> <div class="header-right">
<img src="../assets/icons/header-icon.png" alt="" /> <div class="icon">
<img src="../assets/icons/header-right-icon1.png" alt="" />
</div>
<div class="icon">
<img src="../assets/icons/header-right-icon2.png" alt="" />
</div>
</div> </div>
</div> </div>
<div class="box3-main"> <div class="box3-main">
...@@ -115,23 +113,20 @@ const box1BtnActive = ref(1); ...@@ -115,23 +113,20 @@ const box1BtnActive = ref(1);
const backgroundList = ref([ const backgroundList = ref([
{ {
title: title: "认为人工智能(AI)是一项将决定未来几十年经济增长、国家安全和全球竞争力的基础性技术"
"认为人工智能(AI)是一项将决定未来几十年经济增长、国家安全和全球竞争力的基础性技术",
}, },
{ {
title: title: "要求美国不仅必须在开发通用和前沿AI能力方面领先,还必须确保美国的人工智能技术、标准和治理模式在全球范围内被采用"
"要求美国不仅必须在开发通用和前沿AI能力方面领先,还必须确保美国的人工智能技术、标准和治理模式在全球范围内被采用",
}, },
{ {
title: "要求加强与盟友的关系并确保我们持续的技术主导地位", title: "要求加强与盟友的关系并确保我们持续的技术主导地位"
}, },
{ {
title: title: "计划通过支持美国原产人工智能技术的全球部署,以维护和扩大美国在人工智能领域的领导地位"
"计划通过支持美国原产人工智能技术的全球部署,以维护和扩大美国在人工智能领域的领导地位",
}, },
{ {
title: "目的为减少国际社会对由中国开发的人工智能技术的依赖", title: "目的为减少国际社会对由中国开发的人工智能技术的依赖"
}, }
]); ]);
const relatedEvents = ref([ const relatedEvents = ref([
...@@ -140,36 +135,34 @@ const relatedEvents = ref([ ...@@ -140,36 +135,34 @@ const relatedEvents = ref([
title: "中美AI模型性能差距迅速缩小", title: "中美AI模型性能差距迅速缩小",
content: content:
"斯坦福大学《2025年人工智能指数报告》显示,中美顶尖AI模型在MMLU(大规模多任务语言理解)等主流基准测试中的性能...", "斯坦福大学《2025年人工智能指数报告》显示,中美顶尖AI模型在MMLU(大规模多任务语言理解)等主流基准测试中的性能...",
time: "2025-08-30", time: "2025-08-30"
}, },
{ {
image: Img2, image: Img2,
title: "中国模型以更低成本实现高性能", title: "中国模型以更低成本实现高性能",
content: content: "2025年1月,中国公司深度求索(DeepSeek)发布高性能AI推理模型R1,以其极低的训练成本和媲美顶级模型的推理能力受...",
"2025年1月,中国公司深度求索(DeepSeek)发布高性能AI推理模型R1,以其极低的训练成本和媲美顶级模型的推理能力受...", time: "2025-05-16"
time: "2025-05-16",
}, },
{ {
image: Img3, image: Img3,
title: "美国发布《赢得AI竞赛:美国AI行动计划》​", title: "美国发布《赢得AI竞赛:美国AI行动计划》​",
content: content:
"特朗普政府发布该计划,核心包括加速创新​(解除监管)、建设AI基础设施​(加速数据中心审批、保障能源供应)和引领国际...", "特朗普政府发布该计划,核心包括加速创新​(解除监管)、建设AI基础设施​(加速数据中心审批、保障能源供应)和引领国际...",
time: "2025-07-23", time: "2025-07-23"
}, },
{ {
image: Img4, image: Img4,
title: "中国深入推进“人工智能+”行动", title: "中国深入推进“人工智能+”行动",
content: content: "中国国务院常务会议审议通过《关于深入实施“人工智能+”行动的意见》,大力推进AI在各领域的规模化商业化应用和和深...",
"中国国务院常务会议审议通过《关于深入实施“人工智能+”行动的意见》,大力推进AI在各领域的规模化商业化应用和和深...", time: "2025-07-31"
time: "2025-07-31",
}, },
{ {
image: Img5, image: Img5,
title: "美国对华AI芯片出口管制持续升级", title: "美国对华AI芯片出口管制持续升级",
content: content:
"美国商务部宣布撤销拜登时期的《AI扩散规则》,要求全球使用美国技术的芯片厂商停止向中国出口AI芯片,直接影响英伟达...", "美国商务部宣布撤销拜登时期的《AI扩散规则》,要求全球使用美国技术的芯片厂商停止向中国出口AI芯片,直接影响英伟达...",
time: "2025-05-20", time: "2025-05-20"
}, }
]); ]);
const laws = ref([ const laws = ref([
...@@ -177,32 +170,30 @@ const laws = ref([ ...@@ -177,32 +170,30 @@ const laws = ref([
name: "《美国法典》", name: "《美国法典》",
info: "第3编第301条", info: "第3编第301条",
content: content:
"允许总统通过行政命令(Executive Order)​​ 或其它书面形式授权行政部门或机构的负责人​(如国务卿、财政部长等)代行本属于总统的法定职能(由国会立法授予总统的职能)。", "允许总统通过行政命令(Executive Order)​​ 或其它书面形式授权行政部门或机构的负责人​(如国务卿、财政部长等)代行本属于总统的法定职能(由国会立法授予总统的职能)。"
}, },
{ {
name: "《出口管制改革法案》", name: "《出口管制改革法案》",
info: "", info: "",
content: content:
"该法案授权政府出于国家安全和外交政策目的对特定技术、商品和软件的出口进行管制。确保AI技术不流向“对手国家”是其题中应有之义。", "该法案授权政府出于国家安全和外交政策目的对特定技术、商品和软件的出口进行管制。确保AI技术不流向“对手国家”是其题中应有之义。"
}, },
{ {
name: "《国际紧急经济权力法》", name: "《国际紧急经济权力法》",
info: "", info: "",
content: content:
"授予总统在应对“不寻常且极其严重的威胁”时,监管商业和金融交易的广泛权力,包括实施出口管制。这在以往的贸易和科技管制中常被引用。", "授予总统在应对“不寻常且极其严重的威胁”时,监管商业和金融交易的广泛权力,包括实施出口管制。这在以往的贸易和科技管制中常被引用。"
}, },
{ {
name: "《2019年通过外交捍卫美国商业法》", name: "《2019年通过外交捍卫美国商业法》",
info: "第708(c)(3)条", info: "第708(c)(3)条",
content: content: "授权小企业管理局局长和OSTP主任任命其各自行政部门和机构的高级官员担任EDAG成员。"
"授权小企业管理局局长和OSTP主任任命其各自行政部门和机构的高级官员担任EDAG成员。",
}, },
{ {
name: "《关于安全、可靠和可信地开发和使用人工智能的行政命令》", name: "《关于安全、可靠和可信地开发和使用人工智能的行政命令》",
info: "", info: "",
content: content: "要求强大AI系统的开发者与政府共享安全测试结果,并为AI安全、隐私保护、公平权利及创新竞争等方面制定标准。"
"要求强大AI系统的开发者与政府共享安全测试结果,并为AI安全、隐私保护、公平权利及创新竞争等方面制定标准。", }
},
]); ]);
</script> </script>
...@@ -234,7 +225,7 @@ const laws = ref([ ...@@ -234,7 +225,7 @@ const laws = ref([
.header-btn-box { .header-btn-box {
position: absolute; position: absolute;
top: 14px; top: 14px;
right: 52px; right: 84px;
display: flex; display: flex;
.btn { .btn {
margin-left: 8px; margin-left: 8px;
...@@ -244,14 +235,19 @@ const laws = ref([ ...@@ -244,14 +235,19 @@ const laws = ref([
position: absolute; position: absolute;
top: 14px; top: 14px;
right: 12px; right: 12px;
width: 32px; height: 28px;
height: 32px; display: flex;
gap: 4px;
.icon {
width: 28px;
height: 28px;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
} }
}
.left { .left {
width: 1150px; width: 1150px;
.box1 { .box1 {
......
...@@ -7,7 +7,12 @@ ...@@ -7,7 +7,12 @@
<div class="title">基本信息</div> <div class="title">基本信息</div>
<div class="header-right"> <div class="header-right">
<img src="../assets/icons/header-icon.png" alt="" /> <div class="icon">
<img src="../assets/icons/header-right-icon1.png" alt="" />
</div>
<div class="icon">
<img src="../assets/icons/header-right-icon2.png" alt="" />
</div>
</div> </div>
</div> </div>
<div class="box1-main"> <div class="box1-main">
...@@ -63,15 +68,16 @@ ...@@ -63,15 +68,16 @@
<div class="header-left"></div> <div class="header-left"></div>
<div class="title">主要指令</div> <div class="title">主要指令</div>
<div class="header-right"> <div class="header-right">
<img src="../assets/icons/header-icon.png" alt="" /> <div class="icon">
<img src="../assets/icons/header-right-icon1.png" alt="" />
</div>
<div class="icon">
<img src="../assets/icons/header-right-icon2.png" alt="" />
</div>
</div> </div>
</div> </div>
<div class="box2-main"> <div class="box2-main">
<div <div class="box2-item" v-for="(item, index) in majorList" :key="index">
class="box2-item"
v-for="(item, index) in majorList"
:key="index"
>
<div class="id">{{ index + 1 }}</div> <div class="id">{{ index + 1 }}</div>
<div class="title">{{ item.title }}</div> <div class="title">{{ item.title }}</div>
<div class="open"> <div class="open">
...@@ -82,12 +88,7 @@ ...@@ -82,12 +88,7 @@
<div class="box2-footer"> <div class="box2-footer">
<div class="box2-footer-left">{{ "共计10条指令" }}</div> <div class="box2-footer-left">{{ "共计10条指令" }}</div>
<div class="box2-footer-right"> <div class="box2-footer-right">
<el-pagination <el-pagination :page-size="5" background layout="prev, pager, next" :total="10" />
:page-size="5"
background
layout="prev, pager, next"
:total="10"
/>
</div> </div>
</div> </div>
</div> </div>
...@@ -96,60 +97,65 @@ ...@@ -96,60 +97,65 @@
<div class="box3"> <div class="box3">
<div class="box-header"> <div class="box-header">
<div class="header-left"></div> <div class="header-left"></div>
<div class="title">立法背景</div> <div class="title">执行机构</div>
<div class="header-btn-box"> <div class="header-btn-box">
<div class="btn" @click="handleClickBox1Btn(1)"> <div class="btn" @click="handleClickBox1Btn(1)">
<el-button type="primary" plain v-if="box1BtnActive === 1" <el-button type="primary" plain v-if="box1BtnActive === 1">商务部</el-button>
>商务部</el-button
>
<el-button type="info" plain v-else>商务部</el-button> <el-button type="info" plain v-else>商务部</el-button>
</div> </div>
<div class="btn" @click="handleClickBox1Btn(2)"> <div class="btn" @click="handleClickBox1Btn(2)">
<el-button type="primary" plain v-if="box1BtnActive === 2" <el-button type="primary" plain v-if="box1BtnActive === 2">经济外交行动组</el-button>
>经济外交行动组</el-button
>
<el-button type="info" plain v-else>经济外交行动组</el-button> <el-button type="info" plain v-else>经济外交行动组</el-button>
</div> </div>
</div> </div>
<div class="header-right"> <div class="header-right">
<img src="../assets/icons/header-icon.png" alt="" /> <div class="icon">
<img src="../assets/icons/header-right-icon1.png" alt="" />
</div>
<div class="icon">
<img src="../assets/icons/header-right-icon2.png" alt="" />
</div>
</div> </div>
</div> </div>
<div class="box3-top"> <div class="box3-top">
<div class="box3-top-left"> <div class="box3-top-top">
<div class="left">
<img src="./assets/images/box3-img.png" alt="" /> <img src="./assets/images/box3-img.png" alt="" />
</div> </div>
<div class="box3-top-right"> <div class="right">
<div class="box3-top-right-header"> <div class="name">{{ "美国商务部" }}</div>
<div class="header-left">{{ "美国商务部" }}</div> <div class="ename">{{ "United States Department of Commerce" }}</div>
<div class="header-right">
<img src="./assets/images/open-icon.png" alt="" />
</div> </div>
<div class="more">
<div class="text">{{ "查看官网" }}</div>
<div class="icon">
<img src="./assets/images/open-icon.png" alt="" />
</div> </div>
<div class="box3-top-right-main">
<div class="main-item">
<div class="item-left">{{ "英文名:" }}</div>
<div class="item-right">
{{ "United States Department of Commerce" }}
</div> </div>
</div> </div>
<div class="box3-top-bottom">
<div class="box3-top-right-main">
<div class="main-item"> <div class="main-item">
<div class="item-icon"></div>
<div class="item-left">{{ "成立时间:" }}</div> <div class="item-left">{{ "成立时间:" }}</div>
<div class="item-right">{{ "1903年2月14日" }}</div> <div class="item-right">{{ "1903年2月14日" }}</div>
</div> </div>
<div class="main-item"> <div class="main-item">
<div class="item-icon"></div>
<div class="item-left">{{ "主要职责:" }}</div> <div class="item-left">{{ "主要职责:" }}</div>
<div class="item-right"> <div class="item-right">
{{ "国际贸易、进出口管制(R-TX-19)" }} {{ "国际贸易、进出口管制(R-TX-19)" }}
</div> </div>
</div> </div>
<div class="main-item"> <div class="main-item">
<div class="item-icon"></div>
<div class="item-left">{{ "总部地址:" }}</div> <div class="item-left">{{ "总部地址:" }}</div>
<div class="item-right"> <div class="item-right">
{{ "华盛顿宪法大道1401号胡佛大楼" }} {{ "华盛顿宪法大道1401号胡佛大楼" }}
</div> </div>
</div> </div>
<div class="main-item"> <div class="main-item">
<div class="item-icon"></div>
<div class="item-left">{{ "部长:" }}</div> <div class="item-left">{{ "部长:" }}</div>
<div class="item-right">{{ "霍华德·卢特尼克" }}</div> <div class="item-right">{{ "霍华德·卢特尼克" }}</div>
</div> </div>
...@@ -159,9 +165,9 @@ ...@@ -159,9 +165,9 @@
<div class="box3-bottom"> <div class="box3-bottom">
<div class="box3-bottom-header"> <div class="box3-bottom-header">
<div class="header-icon"> <div class="header-icon">
<img src="./assets/images/box3-bottom-header-icon.png" alt=""> <img src="./assets/images/box3-bottom-header-icon.png" alt="" />
</div> </div>
<div class="header-title">{{ '机构动态' }}</div> <div class="header-title">{{ "机构动态" }}</div>
</div> </div>
<div class="box3-bottom-main"> <div class="box3-bottom-main">
<el-timeline style="max-width: 500px"> <el-timeline style="max-width: 500px">
...@@ -178,7 +184,7 @@ ...@@ -178,7 +184,7 @@
</el-timeline> </el-timeline>
</div> </div>
<div class="box3-bottom-footer"> <div class="box3-bottom-footer">
<img src="./assets/images/more-icon.png" alt=""> <img src="./assets/images/more-icon.png" alt="" />
</div> </div>
</div> </div>
</div> </div>
...@@ -190,55 +196,48 @@ ...@@ -190,55 +196,48 @@
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
const box1BtnActive = ref(1); const box1BtnActive = ref(1);
const areaList = ref([ const areaList = ref(["人工智能", "出口管制", "半导体产业", "关税", "光伏产业"]);
"人工智能",
"出口管制",
"半导体产业",
"关税",
"光伏产业",
]);
const majorList = ref([ const majorList = ref([
{ {
title: '要求商务部在90天内建立"全栈式"美国AI出口机制。', title: '要求商务部在90天内建立"全栈式"美国AI出口机制。'
}, },
{ {
title: '要求每个纳入出口计划的提案必须涵盖完整的"全栈AI技术包"。', title: '要求每个纳入出口计划的提案必须涵盖完整的"全栈AI技术包"。'
}, },
{ {
title: title: '指示联邦机构提供贷款、担保、股权投资和技术援助支持入选的"优先AI出口包"。'
'指示联邦机构提供贷款、担保、股权投资和技术援助支持入选的"优先AI出口包"。',
}, },
{ {
title: title: "要求输出技术必须符合美国出口管制法规,并由多部门对最终用户进行合规与安全联合审查。"
"要求输出技术必须符合美国出口管制法规,并由多部门对最终用户进行合规与安全联合审查。",
}, },
{ {
title: '明确政策目标为"减少对对手国家开发的AI技术的国际依赖"。', title: '明确政策目标为"减少对对手国家开发的AI技术的国际依赖"。'
}, }
]); ]);
// 人物动态 // 人物动态
const eventList = ref([ const eventList = ref([
{ {
time: '2025-07-31', time: "2025-07-31",
content: '美商务部发布指南,警告全球企业使用华为昇腾芯片可能违反美国出口管制。意在限制中国AI产业发展,阻碍其获得先进算力。' content:
"美商务部发布指南,警告全球企业使用华为昇腾芯片可能违反美国出口管制。意在限制中国AI产业发展,阻碍其获得先进算力。"
}, },
{ {
time: '2025-07-25', time: "2025-07-25",
content: '美商务部持续对多种中国产品发起“双反”(反倾销、反补贴)调查并作出裁决,涉及产品从工业原料到日常用品,且裁定的税率普遍较高。' content:
"美商务部持续对多种中国产品发起“双反”(反倾销、反补贴)调查并作出裁决,涉及产品从工业原料到日常用品,且裁定的税率普遍较高。"
}, },
{ {
time: '2025-07-21', time: "2025-07-21",
content: '美商务部进一步收紧对华先进半导体出口管制,将更多中国实体列入“实体清单”。限制14纳米及以下先进芯片、DRAM等对华出口' content:
"美商务部进一步收紧对华先进半导体出口管制,将更多中国实体列入“实体清单”。限制14纳米及以下先进芯片、DRAM等对华出口"
}, },
{ {
time: '2025-07-12', time: "2025-07-12",
content: '美商务部发起第三次反倾销和反补贴日落复审调查。' content: "美商务部发起第三次反倾销和反补贴日落复审调查。"
} }
]); ]);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -262,14 +261,14 @@ const eventList = ref([ ...@@ -262,14 +261,14 @@ const eventList = ref([
line-height: 16px; line-height: 16px;
color: rgba(10, 87, 166, 1); color: rgba(10, 87, 166, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 16px; font-size: 20px;
font-weight: 600; font-weight: 700;
line-height: 16px; line-height: 16px;
} }
.header-btn-box { .header-btn-box {
position: absolute; position: absolute;
top: 14px; top: 14px;
right: 52px; right: 84px;
display: flex; display: flex;
.btn { .btn {
margin-left: 8px; margin-left: 8px;
...@@ -279,14 +278,19 @@ const eventList = ref([ ...@@ -279,14 +278,19 @@ const eventList = ref([
position: absolute; position: absolute;
top: 14px; top: 14px;
right: 12px; right: 12px;
width: 32px; height: 28px;
height: 32px; display: flex;
gap: 4px;
.icon {
width: 28px;
height: 28px;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
} }
}
.left { .left {
width: 1150px; width: 1150px;
.box1 { .box1 {
...@@ -328,12 +332,11 @@ const eventList = ref([ ...@@ -328,12 +332,11 @@ const eventList = ref([
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
// line-height: 20px;
box-sizing: border-box; box-sizing: border-box;
border: 1px solid rgba(186, 224, 255, 1); border: 1px solid rgba(186, 224, 255, 1);
border-radius: 4px; border-radius: 4px;
background: rgba(230, 244, 255, 1); background: rgba(230, 244, 255, 1);
padding: 1px 8px; padding: 0px 8px;
margin-right: 8px; margin-right: 8px;
} }
} }
...@@ -381,6 +384,10 @@ const eventList = ref([ ...@@ -381,6 +384,10 @@ const eventList = ref([
width: 1000px; width: 1000px;
line-height: 48px; line-height: 48px;
margin-left: 13px; margin-left: 13px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
} }
.open { .open {
width: 16px; width: 16px;
...@@ -418,27 +425,55 @@ const eventList = ref([ ...@@ -418,27 +425,55 @@ const eventList = ref([
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2); box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
.box3-top { .box3-top {
display: flex;
margin-top: 10px; margin-top: 10px;
height: 261px; height: 261px;
border-bottom: 1px solid rgba(234, 236, 238, 1); border-bottom: 1px solid rgba(234, 236, 238, 1);
.box3-top-left { .box3-top-top {
width: 120px; width: 473px;
height: 120px; height: 88px;
margin-left: 27px; box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px;
background: rgba(247, 248, 249, 1);
display: flex;
align-items: center;
margin: 0 auto;
position: relative;
.more {
position: absolute;
right: 17px;
top: 17px;
display: flex;
gap: 3px;
.text {
height: 16px;
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 16px;
}
.icon {
width: 16px;
height: 16px;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
.box3-top-right { }
margin-left: 30px; .left {
.box3-top-right-header { width: 64px;
display: flex; height: 64px;
height: 26px; margin-left: 17px;
.header-left { img {
width: 325px; width: 100%;
height: 100%;
}
}
.right {
margin-left: 22px;
.name {
height: 26px; height: 26px;
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
...@@ -446,18 +481,19 @@ const eventList = ref([ ...@@ -446,18 +481,19 @@ const eventList = ref([
font-weight: 700; font-weight: 700;
line-height: 26px; line-height: 26px;
} }
.header-right { .ename {
margin-left: 9px; margin-top: 6px;
margin-top: 5px; height: 24px;
width: 16px; color: rgba(95, 101, 108, 1);
height: 16px; font-family: Microsoft YaHei;
cursor: pointer; font-size: 16px;
img{ font-weight: 400;
width: 100%; line-height: 24px;
height: 100%;
} }
} }
} }
.box3-top-bottom {
margin-left: 50px;
.box3-top-right-main { .box3-top-right-main {
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
...@@ -468,11 +504,21 @@ const eventList = ref([ ...@@ -468,11 +504,21 @@ const eventList = ref([
.main-item { .main-item {
display: flex; display: flex;
margin-top: 12px; margin-top: 12px;
.item-left{ height: 26px;
line-height: 26px;
.item-icon {
width: 4px;
height: 4px;
border-radius: 2px;
background: #3b414b;
margin-top: 11px;
margin-right: 19px;
}
.item-left {
height: 24px; height: 24px;
width: 80px; width: 80px;
} }
.item-right{ .item-right {
width: 291px; width: 291px;
} }
} }
...@@ -483,17 +529,17 @@ const eventList = ref([ ...@@ -483,17 +529,17 @@ const eventList = ref([
.box3-bottom-header { .box3-bottom-header {
height: 59px; height: 59px;
display: flex; display: flex;
.header-icon{ .header-icon {
margin-left: 22px; margin-left: 22px;
margin-top: 27px; margin-top: 27px;
width: 16px; width: 16px;
height: 16px; height: 16px;
img{ img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
.header-title{ .header-title {
margin-left: 12px; margin-left: 12px;
margin-top: 23px; margin-top: 23px;
height: 24px; height: 24px;
...@@ -504,15 +550,15 @@ const eventList = ref([ ...@@ -504,15 +550,15 @@ const eventList = ref([
line-height: 24px; line-height: 24px;
} }
} }
.box3-bottom-main{ .box3-bottom-main {
height: 410px; height: 410px;
} }
.box3-bottom-footer{ .box3-bottom-footer {
width: 108px; width: 108px;
height: 32px; height: 32px;
margin: 5px auto; margin: 5px auto;
cursor: pointer; cursor: pointer;
img{ img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
......
<template> <template>
<<<<<<< HEAD
<div class="home-wrapper"> <div class="home-wrapper">
<div class="home-main"> <div class="home-main">
<div class="home-main-header"> <div class="home-main-header">
...@@ -225,7 +224,7 @@ ...@@ -225,7 +224,7 @@
</div> </div>
<div class="header-title">{{ "涉及领域" }}</div> <div class="header-title">{{ "涉及领域" }}</div>
<div class="box4-header-right"> <div class="box4-header-right">
<el-select v-model="curAreaYear" placeholder="选择发布时间" style="width: 120px"> <el-select v-model="curAreaYear" placeholder="选择发布时间" style="width: 100px">
<el-option <el-option
v-for="item in areaYearList" v-for="item in areaYearList"
:key="item.value" :key="item.value"
...@@ -239,265 +238,6 @@ ...@@ -239,265 +238,6 @@
</div> </div>
</div> </div>
</div> </div>
=======
<div class="home-wrapper">
<div class="home-main">
<div class="home-main-header">
<div class="home-main-header-top">
<span>国家科技安全 </span>> <span>中美博弈概览 </span>>
<span>市场准入限制</span>
</div>
<div class="home-main-header-center">
<el-input
v-model="input"
style="width: 838px; height: 100%"
placeholder="搜索市场准入限制调查"
/>
<div class="search">
<div class="search-icon">
<img src="./assets/images/search-icon.png" alt="" />
</div>
<div class="search-text">搜索</div>
</div>
</div>
<div class="home-main-header-footer">
<div class="home-main-header-footer-item">
<div class="item-top">142</div>
<div class="item-footer">总调查案件数</div>
</div>
<div class="home-main-header-footer-item">
<div class="item-top">28</div>
<div class="item-footer">调查中案件数</div>
</div>
<div class="home-main-header-footer-item">
<div class="item-top">326</div>
<div class="item-footer">涉及中企</div>
</div>
<div class="home-main-header-footer-item">
<div class="item-top">38%</div>
<div class="item-footer">胜诉/和解率</div>
</div>
<div class="home-main-header-footer-item">
<div class="item-top">285</div>
<div class="item-footer">分析报告</div>
</div>
</div>
</div>
<div class="home-main-center">
<div class="center-top">
<div class="box1">
<div class="box1-left">
<img src="./assets/images/box1-left.png" alt="" />
</div>
<div class="box1-right">
<img src="./assets/images/box1-right.png" alt="" />
</div>
<div class="box1-header">
<div class="box1-header-left">
<div class="icon">
<img src="./assets/images/box1-header-icon.png" alt="" />
</div>
<div class="title">{{ "调查进展" }}</div>
</div>
<div class="box1-header-right" @click="handleClickToDetail()">
{{ "查看详情 >" }}
</div>
</div>
<div class="box1-main">
<div class="box1-main-header">
<div class="header-left">
{{
"美国ITC发布对外国制造的半导体器件及其下游产品和组件的337部分终裁"
}}
</div>
<div class="header-right">
<div class="tag1">{{ "337" }}</div>
<div class="tag2">{{ "半导体" }}</div>
</div>
</div>
<div class="info-box">
<div class="info-header">
<div class="icon"></div>
<div class="time">{{ "2025-08-15" }}</div>
<div class="title">{{ "部分终裁" }}</div>
</div>
<div class="info-content">
{{
"对本案行政法官于2025年7月31日作出的初裁(No.36)不予复审,即基于申请方撤回,终止本案对美国注册专利号9,093,473第4项申诉的调查。"
}}
</div>
</div>
<div class="list-box">
<div class="list-item">
<div class="icon"></div>
<div class="list-left">{{ "调查案号:" }}</div>
<div class="list-right">{{ "337-TA-1443" }}</div>
</div>
<div class="list-item">
<div class="icon"></div>
<div class="list-left">{{ "涉及产品:" }}</div>
<div class="list-right">
{{
"对美出口、在美进口及销售的特定外国制造的半导体器件及其下游产品和组件(Certain Foreign-Fabricated ..."
}}
</div>
</div>
<div class="list-item">
<div class="icon"></div>
<div class="list-left">{{ "原告:" }}</div>
<div class="list-right">
{{
"爱尔兰Longitude Licensing Ltd.、爱尔兰Marlin Semiconductor Limited"
}}
</div>
</div>
<div class="list-item">
<div class="icon"></div>
<div class="list-left">{{ "被告:" }}</div>
<div class="list-right">
{{
"中国台湾地区Taiwan Semiconductor Manufacturing Company Limited of Taiwan、美国Apple Inc. of ...."
}}
</div>
</div>
<div class="list-item">
<div class="icon"></div>
<div class="list-left">{{ "涉案专利" }}</div>
<div class="list-right">
{{ "美国注册专利号7745847、9093473、9147747、9184292" }}
</div>
</div>
</div>
</div>
</div>
<div class="box2">
<div class="box2-header">
<div class="icon">
<img src="./assets/images/box2-header-icon.png" alt="" />
</div>
<div class="title">
<div class="text">{{ "风险信号" }}</div>
<div class="num">{{ warningList.length }}</div>
</div>
<div class="more">{{ "更多 >" }}</div>
</div>
<div class="box2-main">
<div
class="box2-main-item"
v-for="(item, index) in warningList"
:key="index"
>
<div
class="item-left"
:class="{
itemLeftStatus1: item.status === '一般风险',
itemLeftStatus2: item.status === '重大风险',
}"
>
{{ item.status }}
</div>
<div class="item-right">
<div class="text">
{{ item.title }}
</div>
<div class="time">{{ item.time }}</div>
</div>
</div>
</div>
<div class="box2-footer">
<div class="icon">
<img src="./assets/images/box2-footer-icon.png" alt="" />
</div>
<div class="text">{{ "风险处理" }}</div>
</div>
</div>
</div>
<div class="center-center">
<div class="center-center-box1">
<div class="header">
<div class="header-left">{{ "301调查" }}</div>
<div class="header-right">{{ "52项" }}</div>
</div>
<div class="content-box">
<div class="item">{{ "可能措施: 加征关税、限制进口" }}</div>
<div class="item">
{{ '依据《1974年贸易法》第301条针对"不合理或不公正贸易做法"' }}
</div>
</div>
</div>
<div class="center-center-box2">
<div class="header">
<div class="header-left">{{ "232调查" }}</div>
<div class="header-right">{{ "3项" }}</div>
</div>
<div class="content-box">
<div class="item">{{ "可能措施: 加征关税、限制进口" }}</div>
<div class="item">
{{
"依据《1962年贸易扩展法》第232条评估进口产品对国家安全影响"
}}
</div>
</div>
</div>
<div class="center-center-box3">
<div class="header">
<div class="header-left">{{ "337调查" }}</div>
<div class="header-right">{{ "87项" }}</div>
</div>
<div class="content-box">
<div class="item">{{ "可能措施: 排除令、禁止令" }}</div>
<div class="item">
{{ "依据《1930年关税法》第337条针对知识产权侵权行为" }}
</div>
</div>
</div>
</div>
<div class="center-footer">
<div class="box3">
<div class="box3-header">
<div class="box3-header-left">
<div class="box3-header-icon">
<img src="./assets/images/box3-header-icon.png" alt="" />
</div>
<div class="box3-header-title">{{ "调查数量" }}</div>
</div>
<div class="box3-header-right">
<div class="right-box rightBoxActive">
{{ "按年度" }}
</div>
<div class="right-box">
{{ "按月度" }}
</div>
</div>
</div>
<div class="box3-main" id="chart1"></div>
</div>
<div class="box4">
<div class="box4-header">
<div class="header-icon">
<img src="./assets/images/box4-header-icon.png" alt="" />
</div>
<div class="header-title">{{ "涉及领域" }}</div>
<div class="box4-header-right">
<el-select
v-model="curAreaYear"
placeholder="选择发布时间"
style="width: 100px"
>
<el-option
v-for="item in areaYearList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
<div class="box4-main" id="chart2"></div>
</div>
</div>
</div>
>>>>>>> 472380f98908a1b616c78da3af0082bf120e3559
<div class="home-main-footer"> <div class="home-main-footer">
<div class="home-main-footer-header"> <div class="home-main-footer-header">
...@@ -938,10 +678,6 @@ onMounted(async () => { ...@@ -938,10 +678,6 @@ onMounted(async () => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
// position: sticky;
// left: 0;
// top: 0;
// z-index: 9999;
.home-main-header-top { .home-main-header-top {
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
...@@ -959,7 +695,7 @@ onMounted(async () => { ...@@ -959,7 +695,7 @@ onMounted(async () => {
padding-left: 160px; padding-left: 160px;
} }
.home-main-header-center { .home-main-header-center {
margin-top: 13px; margin-top: 48px;
width: 960px; width: 960px;
height: 48px; height: 48px;
border-radius: 4px; border-radius: 4px;
...@@ -971,14 +707,15 @@ onMounted(async () => { ...@@ -971,14 +707,15 @@ onMounted(async () => {
.search { .search {
position: absolute; position: absolute;
right: 1px; right: 1px;
top: 1px; top: 2px;
width: 120px; width: 120px;
height: 42px; height: 44px;
border-radius: 4px; border-radius: 10px;
background: rgba(22, 119, 255, 1); background: var(--color-main-active);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
cursor: pointer;
.search-icon { .search-icon {
width: 18px; width: 18px;
height: 18px; height: 18px;
...@@ -1030,7 +767,6 @@ onMounted(async () => { ...@@ -1030,7 +767,6 @@ onMounted(async () => {
} }
} }
<<<<<<< HEAD
.home-main-center { .home-main-center {
margin-top: 34px; margin-top: 34px;
.center-top { .center-top {
...@@ -1564,962 +1300,6 @@ onMounted(async () => { ...@@ -1564,962 +1300,6 @@ onMounted(async () => {
} }
} }
} }
.center-footer {
margin-top: 21px;
height: 450px;
display: flex;
justify-content: center;
.box3 {
width: 1064px;
height: 450px;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: rgba(255, 255, 255, 1);
.box3-header {
height: 53px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
margin: 0 auto;
display: flex;
justify-content: space-between;
padding: 0 20px;
.box3-header-left {
display: flex;
.box3-header-icon {
margin-top: 15px;
width: 13px;
height: 13px;
img {
width: 100%;
height: 100%;
}
}
.box3-header-title {
margin-top: 16px;
margin-left: 22px;
height: 22px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 22px;
}
}
.box3-header-right {
display: flex;
justify-content: flex-end;
width: 178px;
height: 22px;
margin-top: 11px;
.right-box {
height: 28px;
padding: 0 8px;
text-align: center;
line-height: 28px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
margin-left: 8px;
cursor: pointer;
}
.rightBoxActive {
color: rgba(10, 87, 166, 1);
border: 1px solid rgba(10, 87, 166, 1);
border-radius: 4px;
background: rgba(246, 250, 255, 1);
}
}
}
.box3-main {
height: 397px;
}
}
.box4 {
margin-left: 20px;
width: 521px;
height: 450px;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: rgba(255, 255, 255, 1);
.box4-header {
width: 452px;
margin: 0 auto;
height: 53px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
display: flex;
position: relative;
.header-icon {
margin-top: 18px;
width: 18px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
.header-title {
margin-top: 16px;
margin-left: 26px;
height: 22px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 22px;
}
.box4-header-right {
position: absolute;
right: 0;
top: 10px;
}
}
.box4-main {
width: 452px;
height: 360px;
margin: 8px auto;
}
}
}
}
.home-main-footer {
// width: 100%;
height: 1059px;
background: rgba(248, 249, 250, 1);
.home-main-footer-header {
width: 1600px;
height: 42px;
margin: 36px auto;
// background: orange;
display: flex;
justify-content: space-between;
.btn-box {
width: 1000px;
display: flex;
.btn {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 42px;
padding: 0 24px;
border-radius: 21px;
background: rgba(20, 89, 187, 0);
margin-right: 20px;
cursor: pointer;
&:hover {
background: rgba(20, 89, 187, 0.1);
}
}
.btnActive {
padding: 0 24px;
border-radius: 21px;
background: rgba(20, 89, 187, 1);
color: #fff;
&:hover {
color: #fff;
background: rgba(20, 89, 187, 1);
}
}
}
.select-box {
height: 42px;
box-sizing: border-box;
padding: 5px 0;
}
}
.home-main-footer-main {
width: 1600px;
margin-bottom: 20px;
height: 985px;
// box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
// background: rgba(255, 255, 255, 1);
margin: 0 auto;
box-sizing: border-box;
// padding: 20px;
display: flex;
.left {
width: 300px;
height: 560px;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
.left-box1 {
margin-top: 17px;
height: 260px;
.left-box1-header {
display: flex;
.icon {
width: 8px;
height: 16px;
margin-top: 4px;
border-radius: 2px 2px 0 0;
background: rgba(10, 87, 166, 1);
}
.title {
height: 2px;
margin-left: 17px;
color: rgba(10, 87, 166, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
}
.left-box1-main {
margin-top: 10px;
.time-label {
height: 35px;
margin-left: 25px;
}
}
}
.left-box2 {
margin-top: 17px;
height: 260px;
.left-box2-header {
display: flex;
.icon {
width: 8px;
height: 16px;
margin-top: 4px;
border-radius: 2px 2px 0 0;
background: rgba(10, 87, 166, 1);
}
.title {
height: 2px;
margin-left: 17px;
color: rgba(10, 87, 166, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
}
.left-box2-main {
margin-top: 10px;
.area-label {
height: 35px;
margin-left: 25px;
}
}
}
}
.right {
margin-left: 16px;
width: 1284px;
height: 899px;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
.right-header {
height: 54px;
background: rgba(59, 65, 75, 1);
display: flex;
.header-item1 {
width: 500px;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 54px;
padding-left: 80px;
box-sizing: border-box;
}
.header-item2 {
width: 196px;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 54px;
padding-left: 20px;
box-sizing: border-box;
}
.header-item3 {
width: 196px;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 54px;
padding-left: 20px;
box-sizing: border-box;
}
.header-item4 {
width: 196px;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 54px;
padding-left: 20px;
box-sizing: border-box;
}
.header-item5 {
width: 196px;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 54px;
padding-left: 20px;
box-sizing: border-box;
}
}
.right-main {
height: 780px;
// background: orange;
.item {
display: flex;
padding: 16px 0;
// height: 56px;
&:nth-child(2n) {
background: rgba(247, 248, 249, 1);
}
.item-box1 {
width: 500px;
display: flex;
.name {
height: 22px;
padding: 0 8px;
box-sizing: border-box;
border-radius: 4px;
margin-left: 32px;
margin-top: 10px;
// display: flex;
// align-items: center;
}
.name1 {
color: rgba(250, 140, 22, 1);
border: 1px solid rgba(255, 213, 145, 1);
background: rgba(255, 247, 230, 1);
}
.name2 {
color: rgba(10, 87, 166, 1);
border: 1px solid rgba(145, 202, 255, 1);
background: rgba(230, 244, 255, 1);
}
.name3 {
color: rgba(114, 46, 209, 1);
border: 1px solid rgba(211, 173, 247, 1);
background: rgba(249, 240, 255, 1);
}
.title {
margin-left: 12px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
display: flex;
align-items: center;
}
}
.item-box2 {
width: 196px;
padding-left: 20px;
box-sizing: border-box;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
display: flex;
align-items: center;
}
.item-box3 {
width: 196px;
padding-left: 20px;
box-sizing: border-box;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
display: flex;
align-items: center;
}
.item-box4 {
width: 196px;
padding-left: 20px;
box-sizing: border-box;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
display: flex;
align-items: center;
}
.item-box5 {
width: 196px;
padding-left: 20px;
box-sizing: border-box;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
display: flex;
align-items: center;
}
}
}
.right-footer {
display: flex;
// height: 60px;
// background: orange;
justify-content: space-between;
.footer-left {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
margin-left: 24px;
margin-top: 6px;
}
.footer-right {
margin-right: 24px;
}
}
}
}
}
}
=======
.home-main-center {
margin-top: 34px;
.center-top {
height: 450px;
display: flex;
justify-content: center;
gap: 20px;
.box1 {
width: 1064px;
height: 450px;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: #fff;
box-sizing: border-box;
padding-left: 31px;
padding-right: 41px;
position: relative;
.box1-left {
position: absolute;
left: 0;
top: 220px;
width: 24px;
height: 48px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.box1-right {
position: absolute;
right: 0;
top: 220px;
width: 24px;
height: 48px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.box1-header {
height: 53px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
display: flex;
justify-content: space-between;
.box1-header-left {
display: flex;
.icon {
width: 18px;
height: 18px;
margin-top: 19px;
img {
width: 100%;
height: 100%;
}
}
.title {
width: 152px;
height: 53px;
margin-left: 18px;
color: #fff;
background: rgba(10, 87, 166, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 53px;
text-align: center;
}
}
.box1-header-right {
margin-top: 19px;
height: 16px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 16px;
cursor: pointer;
}
}
.box1-main {
width: 1064px;
height: 354px;
margin-top: 22px;
.box1-main-header {
width: 990px;
height: 54px;
display: flex;
justify-content: space-between;
.header-left {
padding-left: 22px;
color: rgba(10, 87, 166, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
}
.header-right {
display: flex;
width: 200px;
justify-content: flex-end;
.tag1 {
height: 24px;
line-height: 24px;
padding: 0 8px;
box-sizing: border-box;
color: rgba(10, 87, 166, 1);
border: 1px solid rgba(145, 202, 255, 1);
border-radius: 4px;
background: rgba(230, 244, 255, 1);
}
.tag2 {
margin-left: 8px;
height: 24px;
line-height: 24px;
padding: 0 8px;
box-sizing: border-box;
color: rgba(19, 168, 168, 1);
border: 1px solid rgba(135, 232, 222, 1);
border-radius: 4px;
background: rgba(230, 255, 251, 1);
}
}
}
.info-box {
margin-left: 6px;
width: 989px;
height: 108px;
box-sizing: border-box;
border: 1px solid rgba(231, 243, 255, 1);
border-radius: 4px;
background: rgba(246, 250, 255, 1);
.info-header {
height: 38px;
display: flex;
.icon {
width: 4px;
height: 4px;
border-radius: 2px;
background: rgba(59, 65, 75, 1);
margin-left: 24px;
margin-top: 20px;
}
.time {
width: 98px;
height: 24px;
margin-top: 10px;
margin-left: 12px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
.title {
margin-left: 11px;
margin-top: 10px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
}
.info-content {
width: 909px;
height: 60px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
margin-left: 41px;
margin-top: 4px;
}
}
.list-box {
margin-top: 18px;
margin-left: 28px;
width: 940px;
height: 185px;
.list-item {
height: 37px;
display: flex;
.icon {
width: 4px;
height: 4px;
border-radius: 2px;
background: rgba(59, 65, 75, 1);
margin-top: 16px;
}
.list-left {
margin-left: 18px;
line-height: 37px;
width: 100px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
}
.list-right {
line-height: 37px;
margin-left: 17px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
}
}
}
}
}
.box2 {
width: 521px;
padding-right: 20px;
height: 450px;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: rgba(255, 255, 255, 1);
position: relative;
.box2-header {
height: 54px;
display: flex;
.icon {
width: 24px;
height: 22px;
margin-left: 33px;
margin-top: 18px;
img {
width: 100%;
height: 100%;
}
}
.title {
display: flex;
width: 148px;
background: rgba(206, 79, 81, 1);
margin-left: 25px;
.text {
margin-left: 15px;
margin-top: 16px;
height: 22px;
color: #fff;
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 22px;
}
.num {
width: 24px;
height: 20px;
line-height: 20px;
text-align: center;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 12px;
margin-left: 15px;
margin-top: 18px;
border-radius: 100px;
background: rgba(255, 255, 255, 0.3);
}
}
.more {
margin-top: 19px;
margin-left: 200px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 16px;
cursor: pointer;
}
}
.box2-main {
height: 282px;
overflow-y: auto;
.box2-main-item {
margin-left: 23px;
height: 47px;
width: 464px;
display: flex;
.itemLeftStatus1 {
color: rgba(82, 196, 26, 1) !important;
background: rgba(246, 255, 237, 1) !important;
}
.itemLeftStatus2 {
color: rgba(250, 140, 22, 1) !important;
background: rgba(255, 247, 230, 1) !important;
}
.item-left {
margin-top: 4px;
margin-left: 2px;
width: 40px;
height: 40px;
border-radius: 20px;
background: rgba(255, 241, 240);
color: rgba(245, 34, 45, 1);
font-family: Microsoft YaHei;
font-size: 12px;
font-weight: 400;
line-height: 14px;
box-sizing: border-box;
padding: 6px 4px;
text-align: center;
}
.item-right {
margin-left: 13px;
width: 408px;
height: 47px;
border-top: 1px solid rgba(240, 242, 244, 1);
border-bottom: 1px solid rgba(240, 242, 244, 1);
display: flex;
.text {
width: 348px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 47px;
}
.time {
margin-left: 10px;
line-height: 47px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
}
}
}
}
.box2-footer {
position: absolute;
left: 40px;
bottom: 20px;
width: 430px;
height: 42px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
border-radius: 6px;
background: rgba(22, 119, 255, 1);
cursor: pointer;
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
margin-left: 8px;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
}
}
}
.center-center {
width: 1600px;
margin: 24px auto;
height: 142px;
margin-top: 24px;
display: flex;
justify-content: space-between;
.center-center-box1 {
width: 520px;
height: 142px;
background: #fff;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
position: relative;
&::before {
content: "";
position: absolute;
z-index: 99;
left: 0;
top: 15px;
width: 4px;
height: 111px;
background: rgba(250, 140, 22, 1);
}
.header {
height: 56px;
display: flex;
justify-content: space-between;
.header-left {
margin-left: 30px;
margin-top: 26px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
}
.header-right {
margin-top: 28px;
margin-right: 35px;
height: 24px;
color: rgba(250, 140, 22, 1);
font-family: Microsoft YaHei;
font-size: 30px;
font-weight: 700;
line-height: 24px;
}
}
.content-box {
margin-left: 30px;
.item {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
margin-top: 8px;
}
}
}
.center-center-box2 {
width: 520px;
height: 142px;
background: #fff;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
position: relative;
&::before {
content: "";
position: absolute;
z-index: 99;
left: 0;
top: 15px;
width: 4px;
height: 111px;
background: rgba(114, 46, 209, 1);
}
.header {
height: 56px;
display: flex;
justify-content: space-between;
.header-left {
margin-left: 30px;
margin-top: 26px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
}
.header-right {
margin-top: 28px;
margin-right: 35px;
height: 24px;
color: rgba(114, 46, 209, 1);
font-family: Microsoft YaHei;
font-size: 30px;
font-weight: 700;
line-height: 24px;
}
}
.content-box {
margin-left: 30px;
.item {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
margin-top: 8px;
}
}
}
.center-center-box3 {
width: 520px;
height: 142px;
background: #fff;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
position: relative;
&::before {
content: "";
position: absolute;
z-index: 99;
left: 0;
top: 15px;
width: 4px;
height: 111px;
background: rgba(10, 87, 166, 1);
}
.header {
height: 56px;
display: flex;
justify-content: space-between;
.header-left {
margin-left: 30px;
margin-top: 26px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
}
.header-right {
margin-top: 28px;
margin-right: 35px;
height: 24px;
color: rgba(10, 87, 166, 1);
font-family: Microsoft YaHei;
font-size: 30px;
font-weight: 700;
line-height: 24px;
}
}
.content-box {
margin-left: 30px;
.item {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
margin-top: 8px;
}
}
}
}
.center-footer { .center-footer {
margin-top: 21px; margin-top: 21px;
height: 450px; height: 450px;
...@@ -2942,6 +1722,5 @@ onMounted(async () => { ...@@ -2942,6 +1722,5 @@ onMounted(async () => {
} }
} }
} }
>>>>>>> 472380f98908a1b616c78da3af0082bf120e3559
} }
</style> </style>
<!-- 中M博弈概览页 -->
<template>
<div class="resource-box">
<img class="title-img" src="@/assets/images/bg/概览页模块标题2.png"></img>
<div style="margin-top: 20px;height: 450px;display: flex;">
<div class="resource-content" style="width: 45%; display: block;">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">中美博弈资源新闻动态</div>
<div class="item-header-right"> 更多 +</div>
</div>
<div class="item-header-divider"></div>
</div>
<div class="resource-content" style="width: 45%;margin-left: 5%;">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">创新主体排名</div>
</div>
<div class="item-header-divider"></div>
</div>
</div>
<div style="margin-top: 20px;height: 450px;display: flex;">
<div class="resource-content" style="width: 45%; display: block;">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">研发投入情况</div>
</div>
<div class="item-header-divider"></div>
<div style="display: flex;height: calc(100% - 60px);" id="char3">
</div>
</div>
<div class="resource-content" style="width: 45%;margin-left: 5%;">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">研发投入领域</div>
<div class="item-header-right"> 查看数据源> </div>
</div>
<div class="item-header-divider"></div>
<div style="display: flex;height: calc(100% - 60px);" id="char4">
</div>
</div>
</div>
<div style="margin-top: 20px;height: 450px;display: flex;">
<div class="resource-content" style="width: 45%; display: block;">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">专利申请情况</div>
</div>
<div class="item-header-divider"></div>
<div style="display: flex;height: calc(100% - 60px);" id="char5">
</div>
</div>
<div class="resource-content" style="width: 45%;margin-left: 5%;">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">论文发表情况</div>
<div class="item-header-right"> 查看数据源> </div>
</div>
<div class="item-header-divider"></div>
<div style="display: flex;height: calc(100% - 60px);" id="char6">
</div>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref, computed } from "vue";
import * as echarts from "echarts";
import getBarChart2 from '../js/barChart2.js'
import radarChart2 from '../js/radarChart2.js'
import getMultiLineChart1 from "../js/multiLineChart1.js";
const names = ['Jan', 'Feb', 'Mar', 'Apr', 'May']
const data1 = [120, 200, 150, 80, 70]
const data2 = [90, 230, 180, 110, 100]
//专利申请情况
const chart5Data = ref({
title: [
"2024-09",
"2024-10",
"2024-11",
"2024-12",
"2025-01",
"2025-02",
"2025-03",
"2025-04",
"2025-05",
"2025-06",
"2025-07",
"2025-08"
],
data: [
{
name: "提出法案",
value: [145, 52, 84, 99, 71, 96, 128, 144, 140, 168, 188, 172]
},
{
name: "通过法案",
value: [6, 3, 4, 6, 11, 5, 2, 14, 16, 27, 28, 44]
}
]
});
// 绘制echarts图表
const setChart = (option, chartId) => {
let chartDom = document.getElementById(chartId);
chartDom.removeAttribute("_echarts_instance_");
let chart = echarts.init(chartDom);
chart.setOption(option);
return chart;
};
onMounted(() => {
let char3 = getBarChart2(names, data1, data2, false);
setChart(char3, "char3");
let char4 = radarChart2()
setChart(char4, "char4");
let chart5 = getMultiLineChart1(chart5Data.value.title, chart5Data.value.data[0].value, chart5Data.value.data[1].value);
setChart(chart5, "char5");
let chart6 = getMultiLineChart1(chart5Data.value.title, chart5Data.value.data[0].value, chart5Data.value.data[1].value);
setChart(chart6, "char6");
});
</script>
<style lang="scss" scoped>
.resource-box {
height: 1550px;
}
.title-text {
font-size: 32px;
font-weight: 700;
line-height: 42px;
margin: 40px;
text-align: center;
}
.title-img {
width: 100%;
height: 42px;
}
.resource-content {
/* 容器 480 */
width: 100%;
height: 450px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: var(---, 10px);
/* 业务系统/模块阴影 */
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.item-header {
height: 48px;
width: 100%;
display: flex;
.item-header-icon {
width: 20px;
height: 20px;
margin: 15px;
}
.item-header-text {
width: 250px;
font-size: 20px;
font-weight: 700;
line-height: 26px;
background: rgba(255, 255, 255, 0.65);
color: #055FC2;
font-family: Microsoft YaHei;
font-size: 20px;
line-height: 48px;
text-align: left;
}
.item-header-right {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
line-height: 48px;
text-align: right;
width: calc(100% - 350px);
.item-header-right-icon {
/* 容器 704 */
width: 14px;
height: 16px;
}
}
}
.timeLine-box {
height: 100%;
width: calc(100% - 50px);
.time-item-box {
width: 30%;
height: 165px;
}
}
.item-header-divider {
/* 矩形 249 */
width: 100%;
height: 1px;
background: #eaecee;
}
.resource-btn-left {
height: 100%;
width: 24px;
}
.resource-btn-right {
height: 100%;
width: 24px;
}
.resource-btn-icon {
height: 48px;
width: 100%;
margin-top: calc(50% - 24px);
}
}
</style>
<!-- 中M博弈概览页 -->
<template>
<div class="thematic-box">
<div class="title-text">中美博弈专题分析</div>
<img class="title-img" src="@/assets/images/bg/概览页模块标题.png"></img>
<div class="thematic-content">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">对华打压历程</div>
<div class="item-header-right"> <img class="item-header-right-icon" src="@/assets/images/icon/tips.png"></img>
数据来源:美国某某局</div>
</div>
<div class="item-header-divider"></div>
<div style="display: flex;height: calc(100% - 60px);">
<div class="thematic-btn-left" @click="changeBtn('timwLine', 'left')">
<img class="thematic-btn-icon" src="@/assets/images/icon/card-btn-left.png"></img>
</div>
<div class="timeLine-box">
<div style="height: calc(50% - 8px);display: flex">
<div v-for="(item, index) in timeLineOddIndexItems" class="time-item-box">
{{ item.titlle }}
</div>
</div>
<img style=" width: 100%; height: 10px;" src="@/assets/images/bg/time-line.png"></img>
<div style="height: calc(50% - 8px);display: flex;">
<div v-for="(item, index) in timeLineIndexItems" class="time-item-box">
{{ item.titlle }}
</div>
</div>
</div>
<div class="thematic-btn-right" @click="changeBtn('right')">
<img class="thematic-btn-icon" src="@/assets/images/icon/card-btn-right.png"></img>
</div>
</div>
</div>
<div class="thematic-content" style="margin-top: 20px;height: 350px;">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">打压遏制手段分布</div>
</div>
<div class="item-header-divider"></div>
<div style="display: flex;height: calc(100% - 60px);">
<div class="thematic-btn-left" @click="changeBtn('timwLine', 'left')">
<img class="thematic-btn-icon" src="@/assets/images/icon/card-btn-left.png"></img>
</div>
<div class="cup-box" style="display: flex;">
<div v-for="item in distribution" class="cup-item-box" :style="{
color: item.borderColor
}">
<div class="cup-title">
{{ item.titlle }}
</div>
<div class="cup" :style="{
borderColor: item.bgColor1,
outlineColor: item.bgColor1,
}">
<!-- 水位 -->
<div class="water" :style="{
'--percent': item.value,
'--c1': item.bgColor1,
'--c2': item.bgColor2,
}"></div>
<!-- 文字 -->
<span class="txt" :style="{ color: item.borderColor, }">{{ item.text }}</span>
</div>
<div style="margin-top: 20px;">
{{ item.change }}
</div>
</div>
</div>
<div class="thematic-btn-right" @click="changeBtn('right')">
<img class="thematic-btn-icon" src="@/assets/images/icon/card-btn-right.png"></img>
</div>
</div>
</div>
<div style="margin-top: 20px;height: 450px;display: flex;">
<div class="thematic-content" style="width: 45%; display: block;">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">打压遏制强度变化</div>
<div class="item-header-right"> <img class="item-header-right-icon" src="@/assets/images/icon/tips.png"></img>
数据来源:美国某某局</div>
</div>
<div class="item-header-divider"></div>
<div style="display: flex;height: calc(100% - 60px);" id="chart1">
</div>
</div>
<div class="thematic-content" style="width: 45%;margin-left: 5%;">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">打压遏制强度变化</div>
<div class="item-header-right"> <img class="item-header-right-icon" src="@/assets/images/icon/tips.png"></img>
数据来源:美国某某局</div>
</div>
<div class="item-header-divider"></div>
<div style="display: flex;height: calc(100% - 60px);" id="char2">
</div>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref, computed } from "vue";
import * as echarts from "echarts";
import getBarChart from '../js/barChart.js'
import radarChart from '../js/radarChart.js'
const timeLine = ref([
{
time: '2025年1月',
titlle: '《AI扩散暂行最终规则》发布0',
content: '拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。'
},
{
time: '2025年1月',
titlle: '《AI扩散暂行最终规则》发布1',
content: '拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。'
},
{
time: '2025年1月',
titlle: '特朗普签署EO 143202',
content: '拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。'
},
{
time: '2025年1月',
titlle: '《AI扩散暂行最终规则》发布3',
content: '拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。'
},
{
time: '2025年7月23日',
titlle: '《AI扩散暂行最终规则》发布4',
content: '拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。'
},
])
// 过滤出奇数下标(1,3,5...)
const timeLineOddIndexItems = computed(() =>
timeLine.value.filter((_, idx) => idx % 2 === 1)
)
// 过滤出偶数下标(1,3,5...)
const timeLineIndexItems = computed(() =>
timeLine.value.filter((_, idx) => idx % 2 === 0)
)
const distribution = ref([
{
titlle: '法案',
value: 80,
text: '1626个',
change: '较上个月+3',
bgColor1: '#E6F4FF',//浅色
bgColor2: '#91CAFF',//深色
borderColor: '#0958D9',
}, {
titlle: '法案',
value: 20,
text: '1626个',
change: '较上个月+3',
bgColor1: '#FFFBE6',//浅色
bgColor2: '#FDE19A',//深色
borderColor: '#D48806',
}, {
titlle: '法案',
value: 10,
text: '1626个',
change: '较上个月+3',
bgColor1: '#E6F4FF',//浅色
bgColor2: '#91CAFF',//深色
borderColor: '#0958D9',
}, {
titlle: '法案',
value: 40,
text: '1626个',
change: '较上个月+3',
bgColor1: '#E6F4FF',//浅色
bgColor2: '#91CAFF',//深色
borderColor: '#0958D9',
}, {
titlle: '法案',
value: 50,
text: '1626个',
change: '较上个月+3',
bgColor1: '#E6F4FF',//浅色
bgColor2: '#91CAFF',//深色
borderColor: '#0958D9',
}
])
const timeIndex = ref(0)
//时间轴及遏制手段分布按钮
function changeBtn(data, type) {
if (type === 'left') {
timeIndex.value === 0 ? '' : timeIndex.value = timeIndex.value - 1
} else {
(timeIndex.value.length - timeIndex.value <= 4) ? '' : timeIndex.value = timeIndex.value + 1
}
}
const chart1Data = ref({
name: [
"2024-12",
"2025-1",
"2025-2", "2025-3", "2025-4", "2025-5", "2025-6", "2025-7",
],
value: [83.76, 76.72, 73.89, 72.16, 66.24, 65.47, 63.98, 62.12, 44.38, 24.79],
});
// 绘制echarts图表
const setChart = (option, chartId) => {
let chartDom = document.getElementById(chartId);
console.log(chartDom, 'chartDomchartDomchartDom')
chartDom.removeAttribute("_echarts_instance_");
let chart = echarts.init(chartDom);
chart.setOption(option);
return chart;
};
onMounted(() => {
let char1 = getBarChart(chart1Data.value.name, chart1Data.value.value, true);
setChart(char1, "chart1");
let char2 = radarChart()
setChart(char2, "char2");
});
</script>
<style lang="scss" scoped>
.cup-box {
overflow-x: auto;
.cup-item-box {
width: 220px;
text-align: center;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: var(---, 10px);
margin: 20px;
padding: 20px;
.cup-title {
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
letter-spacing: 0px;
text-align: center;
margin-bottom: 20px;
}
}
}
/* 杯子:正圆 */
.cup {
position: relative;
width: 130px;
height: 130px;
/* 本身高度设为 0,内容靠子元素或绝对定位 */
border-radius: 50%;
border: 4px #2196f3 solid;
overflow: hidden;
/* 关键:把超出部分裁掉 */
display: flex;
align-items: flex-end;
/* 水永远贴底 */
justify-content: center;
border: 4px solid #2196f3;
/* 内圈实线 */
outline: 4px solid #2196f3;
/* 外圈实线 */
outline-offset: 4px;
/* 两线间距,想再宽调大即可 */
}
/* 水位层 */
.water {
width: 100%;
height: calc(var(--percent) * 1%);
/* 0~100 对应 0~100% */
background: linear-gradient(to top, var(--c1), var(--c2));
position: relative;
animation: wave 3s linear infinite;
}
/* 波浪 */
.water::before,
.water::after {
content: '';
position: absolute;
width: 400px;
height: 400px;
top: -350px;
/* 把圆心顶到上面去 */
left: 50%;
border-radius: 45%;
transform: translate(-50%, 0);
background: rgba(255, 255, 255, .4);
animation: rotate 7s linear infinite;
}
.water::after {
top: -370px;
border-radius: 40%;
opacity: .7;
animation-duration: 9s;
animation-direction: reverse;
}
/* 旋转动画 */
@keyframes rotate {
to {
transform: translate(-50%, 0) rotate(360deg);
}
}
/* 百分比文字 */
.txt {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font: 24px/1 sans-serif;
color: #0d47a1;
z-index: 2;
}
.thematic-box {
height: 1500px;
}
.title-text {
font-size: 32px;
font-weight: 700;
line-height: 42px;
margin: 40px;
text-align: center;
}
.title-img {
width: 100%;
height: 42px;
}
.thematic-content {
/* 容器 480 */
width: 100%;
height: 450px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: var(---, 10px);
/* 业务系统/模块阴影 */
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.item-header {
height: 48px;
width: 100%;
display: flex;
.item-header-icon {
width: 20px;
height: 20px;
margin: 15px;
}
.item-header-text {
width: 250px;
font-size: 20px;
font-weight: 700;
line-height: 26px;
background: rgba(255, 255, 255, 0.65);
color: #055FC2;
font-family: Microsoft YaHei;
font-size: 20px;
line-height: 48px;
text-align: left;
}
.item-header-right {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
line-height: 48px;
text-align: right;
width: calc(100% - 350px);
.item-header-right-icon {
/* 容器 704 */
width: 14px;
height: 16px;
}
}
}
.timeLine-box {
height: 100%;
width: calc(100% - 50px);
.time-item-box {
width: 30%;
height: 165px;
}
}
.item-header-divider {
/* 矩形 249 */
width: 100%;
height: 1px;
background: #eaecee;
}
.thematic-btn-left {
height: 100%;
width: 24px;
}
.thematic-btn-right {
height: 100%;
width: 24px;
}
.thematic-btn-icon {
height: 48px;
width: 100%;
margin-top: calc(50% - 24px);
}
}
</style>
<!-- 中M博弈概览页 -->
<template>
<div class="resource-box">
<img class="title-img" src="@/assets/images/bg/概览页模块标题3.png"></img>
<div style="margin-top: 20px;height: 450px;display: flex;">
<div class="resource-content" style="width:100%; display: flex;">
<div style="width: 50%;height: 100%;" id="char7">
</div>
<div style="width: 50%;height: 100%;text-align: center;">
<div v-for="value in data">
<div>{{ value.name }}</div>
<div class="progress-row">
<div class="progress-wrapper left">
<el-progress :percentage="value.value[0]" :stroke-width="20" class="left-progress" />
<span class="inner-text">{{ value.value[0] }}%</span>
</div>
<!-- 右侧进度条 -->
<div class="progress-wrapper right">
<el-progress :percentage="value.value[1]" :stroke-width="20" class="right-progress" />
<span class="inner-text">{{ value.value[0] }}%</span>
</div>
</div>
</div>
<!-- 左侧进度条 -->
</div>
<div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref, computed } from "vue";
import * as echarts from "echarts";
import radarChart3 from '../js/radarChart3.js'
// 绘制echarts图表
const setChart = (option, chartId) => {
let chartDom = document.getElementById(chartId);
chartDom.removeAttribute("_echarts_instance_");
let chart = echarts.init(chartDom);
chart.setOption(option);
return chart;
};
const data = ref([
{
name: '竞争潜力',
value: [81.7, 75.4]
}, {
name: '研究人员总数',
value: [81.7, 75.4]
}, {
name: '研发经费投入总额',
value: [81.7, 75.4]
}, {
name: '研发经费占GDP的比重',
value: [81.7, 75.4]
}, {
name: '每万人研发经费投入额',
value: [81.7, 75.4]
}, {
name: '每万研究人员经费投入额',
value: [81.7, 75.4]
}, {
name: '每万人研究人员数',
value: [81.7, 75.4]
}
])
onMounted(() => {
let char7 = radarChart3()
setChart(char7, "char7");
});
</script>
<style lang="scss" scoped>
/* ========== 一行两个 ========== */
.progress-row {
display: flex;
gap: 16px;
align-items: center;
padding: 10px;
}
/* ========== 公共外壳 ========== */
.progress-wrapper {
position: relative;
flex: 1;
height: 20px;
}
/* 文字居中在彩色条内 */
.inner-text {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 12px;
color: #fff;
font-weight: bold;
z-index: 2;
}
/* ========== 左侧:右侧斜切 + 左侧圆角 ========== */
/* 左侧文字 */
.left-text {
font-size: 12px;
color: #333;
margin-right: 8px;
white-space: nowrap;
}
.left-progress :deep(.el-progress-bar__outer) {
border-radius: 10px 0 0 10px;
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 100%, 0 100%);
background: #aed6ff;
overflow: hidden;
}
.left-progress :deep(.el-progress-bar__inner) {
border-radius: 10px 0 0 10px;
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 100%, 0 100%);
background: #aed6ff;
}
/* ========== 右侧:左侧斜切 + 右侧圆角 ========== */
.right-progress :deep(.el-progress-bar__outer) {
border-radius: 0 10px 10px 0;
clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%);
background: #ffccc7;
overflow: hidden;
}
.right-progress :deep(.el-progress-bar__inner) {
border-radius: 0 10px 10px 0;
clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%);
background: #ff7875;
}
.resource-box {
height: 700px;
}
.title-text {
font-size: 32px;
font-weight: 700;
line-height: 42px;
margin: 40px;
text-align: center;
}
.title-img {
width: 100%;
height: 42px;
}
.resource-content {
/* 容器 480 */
width: 100%;
height: 450px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: var(---, 10px);
/* 业务系统/模块阴影 */
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.item-header {
height: 48px;
width: 100%;
display: flex;
.item-header-icon {
width: 20px;
height: 20px;
margin: 15px;
}
.item-header-text {
width: 250px;
font-size: 20px;
font-weight: 700;
line-height: 26px;
background: rgba(255, 255, 255, 0.65);
color: #055FC2;
font-family: Microsoft YaHei;
font-size: 20px;
line-height: 48px;
text-align: left;
}
.item-header-right {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
line-height: 48px;
text-align: right;
width: calc(100% - 350px);
.item-header-right-icon {
/* 容器 704 */
width: 14px;
height: 16px;
}
}
}
.item-header-divider {
/* 矩形 249 */
width: 100%;
height: 1px;
background: #eaecee;
}
}
</style>
<!-- 中M博弈概览页 -->
<template>
<div class="content-main">
<!-- 面包屑 -->
<div class="content-title"><span>国家科技安全</span>> <span>中美博弈概览 </span></div>
<!-- 中美博弈最新动态内容-->
<div class="content-box">
<div class="title-text">中美博弈最新动态 </div>
<div class="title-text-small">
提供半导体、AI、量子等关键领域的竞争动态、政策追踪与产业链分析,实时把握中美博弈全局
</div>
<div class="box">
<div class="item left">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/overview-card-header-icon.png"></img>
<div class="item-header-text">机构动态</div>
<div class="item-header-more">更多 +</div>
</div>
<div class="item-header-divider"></div>
<div class="item-content">
<div class="item-card" style="">
<div class="item-card-btn-left" @click="changeOrganizationNews('left')">
<img class="item-btn-icon" src="@/assets/images/icon/card-btn-left.png"></img>
</div>
<!-- 机构动态内容-->
<div class="item-card-content">
<div class="item-card-content-header">
<div style="width: calc(100% - 80px);">
<div class="item-card-content-title">
{{ organizationNews[organizationNewsShow].title }}
</div>
<div class="item-card-content-title-small">
{{ organizationNews[organizationNewsShow].time, organizationNews[organizationNewsShow].adress }}
</div>
</div>
<img class="item-card-content-title-image" :src="organizationNews[organizationNewsShow].image" alt="">
</div>
<div class="item-header-divider"></div>
<div class="item-card-content-text ">
{{ organizationNews[organizationNewsShow].content }}
</div>
<div style="display: flex">
<div class="item-card-content-tag" v-for="tag in organizationNews[organizationNewsShow].tag"
:style="{ color: tag.textColor, background: tag.color, borderColor: tag.color }">
{{ tag.text }}
</div>
</div>
</div>
<div class="item-card-btn-right" @click="changeOrganizationNews('right')">
<img class="item-btn-icon" src="@/assets/images/icon/card-btn-right.png"></img>
</div>
</div>
<div class="item-card-right ">
<div class="item-list">
<div v-for="organizationItem in organizationList" style="height: 40px">
<div style="display: flex;margin: 10px">
<div class="item-list-punblier">
{{ organizationItem.punblier }}
</div>
<div class="item-list-content">
{{ organizationItem.content }}
</div>
<div class="item-list-time">
{{ organizationItem.time }}
</div>
</div>
<div class="item-header-divider"></div>
</div>
</div>
</div>
</div>
</div>
<!--风险信号-->
<div class="item left">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/waring-card-header-icon.png"></img>
<div class="item-header-text" style="background-color: #CE4F51;">风险信号</div>
</div>
<div class="item-header-divider"></div>
<div style="padding: 30px 10px;height: 350px;">
<div class="waring-item" v-for="(item, index) in warningList" :key="index">
<div style="display: flex;height: 40px;">
<div class="waring-status" :style="{
color: item.status === 0 ? '#CE4F51' : item.status === 1 ? '#FA8C16' : '#52C41A',
backgroundColor: item.status === 0 ? '#FFF1F0' : item.status === 1 ? '#FFF7E6' : '#F6FFED'
}">
{{ item.status === 0 ? '特别重大' : item.status === 1 ? '重大风险' : '一般风险'
}}
</div>
<div class="waring-text">
{{ item.title }}
</div>
<div class="waring-time">{{ item.time }}</div>
</div>
<div class="item-header-divider"></div>
</div>
</div>
<div class="item-btn">
查看更多
</div>
</div>
<!--新闻资讯-->
<div class="item right">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/news-card-header-icon.png"></img>
<div class="item-header-text" style="background: rgba(255, 255, 255, 0.65) ;color:#055FC2">新闻资讯</div>
<div class="item-header-more" style=" color:#055FC2">更多 +</div>
</div>
<div class="item-header-divider"></div>
<div class="news-box">
<div v-for="item in newsList" class="news-box-item">
<div style=" display: flex;">
<img :src="item.image"></img>
<div style="padding: 0 10px ;">
<div class="news-box-title">
{{ item.title }}
</div>
<div class="news-box-title-small">
{{ item.time + item.publier }}
</div>
</div>
</div>
</div>
</div>
</div>
<!--人物动态-->
<div class="item right">
<div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/people-card-header-icon.png"></img>
<div class="item-header-text" style="background: rgba(255, 255, 255, 0.65) ;color:#055FC2">人物动态</div>
<div class="item-header-more" style=" color:#055FC2">更多 +</div>
</div>
<div class="item-header-divider"></div>
<div class="character-box">
<div class="character-item" v-for="item in characterDynamics">
<img :src="item.image" class="character-image"></img>
<div class="talk-box">
<div style="display: flex;">
<div class="talk-title">
{{ item.name }}
</div>
<div style="width: 60%;text-align: right;">
{{ item.position + '.' + item.time }}
</div>
</div>
{{ item.talk }}
</div>
</div>
</div>
</div>
</div>
<div>
<Thematicanalysis />
<ResourceSupport />
<strengthComparison />
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import Thematicanalysis from './component/Thematicanalysis.vue'
import ResourceSupport from './component/ResourceSupport.vue'
import strengthComparison from './component/strengthComparison.vue'
import router from "@/router";
import { color } from "echarts";
const organizationNews = ref([
{
title: '1美国白宫发布关于进一步延长TikTok执法宽限期的行政令',
time: '2025年9月16日',
adress: '美国白宫',
image: '/testData/organizationNews-image1.png',
content: '9月16日,美国白宫官方网站发布总统政令,再次推迟(第四次)对TikTok禁令的执法,新的宽限期截止日为2025年12月16日​。在宽限期内及对于宽限期前的行为,司法部不得强制执行​《保护美国人免受外国对手控制应用程序法》或因此处罚相关实体​(如TikTok及其分发平台)。司法部还需',
tag: [{
color: '#FFF1F0',
textColor: ' rgba(245, 34, 45, 1)',
text: '人工智能'
}, {
color: '#E6F4FF',
textColor: ' rgba(22, 119, 255, 1)',
text: '通信网络'
}]
},
{
title: '2美国白宫发布关于进一步延长TikTok执法宽限期的行政令',
time: '2025年9月16日',
adress: '美国白宫',
image: '/testData/organizationNews-image1.png',
content: '9月16日,美国白宫官方网站发布总统政令,再次推迟(第四次)对TikTok禁令的执法,新的宽限期截止日为2025年12月16日​。在宽限期内及对于宽限期前的行为,司法部不得强制执行​《保护美国人免受外国对手控制应用程序法》或因此处罚相关实体​(如TikTok及其分发平台)。司法部还需',
tag: [{
color: '#F5222D',
textColor: ' #FFF1F0',
text: '人工智能'
}, {
color: '#E6F4FF',
textColor: ' #1677FF',
text: '通信网络'
}]
}
,
{
title: '3美国白宫发布关于进一步延长TikTok执法宽限期的行政令',
time: '2025年9月16日',
adress: '美国白宫',
image: '/testData/organizationNews-image1.png',
content: '9月16日,美国白宫官方网站发布总统政令,再次推迟(第四次)对TikTok禁令的执法,新的宽限期截止日为2025年12月16日​。在宽限期内及对于宽限期前的行为,司法部不得强制执行​《保护美国人免受外国对手控制应用程序法》或因此处罚相关实体​(如TikTok及其分发平台)。司法部还需',
tag: [{
color: '#FFF1F0',
textColor: ' rgba(245, 34, 45, 1)',
text: '人工智能'
}, {
color: '#E6F4FF',
textColor: ' rgba(22, 119, 255, 1)',
text: '通信网络'
}]
}
])//机构动态
const organizationNewsShow = ref(0)//机构动态当前展示条目
const organizationList = ref([
{
time: "1小时前",
content: "特朗普于美国独立日签署法案,​公法编号Pub. L. No. 119-21。白宫举行庆典,B-2轰炸机飞越上空,象征“美国新时代”开启。",
punblier: "国会",
},
{
time: "10小时前",
content: "众议院最终表决218票赞成 vs 214票反对,修订版法案以4票优势通过,2名共和党议员倒戈,民主党全员反对。",
punblier: "商务部",
},
{
time: "11小时前",
content: "民主党领袖杰弗里斯发表 ​8小时45分钟​ 演讲(众议院现代史最长),抗议法案“劫贫济富”,但仍未阻止表决。",
punblier: "财政部",
},
{
time: "一天前",
content: "众议院以 ​219:213​ 通过程序规则,为最终表决铺路。此前4名共和党议员反对程序规则,议长约翰逊紧急游说挽回1票。",
punblier: "FCC",
},
{
time: "周三",
content: "参议院最终表决投票51:50​,副总统万斯(JD Vance)投出关键票打破平局。3名共和党参议员倒戈(蒂利斯、保罗、柯林斯)。",
punblier: "白宫",
},
])//机构动态
//风险信号
const warningList = ref([
{
title: "美国大而美法案落地,总统签署通过",
time: "一天前",
status: 2
},
{
title: "美大而美法案7月1日以51:50的票数胜出",
time: "一天前",
status: 2
},
{
title: "首次提出“限制外国敏感实体获取补",
time: "一天前",
status: 1
},
{
title: "首次提出“限制外国敏感实体获取补偿",
time: "一天前",
status: 1
},
{
title: "首次提出“限制外国敏感实体获取补偿",
time: "一天前",
status: 0
}
]);
//新闻资讯
const newsList = ref([
{
image: '/testData/news-1.png',
title: ' 美国联邦政府停摆持续临时拨款法案再次“闯关”失败美政府即将刷新“停摆”纪录 ',
time: '11-4',
publier: '华盛顿纽约'
}, {
image: '/testData/news-1.png',
title: ' 美国联邦政府停摆持续临时拨款法案再次“闯关”失败美政府即将刷新“停摆”纪录 ',
time: '11-4',
publier: '华盛顿纽约'
}, {
image: '/testData/news-1.png',
title: ' 美国联邦政府停摆持续临时拨款法案再次“闯关”失败美政府即将刷新“停摆”纪录 ',
time: '11-4',
publier: '华盛顿纽约'
}, {
image: '/testData/news-1.png',
title: ' 美国联邦政府停摆持续临时拨款法案再次“闯关”失败美政府即将刷新“停摆”纪录 ',
time: '11-4',
publier: '华盛顿纽约'
}, {
image: '/testData/news-1.png',
title: ' 美国联邦政府停摆持续临时拨款法案再次“闯关”失败美政府即将刷新“停摆”纪录 ',
time: '11-4',
publier: '华盛顿纽约'
}, {
image: '/testData/news-1.png',
title: ' 美国联邦政府停摆持续临时拨款法案再次“闯关”失败美政府即将刷新“停摆”纪录 ',
time: '11-4',
publier: '华盛顿纽约'
}
])
//人物动态
const characterDynamics = ref([
{
image: '/testData/united_states 1.png',
name: '詹姆斯·刘易斯',
position: '商务部某办公室主任',
time: '一天前',
talk: '指出美国在AI赋能科学,特别是“自驱实验室”等自动化科研设施上的投资不足,呼吁进行系统性战略投资'
},
{
image: '/testData/united_states 2.png',
name: '迈克尔·霍洛维茨',
position: '某计划署主席',
time: '一天前',
talk: '评价特朗普政府《AI国家行动计划》,认为其关键在于通过技术出口和基础设施建设主动抢占全球AI主导权。'
},
{
image: '/testData/united_states 1.png',
name: '詹姆斯·戴维·万斯',
position: '副总统',
time: '一天前',
talk: '提出特朗普政府的AI政策强调技术开放与快速应用,但可能以牺牲安全防范为代价,开启了“潘多拉魔盒”。'
},
])
function changeOrganizationNews(type) {
if (type === 'left') {
organizationNewsShow.value === 0 ? '' : organizationNewsShow.value = organizationNewsShow.value - 1
} else {
organizationNews.value === organizationNews.value.length - 1 ? '' : organizationNewsShow.value = organizationNewsShow.value + 1
}
}
onMounted(() => { });
</script>
<style lang="scss" scoped>
.content-main {
width: 100%;
height: 100%;
overflow: hidden;
.content-title {
height: 64px;
color: #fff;
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
line-height: 64px;
background: url("../../assets/images/bg//header-bg.png");
box-sizing: border-box;
padding-left: 160px;
}
.content-box {
width: 100%;
height: 100%;
overflow: auto;
padding: 0 160px;
.title-text {
font-size: 32px;
font-weight: 700;
line-height: 42px;
margin: 40px;
text-align: center;
}
.title-text-small {
font-size: 20px;
font-weight: 400;
line-height: 30px;
margin: 40px;
text-align: center;
}
/* 父级:2×2 网格,固定间距 */
.box {
display: grid;
grid-template-columns: 2fr 1fr;
/* 左列宽是右列的 2 倍 */
grid-auto-rows: 1fr;
/* 两行等高 */
gap: 16px;
/* 横竖间距都是 16 px */
height: 1000px;
/* 示例:撑满视口,可改 */
}
/* 子级:仅上色居中,方便观察 */
.item {
height: 450px;
justify-content: center;
box-sizing: border-box;
border: 1px solid var(--主色/白色主色, rgba(255, 255, 255, 1));
border-radius: var(---, 10px);
/* 业务系统/模块阴影 */
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 0.65);
.item-header {
height: 48px;
width: 100%;
display: flex;
.item-header-icon {
width: 20px;
height: 20px;
margin: 15px;
}
.item-header-text {
width: 112px;
background: #055FC2;
color: #ffffff;
font-family: Microsoft YaHei;
font-size: 20px;
line-height: 48px;
text-align: center;
}
.item-header-more {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
line-height: 48px;
text-align: center;
margin-left: calc(100% - 200px);
width: 50px;
margin-left: calc(100% - 250px);
}
}
.item-header-divider {
/* 矩形 249 */
width: 100%;
height: 1px;
background: #eaecee;
}
.item-card-content-tag {
width: 74px;
height: 24px;
padding: 1px 8px 1px 8px;
margin: 2px;
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 20px;
letter-spacing: 0px;
text-align: justify;
box-sizing: border-box;
border: 1px;
border-radius: 4px;
}
.item-content {
height: calc(100% - 50px);
width: 100%;
display: flex;
padding: 20px;
.item-card {
width: 50%;
height: 100%;
display: flex;
box-sizing: border-box;
border: 1px solid var(--主色/白色主色, rgba(255, 255, 255, 1));
border-radius: 10px;
/* 业务系统/模块阴影 */
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 0.3);
.item-card-btn-left {
height: 100%;
width: 24px;
padding-top: calc(50% - 20px);
}
.item-card-content {
height: 100%;
width: calc(100% - 50px);
padding: 20px;
.item-card-content-header {
display: flex;
.item-card-content-title {
color: var(rgba(59, 65, 75, 1));
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
letter-spacing: 0px;
text-align: justify;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
word-break: break-all;
}
.item-card-content-title-small {
color: var(rgba(95, 101, 108, 1));
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
}
.item-card-content-title-image {
height: 50px;
width: 50px;
}
.item-card-content-text {
color: var(rgba(95, 101, 108, 1));
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: left;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 7;
text-overflow: ellipsis;
word-break: break-all;
}
}
.item-btn-icon {
height: 48px;
width: 100%;
margin-top: calc(50% - 24px);
}
.item-card-btn-right {
height: 100%;
width: 24px;
padding-top: calc(50% - 20px);
}
}
.item-card-right {
width: 50%;
height: 100%;
display: flex;
.item-list {
padding: 10px;
.item-list-punblier {
width: 64px;
height: 22px;
border-radius: 4px;
background: rgba(231, 243, 255, 1);
text-align: center;
padding: 1px 4px 1px 4px;
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 20px;
letter-spacing: 0px;
margin-right: 5px;
}
.item-list-content {
width: calc(100% - 150px);
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
text-overflow: ellipsis;
word-break: break-all;
}
.item-list-time {
width: 68px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: right;
}
}
}
}
.waring-item {
.waring-status {
width: 40px;
height: 40px;
border-radius: 50%;
font-size: 14px;
margin-right: 5px;
}
.waring-text {
color: rgba(59, 65, 75, 1);
width: calc(100% - 180px);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
text-overflow: ellipsis;
word-break: break-all;
}
.waring-time {
width: 68px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: right;
}
}
.item-btn {
/* Buttons按钮/主按钮/亮色/默认 */
width: 460px;
height: 42px;
margin: 0 20px;
/* 自动布局 */
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 8;
padding: 5px 16px 5px 16px;
border-radius: 6px;
background: rgba(5, 95, 194, 1);
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: center;
}
/* 新闻资讯 */
.news-box {
display: grid;
grid-template-columns: 1fr 1fr;
/* 两列,等宽 */
gap: 10px;
height: 400px;
overflow: hidden;
.news-box-item {
padding: 20px;
.news-box-item-img {
/* 矩形 265 */
width: 96px;
height: 72px;
}
.news-box-title {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
letter-spacing: 0px;
text-align: justify;
overflow: hidden;
display: -webkit-box;
/* 旧语法,但必须写 */
-webkit-box-orient: vertical;
/* 垂直排列 */
-webkit-line-clamp: 2;
/* 限制两行 */
text-overflow: ellipsis;
/* 兜底,部分旧机需要 */
/* 可选:防止单词过长撑开 */
word-break: break-all;
}
.news-box-title-small {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
}
}
}
/* 人物动态 */
.character-box {
.character-item {
display: flex;
padding: 17px;
.character-image {
/* united_states 1 */
width: 36px;
height: 36px;
border-radius: 50%;
}
.talk-box {
height: 98px;
width: 100%;
padding: 17px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
background-image: url("../../assets/images/bg/characterDynamics-bg.png");
background-repeat: no-repeat;
/* 不重复 */
background-size: 100% 100%;
/* 自动拉伸并覆盖整个元素,保持比例 */
background-position: center center;
.talk-title {
width: 40%;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
}
}
}
}
}
}
</style>
import * as echarts from "echarts";
const getColumnChart = (nameList, valueList, isPer) => {
const colorList = ['#0958D9', '#0958D9']
return {
tooltip: {},
grid: { top: '10%', right: '3%', bottom: '15%', left: '3%', containLabel: true },
color: colorList,
xAxis: {
type: 'category',
data: nameList,
axisLine: { show: false },
axisTick: { show: false },
axisLabel: {
show: true,
rotate: 45, // ① 文字 45°
color: '#666',
fontSize: 12
}
},
yAxis: {
type: 'value',
axisLine: { show: false },
axisTick: { show: false },
axisLabel: { show: true, color: '#666' }, // ② Y 轴文字
splitLine: { // ③ 横向参考线
show: true,
lineStyle: { color: '#ebebeb', width: 1 }
}
},
series: [{
type: 'bar',
data: valueList.map((v, i) => ({
value: v,
label: { show: false, position: 'top', color: i < 3 ? colorList[0] : colorList[1] }
})),
barWidth: 16,
itemStyle: {
borderRadius: [8, 8, 0, 0],
color: params => {
const colors = params.dataIndex < 3
? [colorList[0], 'rgba(255,255,255,0)']
: [colorList[1], 'rgba(255,255,255,0)']
return new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: colors[0] },
{ offset: 1, color: colors[1] }
])
}
},
label: {
show: true,
position: 'top',
formatter: v => (isPer ? v.value + '%' : v.value)
}
}]
}
}
export default getColumnChart
\ No newline at end of file
import * as echarts from "echarts";
const getColumnChart = (nameList, series1, series2, isPer) => {
// 两套渐变
const gradBlue = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#055FC2' },
{ offset: 1, color: '#BAE0FF' }
])
const gradCyan = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#CE4F51' },
{ offset: 1, color: '#FFA39E' }
])
return {
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
grid: { top: '10%', right: '3%', bottom: '15%', left: '3%', containLabel: true },
legend: { data: ['中国', '美国'], top: 0 },
xAxis: {
type: 'category',
data: nameList,
axisLine: { show: false },
axisTick: { show: false },
axisLabel: { rotate: 45, color: '#666', fontSize: 12 }
},
yAxis: {
type: 'value',
axisLine: { show: false },
axisTick: { show: false },
axisLabel: { show: true, color: '#666' },
splitLine: { show: true, lineStyle: { color: '#ebebeb' } }
},
series: [
{
name: '中国',
type: 'bar',
data: series1,
barWidth: 16,
label: { show: false },
itemStyle: { borderRadius: [8, 8, 0, 0], color: gradBlue }
},
{
name: '美国',
type: 'bar',
data: series2,
barWidth: 16,
label: { show: false },
itemStyle: { borderRadius: [8, 8, 0, 0], color: gradCyan }
}
]
}
}
export default getColumnChart
\ No newline at end of file
import * as echarts from 'echarts'
const getMultiLineChart = (dataX, dataY1, dataY2) => {
return {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
grid: {
top: '8%',
right: '5%',
bottom: '5%',
left: '5%',
containLabel: true
},
legend: {
data: ['中国', '美国'],
show: true
},
color: ['#AED6FF', '#FF7875'],
xAxis: [
{
type: 'category',
boundaryGap: false,
data: dataX
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: '中国',
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: '#0958D9' // 起始颜色
}, {
offset: 1,
color: 'rgba(22, 119, 255, 0)' // 结束颜色
}])
},
emphasis: {
focus: 'series'
},
data: dataY1
},
{
name: '美国',
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: '#FF7875' // 起始颜色
}, {
offset: 1,
color: 'rgba(255, 172, 77, 0)' // 结束颜色
}])
},
emphasis: {
focus: 'series'
},
data: dataY2
}
]
}
}
export default getMultiLineChart
\ No newline at end of file
import * as echarts from "echarts";
const getBarChart = (nameList, valueList, isPer) => {
const option = {
title: { text: '' },
legend: {
icon: 'circle',
orient: 'vertical', // 纵向排列
right: 0, // 贴右边
top: 'center', // 垂直居中
align: 'left', // 文字在图标左侧
data: ['法案', '行政令', '科技智库', '出口管制', '投融资限制', '市场准入']
},
radar: {
indicator: [
{ name: '能源', max: 6500 },
{ name: '集成电路', max: 16000 },
{ name: '人工智能', max: 30000 },
{ name: '通信网络', max: 38000 },
{ name: '量子科技', max: 52000 },
{ name: '生物科技', max: 25000 }
],
axisName: {
formatter: '{value}',
color: 'rgba(59, 65, 75, 1)',
fontSize: 16,
fontWeight: 700
}
},
series: [
{
name: 'Budget vs spending',
type: 'radar',
data: [
{
value: [4200, 3000, 20000, 35000, 50000, 18000],
name: '法案',
areaStyle: { color: 'rgba(10, 87, 166, 0.2)' }
},
{
value: [5000, 14000, 28000, 26000, 42000, 21000],
name: '行政令',
areaStyle: { color: 'rgba(206, 79, 81, 0.2)' }
},
{
value: [4000, 14000, 18000, 21000, 32000, 10000],
name: '科技智库',
areaStyle: { color: 'rgba(250, 140, 22, 0.2)' }
},
{
value: [4000, 14000, 18000, 21000, 32000, 10000],
name: '出口管制',
areaStyle: { color: 'rgba(250, 140, 22, 0.2)' }
},
{
value: [4000, 14000, 18000, 21000, 32000, 10000],
name: '投融资限制',
areaStyle: { color: 'rgba(250, 140, 22, 0.2)' }
},
{
value: [4000, 14000, 18000, 21000, 32000, 10000],
name: '市场准入',
areaStyle: { color: 'rgba(250, 140, 22, 0.2)' }
}
]
}
]
}
return option
}
export default getBarChart
\ No newline at end of file
import * as echarts from "echarts";
const getBarChart = (nameList, valueList, isPer) => {
const option = {
title: { text: '' },
legend: {
icon: 'circle',
orient: 'vertical', // 纵向排列
right: 0, // 贴右边
top: 'center', // 垂直居中
align: 'left', // 文字在图标左侧
data: ['中国', '美国']
},
radar: {
indicator: [
{ name: '能源', max: 6500 },
{ name: '集成电路', max: 16000 },
{ name: '人工智能', max: 30000 },
{ name: '通信网络', max: 38000 },
{ name: '量子科技', max: 52000 },
{ name: '生物科技', max: 25000 }
],
axisName: {
formatter: '{value}',
color: 'rgba(59, 65, 75, 1)',
fontSize: 16,
fontWeight: 700
}
},
series: [
{
name: 'Budget vs spending',
type: 'radar',
data: [
{
value: [4200, 3000, 20000, 35000, 50000, 18000],
name: '中国',
areaStyle: { color: 'rgba(10, 87, 166, 0.2)' }
},
{
value: [5000, 14000, 28000, 26000, 42000, 21000],
name: '美国',
areaStyle: { color: 'rgba(206, 79, 81, 0.2)' }
},
]
}
]
}
return option
}
export default getBarChart
\ No newline at end of file
import * as echarts from "echarts";
const getBarChart = (nameList, valueList, isPer) => {
const option = {
title: { text: '' },
legend: {
show: false,
icon: 'circle',
orient: 'vertical',
right: 0,
top: 'center',
align: 'left',
data: ['法案', '行政令', '科技智库', '出口管制', '投融资限制', '市场准入']
},
radar: {
shape: 'circle', // ① 参考线变弧线
indicator: [
{ name: '研究人员总数', max: 6500 },
{ name: '每万人研究人员数', max: 16000 },
{ name: '每万研究人员研发经费投入额', max: 30000 },
{ name: '每万人研发经费投入额', max: 38000 },
{ name: '研发经费占GDP的比重', max: 52000 },
{ name: '研发经费投入总额', max: 25000 }
],
axisName: {
// ② 文字在线上方 + 自动换两行
formatter: function (txt) {
// 按字数 10 左右自动断行
const len = txt.length;
if (len <= 5) return txt;
const br = Math.ceil(len / 2);
return txt.substring(0, br) + '\n' + txt.substring(br);
},
rich: {
a: { lineHeight: 20 } // 行高
},
color: 'rgba(59, 65, 75, 1)',
fontSize: 14,
fontWeight: 600
},
splitLine: {
lineStyle: {
color: 'rgba(200,200,200,.6)'
}
},
splitArea: { show: false },
axisLine: { show: false }
},
series: [{
name: 'Budget vs spending',
type: 'radar',
data: [
{ value: [4200, 3000, 20000, 35000, 50000, 18000], name: '法案', areaStyle: { color: 'rgba(10, 87, 166, 0.2)' } },
{ value: [5000, 14000, 28000, 26000, 42000, 21000], name: '行政令', areaStyle: { color: 'rgba(206, 79, 81, 0.2)' } },
{ value: [4000, 14000, 18000, 21000, 32000, 10000], name: '科技智库', areaStyle: { color: 'rgba(250, 140, 22, 0.2)' } },
{ value: [4000, 14000, 18000, 21000, 32000, 10000], name: '出口管制', areaStyle: { color: 'rgba(22, 180, 120, 0.2)' } },
{ value: [4000, 14000, 18000, 21000, 32000, 10000], name: '投融资限制', areaStyle: { color: 'rgba(120, 100, 200, 0.2)' } },
{ value: [4000, 14000, 18000, 21000, 32000, 10000], name: '市场准入', areaStyle: { color: 'rgba(255, 100, 150, 0.2)' } }
]
}],
// ③ 最外层弧线加粗:用 graphic 画一个圆环覆盖在最外层
graphic: [{
type: 'circle',
shape: { cx: 300, cy: 300, r: '65%' },
style: { stroke: '#333', lineWidth: 30, fill: 'transparent' },
z: 1000
}]
};
return option
}
export default getBarChart
\ No newline at end of file
<template>
<el-card class="card">
<div class="wrap">
<div class="line" :style="{ backgroundColor: lineColor }"></div>
<div class="header" :style="{ height: headerHeight }">
<div class="iconWrap" :style="{ width: iconWidth }">
<slot name="icon">
<el-icon :size="20">
<Edit />
</el-icon>
</slot>
</div>
<div
class="titleWrap"
:style="{
backgroundColor: titleBackgroundColor,
color: titleColor,
paddingLeft: titleTextAlign === 'left' ? '0px' : '20px'
}"
>
{{ title }}
</div>
<div class="rightWrap">
<slot name="right">
<div class="moreWrap">
<el-button text @click="moreClick">
<span class="moreText">更多</span>
<el-icon :size="14"> <Plus /> </el-icon>
</el-button>
</div>
</slot>
</div>
</div>
<div class="body">
<slot name="default"> </slot>
</div>
</div>
</el-card>
</template>
<script setup>
import { Edit, Plus } from "@element-plus/icons-vue";
const emit = defineEmits(["moreClick"]);
defineProps({
titleBackgroundColor: {
type: String,
default: "red"
},
titleColor: {
type: String,
default: "#fff"
},
titleTextAlign: {
type: String,
default: "center"
},
lineColor: {
type: String,
default: "transparent"
},
title: {
type: String,
default: "风险信号"
},
iconWidth: {
type: String,
default: "60px"
},
headerHeight: {
type: String,
default: "48px"
}
});
function moreClick() {
emit("moreClick");
}
</script>
<style lang="scss" scoped>
.card {
position: relative;
:deep(.el-card__body) {
padding: 0;
height: 100%;
}
}
.wrap {
height: 100%;
display: flex;
flex-direction: column;
}
.line {
left: 1px;
right: 1px;
background-color: transparent;
height: 1px;
top: 0;
position: absolute;
}
.header {
height: 48px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
display: flex;
flex-direction: row;
align-items: stretch;
z-index: 1;
position: relative;
flex-shrink: 0;
}
.iconWrap {
width: 60px;
display: flex;
justify-content: center;
align-items: center;
}
.titleWrap {
display: flex;
justify-content: center;
align-items: center;
padding-left: 20px;
padding-right: 20px;
background-color: red;
color: #fff;
font-size: 20px;
font-weight: 700;
}
.rightWrap {
display: flex;
justify-content: end;
align-items: center;
flex: 1;
}
.moreWrap {
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
height: 100%;
padding-left: 10px;
padding-right: 10px;
cursor: pointer;
.moreText {
margin-right: 3px;
}
}
.body {
flex: 1;
padding: 14px 20px;
}
</style>
<template>
<div class="wrap1">
<div class="chart" ref="chart"></div>
<div class="title">{{ data.title }}</div>
<div class="titleSub">{{ data.titleSub }}</div>
<div class="slope">
<div
class="slopeLine"
:style="{
transform: 'rotate(' + (data.current / data.total) * -25 + 'deg)',
top: -88 + (data.current / data.total) * 25 * 0.3 + 'px',
}"
></div>
</div>
</div>
</template>
<script setup>
import { useTemplateRef, onMounted } from "vue";
import { setChart, getPieChart } from "../utils/charts";
const { data } = defineProps({
data: {
type: Object,
},
});
// 第一个参数必须与模板中的 ref 值匹配
const chart = useTemplateRef("chart");
onMounted(() => {
setChart(
getPieChart((data.current / data.total) * 100, data.current, data.total),
chart.value
);
});
</script>
<style lang="scss" scoped>
.wrap1 {
width: 141.6px;
display: flex;
flex-direction: column;
align-items: center;
}
.chart {
width: 94px;
height: 94px;
}
.title {
font-size: 20px;
font-weight: 700;
margin-top: 12px;
color: rgba(59, 65, 75, 1);
}
.titleSub {
font-size: 16px;
font-weight: 400;
margin-top: 2px;
color: rgba(10, 87, 166, 1);
}
.slope {
width: 68px;
height: 40px;
background-color: aqua;
margin-top: 2px;
background: linear-gradient(
180deg,
rgba(20, 67, 187, 0.3),
rgba(20, 67, 187, 0) 100%
);
position: relative;
overflow: hidden;
}
.slopeLine {
height: 100px;
width: 200%;
background-color: #fff;
border-bottom: 1.5px solid blue;
position: absolute;
top: -82px;
left: -50%;
transform: rotate(0deg);
transform-origin: center bottom;
}
</style>
<template>
<div class="wrap">
<el-row>
<CardCustom
@more-click="moreClick"
title="风险信号"
:style="{ width: '986px', height: '540px' }"
title-background-color="rgba(206, 79, 81, 1)"
>
<template #icon>
<div class="icon icon1"></div>
</template>
</CardCustom>
<CardCustom
@more-click="moreClick"
title="安全速递"
:style="{ width: '600px', height: '540px', marginLeft: '14px' }"
title-background-color="rgba(206, 79, 81, 1)"
>
<template #icon>
<div class="icon icon1"></div>
</template>
<div class="item" v-for="(item, index) in securityExpressList" :key="index">
<span class="itemLevel" :class="levelMap[item.level].class">
{{ levelMap[item.level].text }}
</span>
<div class="itemText">{{ item.title }}</div>
<span class="itemTime">{{ item.time }}</span>
<span class="itemFlag" :style="{ backgroundImage: 'url(' + item.flag + ')' }"></span>
</div>
</CardCustom>
</el-row>
<el-card class="gap">
<el-row>
<PieProgress v-for="item in List" :data="item" />
</el-row>
</el-card>
<el-row class="gap">
<CardCustom
@more-click="moreClick"
title="科技动态"
:style="{ width: '792px', height: '360px' }"
title-background-color="rgba(10, 87, 166, 1)"
line-color="rgba(10, 87, 166, 1)"
>
<template #icon>
<div class="icon icon2"></div>
</template>
<div class="itemTrends" v-for="(item, index) in trendsList" :key="index">
<span class="itemTrendsIcon"> </span>
<div class="itemTrendsText">{{ item.title }}</div>
<span class="itemTrendsTime">{{ item.time }}</span>
</div>
</CardCustom>
<CardCustom
@more-click="moreClick"
title="科技政策"
:style="{ width: '792px', height: '360px', marginLeft: '16px' }"
title-background-color="rgba(10, 87, 166, 1)"
line-color="rgba(10, 87, 166, 1)"
>
<template #icon>
<div class="icon icon3"></div>
</template>
<div class="itemTrends" v-for="(item, index) in policyList" :key="index">
<span class="itemTrendsIcon"> </span>
<div class="itemTrendsText">{{ item.title }}</div>
<span class="itemTrendsTime">{{ item.time }}</span>
</div>
</CardCustom>
</el-row>
<div class="gap">
<el-row class="cardContainer">
<div class="itemCard">
<span class="itemCardIcon itemCardIcon1"></span>
<div class="itemCardTitle">业务协同</div>
</div>
<div class="itemCard">
<span class="itemCardIcon itemCardIcon2"></span>
<div class="itemCardTitle">专题研判</div>
</div>
<div class="itemCard">
<span class="itemCardIcon itemCardIcon3"></span>
<div class="itemCardTitle">数据直报</div>
</div>
<div class="itemCard">
<span class="itemCardIcon itemCardIcon4"></span>
<div class="itemCardTitle">专家库</div>
</div>
</el-row>
</div>
<el-row class="gap">
<CardCustom
@more-click="moreClick"
title="最新报告"
:style="{ width: '1600px', height: '360px' }"
title-background-color="rgba(10, 87, 166, 1)"
line-color="rgba(10, 87, 166, 1)"
>
<template #icon>
<div class="icon icon4"></div>
</template>
<template #right>
<div class="moreWrap">
<el-button text @click="moreClick" :style="{ marginLeft: '515px' }">
<span class="moreText">更多</span>
<el-icon :size="14"> <Plus /> </el-icon>
</el-button>
<el-button text @click="moreClick">
<span class="moreText">换一批</span>
<span class="shuaxinIcon"></span>
</el-button>
</div>
</template>
<el-row>
<div :style="{ width: '750px' }">
<div class="itemTrends" v-for="(item, index) in policyList" :key="index">
<span class="itemTrendsIcon"> </span>
<div class="itemTrendsText">{{ item.title }}</div>
<span class="itemTrendsTime">{{ item.time }}</span>
</div>
</div>
<div class="CardCustomRight">
<div class="itemCard1" v-for="item in 3">
<div class="itemCard1Img">
<div class="itemCard1Footer">国内外技术创新合作模式探索与实践</div>
</div>
</div>
</div>
</el-row>
</CardCustom>
</el-row>
<el-row class="gap spaceBetween">
<el-card v-for="(item, index) in catdList" class="itemCard2" :key="index">
<div class="itemCard2Line" :style="{ backgroundColor: item.bgColor }"></div>
<div class="itemCard2Container">
<div class="itemCard2BigTextWrap" :style="{ color: item.bgColor }">
{{ item.title }}
</div>
<div class="itemCard2TextWrap" v-for="(itemText, inde) in item.list" :key="index">
<div class="temCard2Title">{{ itemText.title }}</div>
<div class="temCard2Text">{{ itemText.text }}</div>
</div>
</div>
</el-card>
</el-row>
</div>
</template>
<script setup>
import CardCustom from "../components/CardCustom.vue";
import PieProgress from "../components/PieProgress.vue";
import flag1 from "../assets/img/flag1.png";
import flag2 from "../assets/img/flag2.png";
import flag3 from "../assets/img/flag3.png";
import { ref } from "vue";
const levelMap = {
L1: { text: "特别重大", class: "level1" },
L2: { text: "重大风险", class: "level2" },
L3: { text: "一般风险", class: "level3" }
};
const securityExpressList = ref([
{
title: "美国新增出口管制,52家中国科技实美国新增出口管制,52家中国科技实美国新增出口管制,52家中国科技实美国新增出口管制,52家中国科技实美国新增出口管制,52家中国科技实",
level: "L1",
time: "一天前",
flag: flag1
},
{
title: "美国加强对华AI芯片出口限制,考虑制...",
level: "L1",
time: "一天前",
flag: flag1
},
{
title: "日本出台《半导体材料出口管制令》...",
level: "L1",
time: "一天前",
flag: flag2
},
{
title: "日本对GAAFET技术、EUV光刻设备等...",
level: "L1",
time: "一天前",
flag: flag2
},
{
title: "欧盟签署协议限制高端AI芯片对华出口",
level: "L2",
time: "一天前",
flag: flag3
},
{
title: "欧盟第18轮制裁中首次将3家中资企业...",
level: "L2",
time: "一天前",
flag: flag3
},
{
title: "美国发布《保障信息和通信技术与服务...",
level: "L2",
time: "一天前",
flag: flag1
},
{
title: "日本将42家中国实体列入出口管制“...",
level: "L3",
time: "一天前",
flag: flag2
},
{
title: "美国政府放慢向英伟达和超威等芯片...",
level: "L3",
time: "一天前",
flag: flag1
},
{
title: "七国集团成员国就人工智能发表了以...",
level: "L3",
time: "一天前",
flag: flag3
}
]);
const trendsList = ref([
{
title: "韩研制用于存内计算的小型低功耗神经形态模块",
time: "08-16"
},
{
title: "中国科学院大学等在有机太阳能电池领域取得重要突破",
time: "08-16"
},
{
title: "德国于利希研究中心成功制造并实验验证全球首个二维半金属材料",
time: "08-16"
},
{
title: "浙江大学开发“女娲”AI模型,精准预测基因组调控序列",
time: "08-16"
},
{
title: "我国基于碳量子点材料制备出高效低成本有机太阳能电池",
time: "08-16"
},
{
title: "谷歌Gemini 2.5系列模型更新,实现高速推理与极致性价比",
time: "08-16"
},
{
title: "上海理工大学联合杜克大学在AI赋能仿生视觉技术领域实现突破",
time: "08-16"
}
]);
const policyList = ref([
{
title: "美国发布《2025财年国防授权法案》,拨款替换华为、中兴设备;禁止国防...",
time: "08-16"
},
{
title: "美国发布对华投资限制新规,限制美资在半导体、AI、量子技术等领域的对...",
time: "08-16"
},
{
title: "欧盟发布《网络弹性法案》(CRA),要求数字产品全生命周期安全合规,...",
time: "08-16"
},
{
title: "欧盟发布对外投资审查建议,要求成员国审查在半导体、AI、量子技术等领...",
time: "08-16"
},
{
title: "日本出台《半导体出口管制修正》加强对十余种半导体相关物项的出口管制...",
time: "08-16"
},
{
title: "日本拟出台“许可制”,限制外国留学生(特别提及中国)学习半导体、机...",
time: "08-16"
},
{
title: "日本通过并实施《经济安全保障推进法案》相关措施",
time: "08-16"
}
]);
const List = ref([
{
title: "当月/总数",
titleSub: "较上月+4",
progress: 90,
slope: "add",
total: 8,
current: 7
},
{
title: "人工智能",
titleSub: "较上月+4",
progress: 50,
slope: "add",
total: 26,
current: 3
},
{
title: "生物技术",
titleSub: "较上月+4",
progress: 60,
slope: "add",
total: 13,
current: 3
},
{
title: "航空航天",
titleSub: "较上月+4",
progress: 40,
slope: "add",
total: 15,
current: 3
},
{
title: "新一代信息技术",
titleSub: "较上月+4",
progress: 50,
slope: "add",
total: 12,
current: 3
},
{
title: "量子科技",
titleSub: "较上月+4",
progress: 20,
slope: "add",
total: 8,
current: 3
},
{
title: "新能源",
titleSub: "较上月+4",
progress: 90,
slope: "add",
total: 18,
current: 3
},
{
title: "集成电路",
titleSub: "较上月+4",
progress: 20,
slope: "add",
total: 16,
current: 3
},
{
title: "海洋",
titleSub: "较上月+4",
progress: 50,
slope: "add",
total: 8,
current: 3
},
{
title: "先进制造",
titleSub: "较上月+4",
progress: 50,
slope: "add",
total: 15,
current: 3
},
{
title: "新材料",
titleSub: "较上月+4",
progress: 50,
slope: "add",
total: 8,
current: 3
}
]);
const catdList = ref([
{
title: "数据资源管理",
bgColor: "rgba(206, 79, 81, 1)",
list: [
{
title: "数据资源目录",
text: "平台各类数据资源汇总导航"
},
{
title: "数据统计分析",
text: "查看资源发布量、各部门资源注册情况"
},
{
title: "信息空间",
text: "对数据资源的全生命周期进行管理"
}
]
},
{
title: "信息发布与管理",
bgColor: "rgba(19, 168, 168, 1)",
list: [
{
title: "信息编辑",
text: "信息的内容导入、格式编辑"
},
{
title: "信息审核",
text: "发布前内容自动审核、词库屏蔽"
},
{
title: "信息发布",
text: "提供点到点以及点到面的消息发送"
}
]
},
{
title: "应用支撑平台",
bgColor: "rgba(250, 140, 22, 1)",
list: [
{
title: "应用功能目录",
text: "快速访问和使用系统功能"
},
{
title: "应用工具目录",
text: "各项应用工具的使用方法和应用场景"
},
{
title: "应用功能与工具管理",
text: "实现功能及工具快捷访问配置入口"
}
]
},
{
title: "后台服务管理",
bgColor: "rgba(10, 87, 166, 1)",
list: [
{
title: "界面配置管理",
text: "支持界面布局、样式定制化修改"
},
{
title: "数据接口管理",
text: "实现数据接口的访问调用、权限控制等"
},
{
title: "系统配置管理",
text: "支持各分系统配置的定制与调整"
}
]
}
]);
function moreClick(n) {
alert(n);
}
</script>
<style lang="scss" scoped>
.wrap {
width: 1600px;
margin: 30px auto;
}
.gap {
margin-top: 24px;
}
.icon {
width: 24px;
height: 22px;
background-size: contain;
background-repeat: no-repeat;
}
.icon1 {
background-image: url("../assets/img/icon1.png");
}
.icon2 {
background-image: url("../assets/img/icon2.png");
}
.icon3 {
background-image: url("../assets/img/icon3.png");
}
.icon4 {
background-image: url("../assets/img/icon4.png");
}
.item {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 7px;
}
.itemLevel {
width: 40px;
height: 40px;
border-radius: 20px;
font-family: Microsoft YaHei;
font-size: 12px;
font-weight: 400;
line-height: 14px;
padding: 6px 4px;
text-align: center;
margin-right: 5px;
}
.itemTime {
color: rgba(132, 136, 142, 1);
}
.itemFlag {
width: 20px;
height: 20px;
background-size: cover;
background-repeat: no-repeat;
margin-left: 10px;
}
.itemTrends {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 20px;
}
.itemTrendsIcon {
width: 4px;
height: 4px;
background-color: rgba(206, 79, 81, 1);
border-radius: 50%;
margin-right: 14px;
margin-left: 20px;
}
.itemTrendsText {
flex: 1;
}
.itemTrendsTime {
margin-right: 6px;
}
.level1 {
background: rgb(255, 241, 240);
color: rgb(245, 34, 45);
}
.level2 {
color: rgb(250, 140, 22);
background: rgb(255, 247, 230);
}
.level3 {
color: rgb(82, 196, 26);
background: rgb(246, 255, 237);
}
.itemText {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.cardContainer {
justify-content: space-between;
}
.itemCardWrap {
width: 400px;
display: flex;
flex-direction: row;
justify-content: center;
}
.itemCard {
width: 388px;
height: 80px;
border-radius: 4px;
background-image: url("../assets/img/cardBg.png");
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
.itemCardIcon {
width: 30px;
height: 30px;
background-size: contain;
margin-right: 7px;
}
.itemCardIcon1 {
background-image: url("../assets/img/cardIcon1.png");
}
.itemCardIcon2 {
background-image: url("../assets/img/cardIcon2.png");
}
.itemCardIcon3 {
background-image: url("../assets/img/cardIcon3.png");
}
.itemCardIcon4 {
background-image: url("../assets/img/cardIcon4.png");
}
.itemCardTitle {
font-size: 24px;
font-weight: 700;
color: #ffffff;
}
}
.moreWrap {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16px;
height: 100%;
padding-left: 10px;
padding-right: 10px;
flex: 1;
.moreText {
margin-right: 3px;
}
.shuaxinIcon {
width: 16px;
height: 16px;
background-image: url("../assets/img/shuaxin.png");
background-size: contain;
}
}
.CardCustomRight {
flex: 1;
padding-left: 50px;
padding-right: 50px;
margin-left: 30px;
display: flex;
justify-content: space-between;
}
.itemCard1 {
.itemCard1Img {
position: relative;
width: 204px;
height: 266px;
background-image: url("../assets/img/book.png");
background-size: contain;
.itemCard1Footer {
position: absolute;
left: 0;
bottom: 0;
width: 204px;
height: 64px;
padding: 10px;
background-color: #000;
color: #fff;
}
}
}
.spaceBetween {
justify-content: space-between;
}
.itemCard2 {
width: 388px;
height: 360px;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
:deep(.el-card__body) {
padding-top: 0;
}
.itemCard2Line {
/* 矩形 214 */
width: 320px;
height: 4px;
background-color: rgba(206, 79, 81, 1);
position: absolute;
top: 0;
left: 34px;
}
.itemCard2Container {
width: 320px;
height: 360px;
.itemCard2BigTextWrap {
color: rgba(206, 79, 81, 1);
font-size: 24px;
font-weight: 700;
height: 83px;
display: flex;
flex-direction: column;
justify-content: center;
border-bottom: 1px solid #ddd;
}
.itemCard2TextWrap {
height: 83px;
display: flex;
flex-direction: column;
justify-content: center;
border-bottom: 1px solid #ddd;
}
.temCard2Title {
color: rgba(59, 65, 75, 1);
font-size: 20px;
font-weight: 700;
}
.temCard2Text {
color: rgba(95, 101, 108, 1);
font-size: 16px;
font-weight: 400;
}
}
}
</style>
<template>
<div class="wrap">
<el-row>
<CardCustom
title="热门数据"
title-text-align="left"
title-color="rgba(10, 87, 166, 1)"
:style="{ width: '520px', height: '459px' }"
title-background-color="rgba(255, 255, 255, 1)"
header-height="53px"
>
<template #icon>
<div class="icon icon5"></div>
</template>
<template #right>
<div></div>
</template>
<div class="item" v-for="(item, index) in List" :key="index">
<span class="itemNumber" :style="{ color: getColor(index) }">
{{ index + 1 }}
</span>
<div class="itemText">{{ item.title }}</div>
<span class="itemClass">{{ item.class }}</span>
</div>
</CardCustom>
<CardCustom
title="数据分布"
title-text-align="left"
title-color="rgba(10, 87, 166, 1)"
:style="{ width: '1064px', height: '459px', marginLeft: '16px' }"
title-background-color="rgba(255, 255, 255, 1)"
header-height="53px"
>
<template #icon>
<div class="icon icon3"></div>
</template>
<template #right>
<div></div>
</template>
</CardCustom>
</el-row>
<div class="gap">
<el-row class="cardContainer">
<div class="itemCard">
<div class="itemCardTitle">科研学术</div>
<div class="itemCardNumber">2465</div>
</div>
</el-row>
</div>
</div>
</template>
<script setup>
import CardCustom from "../components/CardCustom.vue";
import { ref } from "vue";
function getColor(index) {
const mapColor = ["rgba(206, 79, 81, 1)", "rgba(255, 169, 64, 1)", "rgba(255, 197, 61, 1)"];
let color = mapColor[index];
return color || "transparent";
}
const List = ref([
{
title: "H.R.1-119th-大而美法案",
class: "科技法案"
},
{
title: "欧盟单方面宣布对中国电动汽车加征反补贴...",
class: "媒体报道"
},
{
title: "禁止在中国建设半导体产能",
class: "总统政令"
},
{
title: "2025年实体清单",
class: "实体清单"
},
{
title: "2025年实体清单",
class: "实体清单"
},
{
title: "2025年实体清单",
class: "实体清单"
},
{
title: "2025年实体清单",
class: "实体清单"
},
{
title: "2025年实体清单",
class: "实体清单"
},
{
title: "2025年实体清单",
class: "实体清单"
},
{
title: "2025年实体清单",
class: "实体清单"
}
]);
</script>
<style lang="scss" scoped>
.wrap {
width: 1600px;
margin: 30px auto;
}
.gap {
margin-top: 24px;
}
.icon {
width: 18px;
height: 18px;
background-size: contain;
background-repeat: no-repeat;
}
.icon3 {
background-image: url("../assets/img/icon3.png");
}
.icon5 {
background-image: url("../assets/img/icon5.png");
}
.item {
display: flex;
flex-direction: row;
align-items: center;
margin-top: 7px;
}
.itemNumber {
width: 40px;
}
.itemText {
flex: 1;
}
.itemClass {
color: rgba(132, 136, 142, 1);
}
.cardContainer {
justify-content: space-between;
}
.itemCard{
/* 容器 245 */
width: 186px;
height: 80px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 4px;
}
.itemCardTitle{
font-size: 20px;
font-weight: 700;
}
.itemCardNumber{
margin-top: 5px;
font-size: 16px;
}
</style>
import * as echarts from "echarts";
const getPieChart = (number, current, total) => {
const option = {
// 图表标题可置于中心,模拟居中文字的一部分
title: {
text: current + '/' + total, // 主百分比文字
left: 'center',
top: 'center',
textStyle: {
fontSize: 20,
fontWeight: 'bold',
color: '#333'
}
},
series: [
// 背景环系列
{
type: 'pie',
radius: ['84%', '96%'], // 细圆环:内半径50%,外半径55% [citation:5]
silent: true, // 禁用交互 [citation:2]
label: { show: false }, // 不显示标签 [citation:2]
data: [
{
value: 100, // 背景环占满100%,模拟完整圆环
itemStyle: {
color: '#f0f0f0' // 背景环颜色,通常为浅色
}
}
]
},
// 数据进度环系列
{
type: 'pie',
radius: ['80%', '100%'], // 与背景环同样粗细
startAngle: 90, // 起始角度,从顶部开始 [citation:4]
labelLine: false,
silent: true,
data: [
{
value: number, // 实际进度值,对应70%
itemStyle: {
// 使用线性渐变
color: {
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [{
offset: 0, color: 'rgba(105, 177, 255, 1)' // 渐变起始颜色
}, {
offset: 1, color: 'rgba(255, 120, 117, 1)' // 渐变结束颜色
}]
}
}
},
{
value: 100 - number, // 剩余部分 (100 - 70)%
itemStyle: {
color: 'transparent' // 剩余部分透明,仅显示实际进度部分
}
}
]
}
]
};
return option
}
const setChart = (option, chartDom) => {
let chart = echarts.init(chartDom);
chart.setOption(option);
return chart;
};
export {
getPieChart,
setChart
}
\ No newline at end of file
<template>
<div class="writting-wrapper">
<div class="writting-header">
<div class="tab-box">
<div class="tab" :class="{ tabActive: item.active }" v-for="(item, index) in tabList" :key="index">
{{ item.name }}
</div>
</div>
<div class="edit-box"></div>
<div class="btn-box">
<div class="btn" @click="exportContent">
<div class="icon">
<img src="./assets/images/export-icon.png" alt="" />
</div>
<div class="text">{{ "导出" }}</div>
</div>
<div class="btn" @click="handleSwitchMode">
<div class="icon">
<img src="./assets/images/preview-icon.png" alt="" />
</div>
<div class="text">{{ isEditMode ? "预览" : "编辑" }}</div>
</div>
<div class="btn btn1">
<div class="icon">
<img src="./assets/images/save-icon.png" alt="" />
</div>
<div class="text text1">{{ "保存" }}</div>
</div>
</div>
</div>
<div class="writting-main">
<div class="sider">
<div class="sider-box1">
<div class="header">报文主题</div>
<div class="title-box">
<div class="title">主题名称</div>
<el-input
style="width: 476px; height: 32px"
class="title-input"
placeholder="输入主题名称,如:大而美法案"
v-model="writtingTitle"
/>
</div>
<div class="description-box">
<div class="title">主题描述</div>
<el-input
class="description-input"
type="textarea"
style="width: 476px"
:rows="8"
placeholder="输入报文主题描述,如:从科技领域方面分析大而美法案通过后对中国可能产生的影响"
v-model="descText"
/>
</div>
</div>
<div class="sider-box2">
<div class="header">报文模板</div>
<div class="template-box">
<div
class="template"
:class="{ tempActive: tempActiveIndex === index }"
v-for="(temp, index) in tempList"
:key="index"
@click="handleClickTemp(item, index)"
>
<div class="header">
<div class="title">{{ temp.title }}</div>
<div class="icon">
<img src="./assets/images/template-icon.png" alt="" />
</div>
</div>
<div class="content">{{ temp.desc }}</div>
<div class="active-icon" v-if="tempActiveIndex === index">
<img src="./assets/images/active-icon.png" alt="" />
</div>
<div class="selected-icon" v-if="tempActiveIndex === index">
<img src="./assets/images/selected-icon.png" alt="" />
</div>
</div>
</div>
<div class="tips">
<div class="tips-icon">
<img src="./assets/images/tips-icon.png" alt="" />
</div>
<div class="tips-text">内容由AI生成,无法确保真实准确,仅供参考</div>
</div>
</div>
<div class="submit-btn" @click="getStreamChat">
<div class="submit-icon">
<img src="./assets/images/ai.png" alt="" />
</div>
<div class="submit-text">生成报文</div>
</div>
</div>
<div class="main-box">
<div v-if="isEditMode" class="edit-panel">
<v-md-editor
v-model="reportContent"
height="calc(100% - 40px)"
:disabled-menus="[]"
@upload-image="handleUploadImage"
@save="handleSave"
left-toolbar="undo redo clear | h bold italic strikethrough quote | ul ol table hr | link image code | save"
right-toolbar="preview toc sync-scroll fullscreen"
/>
</div>
<div v-else class="content-box" ref="scrollContainer" v-html="renderedContent"></div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import { useMarkdownStream } from "@/hooks/useMarkdownStream";
import { fetchEventSource } from "@microsoft/fetch-event-source";
import VMdEditor from "@kangc/v-md-editor";
import "@kangc/v-md-editor/lib/style/base-editor.css";
import vuepressTheme from "@kangc/v-md-editor/lib/theme/vuepress.js";
import "@kangc/v-md-editor/lib/theme/style/vuepress.css";
// 引入 Prism 相关依赖
import Prism from "prismjs";
VMdEditor.use(vuepressTheme, {
Prism
});
const isEditMode = ref(false);
const handleSwitchMode = () => {
isEditMode.value = !isEditMode.value;
if (!isEditMode.value) {
console.log(reportContent.value);
updateContent(reportContent.value, scrollContainer.value);
}
};
// 保存处理函数
const handleSave = (text, html) => {
console.log("保存内容:", {
markdown: text,
html: html
});
reportContent.value = text;
// 实际保存逻辑
// saveToLocalStorage(text);
ElMessage.success("保存成功!");
};
// 保存到本地存储
const saveToLocalStorage = text => {
localStorage.setItem("markdown-content", text);
};
const abortController = ref(null);
const scrollContainer = ref(null);
const { renderedContent, updateContent } = useMarkdownStream();
const reportContent = ref("");
const getStreamChat = async (search, inputValue) => {
const params = {
query: "输出一篇报文"
};
abortController.value = new AbortController();
fetchEventSource("/sse/api/v1/chat/stream", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params),
signal: abortController.value.signal,
openWhenHidden: true,
async onopen(res) {
console.log("流式回答开始", res);
},
async onmessage(res) {
let msgData = JSON.parse(res.data);
console.log("resss", msgData.content);
let str = msgData.content;
if (str !== "[DONE]") {
reportContent.value += str;
updateContent(reportContent.value, scrollContainer.value);
} else {
ElMessage.success("报文生成结束");
abortController.value.abort();
abortController.value = new AbortController();
}
},
onerror(error) {
ElMessage({
message: "写报生成报错!",
type: "warning"
});
abortController.value.abort();
abortController.value = new AbortController();
throw new Error(error);
}
}).catch(error => {
ElMessage({
message: "写报生成报错!",
type: "warning"
});
abortController.value.abort();
abortController.value = new AbortController();
throw new Error(error);
});
};
const writtingTitle = ref("");
const descText = ref("");
const tabList = ref([
{
name: "写报",
active: true
},
{
name: "收藏",
active: false
},
{
name: "问答",
active: false
}
]);
const tempList = ref([
{
title: "主题报",
desc: "基于特定主题生成各维度的综合分析报告"
},
{
title: "统计速报",
desc: "基于定期更新的数据源生成各关键指标统计"
}
]);
const tempActiveIndex = ref(0);
const handleClickTemp = (item, index) => {
tempActiveIndex.value = index;
};
// 导出
const exportContent = () => {
const blob = new Blob([reportContent.value], { type: "text/markdown" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `markdown-${new Date().getTime()}.md`;
a.click();
URL.revokeObjectURL(url);
};
onMounted(() => {
// const str = '# 欢迎使用 Markdown 编辑器\n\n这是一个功能丰富的 Markdown 编辑器示例。\n\n## 功能特性\n\n- ✨ **实时预览**\n- 🎨 **代码高亮**\n- 📁 **图片上传**\n- 📊 **表格支持**\n- 🔗 **链接管理**\n\n```javascript\n// 示例代码\nconst message = "Hello Markdown!";\nconsole.log(message);\n```'
// updateContent(str, scrollContainer.value);
});
onUnmounted(() => {
if (abortController.value) {
abortController.value.abort();
}
});
</script>
<style lang="scss" scoped>
.writting-wrapper {
width: 100%;
height: 100%;
.writting-header {
height: 60px;
box-sizing: border-box;
border-bottom: 1px solid rgba(234, 236, 238, 1);
border-top: 1px solid rgba(234, 236, 238, 1);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
display: flex;
position: relative;
.tab-box {
display: flex;
margin-left: 130px;
margin-top: 13px;
width: 260px;
height: 46px;
justify-content: space-between;
.tab {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
line-height: 30px;
}
.tabActive {
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 30px;
border-bottom: 4px solid rgba(5, 95, 194, 1);
}
}
.btn-box {
position: absolute;
top: 12px;
right: 39px;
display: flex;
gap: 12px;
.btn {
display: flex;
justify-content: center;
align-items: center;
width: 88px;
height: 36px;
gap: 8px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 6px;
background: rgba(255, 255, 255, 1);
cursor: pointer;
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
width: 32px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
.text1 {
color: #fff;
}
}
.btn1 {
background: rgba(5, 95, 194, 1);
}
}
}
.writting-main {
display: flex;
height: calc(100% - 60px);
.sider {
width: 520px;
box-sizing: border-box;
border-right: 1px solid rgba(234, 236, 238, 1);
border-top: 1px solid rgba(234, 236, 238, 1);
background: rgba(255, 255, 255, 1);
position: relative;
.sider-box1 {
margin-top: 21px;
margin-left: 22px;
.header {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
.title-box {
margin-top: 15px;
.title {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
.title-input {
margin-top: 15px;
}
}
.description-box {
margin-top: 24px;
.title {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
.description-input {
margin-top: 12px;
height: 200px;
}
}
}
.sider-box2 {
margin-top: 24px;
margin-left: 22px;
.header {
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
.template-box {
margin-top: 19px;
height: 120px;
display: flex;
gap: 16px;
.template {
width: 230px;
height: 120px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px;
position: relative;
cursor: pointer;
.active-icon {
width: 24px;
height: 24px;
position: absolute;
top: 0;
right: 0;
z-index: 99;
img {
width: 100%;
height: 100%;
}
}
.selected-icon {
width: 8px;
height: 6px;
position: absolute;
top: -4px;
right: 3px;
z-index: 100;
img {
width: 8px;
height: 6px;
}
}
.header {
display: flex;
justify-content: space-between;
height: 50px;
.title {
height: 24px;
// color: rgba(59, 65, 75, 1);
color: #333;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
margin-left: 15px;
margin-top: 16px;
}
.icon {
margin-top: 15px;
margin-right: 16px;
width: 30px;
height: 30px;
border-radius: 15px;
background: rgba(231, 243, 255, 1);
img {
width: 17px;
height: 14px;
margin-top: 8px;
margin-left: 7px;
}
}
}
.content {
margin: 0 auto;
width: 200px;
height: 48px;
margin-top: 10px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
.tempActive {
border: 1px solid rgba(5, 95, 194, 1);
background: rgba(246, 250, 255, 1);
}
}
.tips {
margin-top: 19px;
height: 22px;
display: flex;
.tips-icon {
width: 14px;
height: 16px;
margin-top: 3px;
img {
width: 100%;
height: 100%;
}
}
.tips-text {
margin-left: 8px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
}
}
.submit-btn {
position: absolute;
left: 22px;
bottom: 13px;
width: 476px;
height: 36px;
border-radius: 4px;
background: rgba(5, 95, 194, 1);
display: flex;
justify-content: center;
cursor: pointer;
&:hover {
background: rgba(5, 95, 194, 0.8);
}
.submit-icon {
/* AI-logo */
width: 21px;
height: 15px;
margin-top: 10px;
img {
width: 100%;
height: 100%;
}
}
.submit-text {
height: 24px;
margin-top: 5px;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
margin-left: 8px;
}
}
}
.main-box {
flex: 1;
background: #f7f8f9;
.edit-panel {
width: calc(100% - 100px);
height: calc(100% - 40px);
margin: 20px 50px;
}
.content-box {
width: calc(100% - 100px);
height: calc(100% - 40px);
margin: 20px 50px;
// height: 500px;
overflow-y: auto;
padding: 20px;
border: 1px solid #dcdfe6;
border-radius: 8px;
background: #fafafa;
line-height: 1.7;
// font-size: 20px;
font-size: 16px;
}
}
}
}
:deep(.el-input__wrapper) {
background: #f7f8f9;
}
:deep(.el-input__inner::placeholder) {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
:deep(.el-input__inner) {
color: #333;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
:deep(.el-textarea__inner) {
background: #f7f8f9;
}
:deep(.el-textarea__inner) {
color: #333;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
:deep(.el-textarea__inner::placeholder) {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
</style>
\ No newline at end of file
...@@ -38,6 +38,16 @@ export default defineConfig({ ...@@ -38,6 +38,16 @@ export default defineConfig({
target: 'http://8.140.26.4:9085/', target: 'http://8.140.26.4:9085/',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '') rewrite: (path) => path.replace(/^\/api/, '')
},
'/sse': {
target: 'http://192.168.26.70:8000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/sse/, '')
},
'/aichat': {
target: 'http://192.168.184.24:7861/',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/aichat/, '')
} }
} }
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论