提交 2278184b authored 作者: 张伊明's avatar 张伊明

Merge branch 'master' of http://8.140.26.4:10003/caijian/risk-monitor into zym-dev

......@@ -9,5 +9,6 @@
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
<script src="/js/config.js"></script>
</body>
</html>
\ No newline at end of file
const baseUrl = `http://8.140.26.4:9085/`
\ No newline at end of file
......@@ -4,6 +4,7 @@ import { ElMessage } from "element-plus";
const request200 = requestP => {
return requestP.then(data => {
if (data.code === 200) {
console.log('返回的数据结构 =>', data.data)
return data.data;
}
ElMessage({
......@@ -122,13 +123,14 @@ export function getSanctionsInfoCount() {
* sanReason: string
* }[]>}
*/
export function getSanctionProcess(typeName = "实体清单", pageNum = 1, pageSize = 10, isCn = false) {
export function getSanctionProcess(sanTypeIds = "1", pageNum = 1, pageSize = 10, isCn = false) {
return request200(
request({
method: "POST",
url: "/api/entitiesDataCount/getSanctionProcess",
data: {
typeName,
sanTypeIds,
// typeName: tabMap[sanTypeId],
pageNum,
pageSize,
isCn
......
import request from "@/api/request.js";
// 实体清单-制裁概况-获取实体清单基本信息
export function getEntityInfo(sanType) {
export function getEntityInfo(id) {
return request({
method: "GET",
url: `/api/sanctionList/baseInfo/${sanType}`
url: `/api/sanctionList/baseInfoById/${id}`
});
}
......@@ -98,10 +98,10 @@ export function get50PercentEntityCount(data) {
}
// 实体清单-数据统计-总量统计
export function getTotalCount() {
export function getTotalCount(id) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/total`
url: `/api/sanctionList/statistics/total?sanTypeId=${id}`
});
}
......@@ -113,7 +113,7 @@ export function getTotalCount() {
export function getSanctionCountChange(params) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/num`,
url: `/api/sanctionList/statistics/num`,
params
});
}
......@@ -128,7 +128,7 @@ export function getSanctionCountChange(params) {
export function getRegionCount(params) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/region`,
url: `/api/sanctionList/statistics/region`,
params
});
}
......@@ -143,7 +143,7 @@ export function getRegionCount(params) {
export function getTechDomainCount(params) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/domain`,
url: `/api/sanctionList/statistics/domain`,
params
});
}
......@@ -158,7 +158,7 @@ export function getTechDomainCount(params) {
export function getEntityTypeCount(params) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/entityType`,
url: `/api/sanctionList/statistics/entityType`,
params
});
}
......@@ -247,7 +247,7 @@ export function getSingleSanctionOverview(params) {
export function getSingleSanctionEntityCountry(params) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/countryRegion`,
url: `/api/sanctionList/statistics/countryRegion`,
params
});
}
......@@ -292,11 +292,10 @@ export function getSingleSanctionOverviewList(data) {
* @param {string} params.sanRecordId - 制裁记录ID
* @header token
*/
export function getSingleSanctionTotalCount(params) {
export function getSingleSanctionTotalCount(id) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/total`,
params
url: `/api/sanctionList/statistics/total?sanTypeId=${id}`,
});
}
......@@ -311,7 +310,7 @@ export function getSingleSanctionTotalCount(params) {
export function getSingleSanctionDomainCount(params) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/domain`,
url: `/api/sanctionList/statistics/domain`,
params
});
}
......@@ -327,7 +326,7 @@ export function getSingleSanctionDomainCount(params) {
export function getSingleSanctionEntityTypeCount(params) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/entityType`,
url: `/api/sanctionList/statistics/entityType`,
params
});
}
......@@ -341,7 +340,7 @@ export function getSingleSanctionEntityTypeCount(params) {
export function getSingleSanctionEntityCountryCount(params) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/countryRegion`,
url: `/api/sanctionList/statistics/countryRegion`,
params
});
}
......@@ -357,7 +356,7 @@ export function getSingleSanctionEntityCountryCount(params) {
export function getSingleSanctionEntityRegionCount(params) {
return request({
method: "GET",
url: `/api/sanctionList/statistics/el/region`,
url: `/api/sanctionList/statistics/region`,
params
});
}
......
......@@ -50,7 +50,7 @@ export const countryCoordMap = {
// 欧洲
俄罗斯: [37.6184, 55.7558], // 俄罗斯莫斯科
德国: [10.4515, 51.1657], // 德国柏林
英国: [-3.436, 55.3781], // 英国伦敦
英国: [-2, 54], // 英国伦敦
法国: [2.2137, 46.2276], // 法国巴黎
意大利: [12.5674, 41.8719], // 意大利罗马
西班牙: [-3.7492, 40.4637], // 西班牙马德里
......@@ -218,12 +218,12 @@ export function convertAsiaCenterCoord(coord) {
const [lng, lat] = coord;
// 将以本初子午线为基准的坐标转换为以亚洲为中心的坐标
// world-asia-center.json 是将标准坐标的经度减去了 180 度
let newLng = lng - 180;
// world-asia-center.json 是将标准坐标的经度加上了 180 度(地图向右平移)
let newLng = lng + 180;
// 规范化到 [-180, 180] 范围
if (newLng < -180) {
newLng += 360;
if (newLng > 180) {
newLng -= 360;
}
return [newLng, lat];
......
......@@ -135,8 +135,8 @@ const headerTitleClasses = computed(() => [
.header-icon {
width: 22px;
height: 18px;
margin-left: 5px;
margin-right: 14px;
margin-left: 0px;
margin-right: 10px;
}
.blue-title-block {
......@@ -155,6 +155,7 @@ const headerTitleClasses = computed(() => [
/* color: var(--base-color); */
color: $base-color;
line-height: 48px;
padding: 0 5px;
// padding: 0 12px;
}
......
......@@ -17,7 +17,7 @@ defineProps({
})
</script>
<style scoped>
<style lang="scss" scoped>
.action-button {
height: 28px;
padding: 0 8px;
......@@ -29,11 +29,16 @@ defineProps({
font-size: 16px;
font-weight: 400;
transition: all 0.3s;
}
.action-button[type="normal"] {
background-color: rgba(255, 255, 255, 1);
color: rgba(59, 65, 75, 1);
&:hover {
background: var(--color-primary-2);
}
}
.action-button[type="active"] {
......@@ -52,6 +57,4 @@ defineProps({
.action-button[type="active"]:hover {
background-color: #40a9ff;
} */
</style>
\ No newline at end of file
<svg viewBox="0 0 1019 61" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1019.000000" height="61.000000" fill="none" customFrame="#000000">
<defs>
<linearGradient id="paint_linear_1" x1="7.60449219" x2="10.1398888" y1="-1.90734863e-06" y2="61.0955963" gradientUnits="userSpaceOnUse">
<stop stop-color="rgb(231,243,255)" offset="0" stop-opacity="1" />
<stop stop-color="rgb(231,243,255)" offset="1" stop-opacity="0" />
</linearGradient>
</defs>
<path id="矩形 5734" d="M0.000322558 0L1019 0L1019 31.5006L0 61.0008L0.000322558 0Z" fill="url(#paint_linear_1)" fill-rule="evenodd" />
</svg>
<svg viewBox="0 0 15 12" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="15.000000" height="12.000000" fill="none" customFrame="url(#clipPath_0)">
<defs>
<clipPath id="clipPath_0">
<rect width="15.000000" height="12.000000" x="0.000000" y="0.000000" rx="6.000000" fill="rgb(255,255,255)" />
</clipPath>
<linearGradient id="paint_linear_0" x1="7.49999952" x2="7.49999952" y1="0" y2="10.5" gradientUnits="userSpaceOnUse">
<stop stop-color="rgb(5,95,194)" offset="0" stop-opacity="1" />
<stop stop-color="rgb(137,193,255)" offset="1" stop-opacity="1" />
</linearGradient>
</defs>
<rect id="AI-logo" width="15.000000" height="12.000000" x="0.000000" y="0.000000" rx="6.000000" />
<path id="合并" d="M12.2098 1.46629C12.9076 0.916637 13.2563 0 13.2563 0C13.2563 0 13.1693 0.916623 13.6052 1.46629C14.0411 2.01595 15 2.19866 15 2.19866C15 2.19866 13.9535 2.38224 13.2559 2.93288C12.5583 3.48351 12.2095 4.40121 12.2095 4.40121C12.2095 4.40121 12.2966 3.48353 11.8605 2.93288C11.4245 2.38222 10.4653 2.1986 10.4653 2.1986C10.4653 2.1986 11.5121 2.01594 12.2098 1.46629ZM8.176 2.20032L9.23888 10.5L6.83718 10.5L6.55783 8.24068L3.20908 8.24068L2.27565 10.5L0 10.5L3.08303 2.61208L2.68105 2.20032L8.176 2.20032ZM5.09297 3.60747L3.75415 6.83353L6.43179 6.83353L6.0298 3.60747L5.09297 3.60747ZM13.0741 10.4999L13.9839 4.57493L10.7578 4.57493L11.1632 5.13349L10.5361 10.4999L13.0741 10.4999Z" fill="url(#paint_linear_0)" fill-rule="evenodd" />
</svg>
<svg viewBox="0 0 6.70703 13.4102" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="6.707031" height="13.410156" fill="none" customFrame="#000000">
<rect id="容器 848" width="6.000000" height="11.997072" x="0.353516" y="0.707031" />
<path id="矢量 626" d="M0 0L2.99854 2.99854L6 0" stroke="rgb(5,95,194)" stroke-width="1.000000" transform="matrix(1,0,0,-1,0.353516,3.70508)" />
<path id="矢量 627" d="M0.353516 9.70508L3.35205 12.7036L6.35352 9.70508" stroke="rgb(5,95,194)" stroke-width="1.000000" />
</svg>
<template>
<div class="summary-wrapper">
<div class="summary-header">
<div class="icon1">
<img src="./icon1.svg" alt="">
</div>
<div class="text text-tip-1">{{ '智库报告总结摘要' }}</div>
<div class="icon2">
<img src="./icon2.svg" alt="">
</div>
</div>
<div class="summary-main">
<slot name="summary-content"></slot>
</div>
</div>
</template>
<style lang="scss">
.summary-wrapper {
width: 100%;
height: 100%;
// background: linear-gradient(90deg, var(--color-primary-10) 0%, var(--bg-white-100) 100%) ;
background: url('./bg.svg') no-repeat;
overflow: hidden;
border-radius: 4px;
border: 1px solid #E7F3FF;
.summary-header {
margin-top: 16px;
margin-left: 24px;
width: 199px;
height: 32px;
border: 1px solid var(--color-primary-100);
border-radius: 16px;
background: var(--color-primary-10);
display: flex;
justify-content: center;
align-items: center;
gap: 9px;
.icon1 {
width: 15px;
height: 12px;
img {
width: 100%;
height: 100%;
}
}
.text {
color: var(--color-primary-100);
}
.icon2 {
width: 6px;
height: 12px;
img {
width: 100%;
height: 100%;
}
}
}
.summary-main {
margin: 0 auto;
margin-top: 24px;
width: calc(100% - 52px);
height: calc(100% - 92px);
}
}
</style>
\ No newline at end of file
// 法案资源库
const CountryBill = () => import('@/views/dataLibrary/components/bill/countryBill/index.vue')
const StateBill = () => import('@/views/dataLibrary/components/bill/stateBill/index.vue')
const CountryBill = () => import('@/views/dataLibrary/bill/countryBill/index.vue')
const StateBill = () => import('@/views/dataLibrary/bill/stateBill/index.vue')
const dataBillRoutes = [
// 科技法案资源库路由
{
path: "/countryBill",
path: "/dataLibrary/countryBill",
name: "CountryBill",
component: CountryBill,
meta: {
......@@ -16,7 +16,7 @@ const dataBillRoutes = [
},
{
path: "/stateBill",
path: "/dataLibrary/stateBill",
name: "StateBill",
component: StateBill,
meta: {
......
// 法案资源库
const Decree = () => import('@/views/dataLibrary/components/decree/index.vue')
const Decree = () => import('@/views/dataLibrary/decree/index.vue')
const dataDecreeRoutes = [
// 科技法案资源库路由
{
path: "/dataDecree",
path: "/dataLibrary/dataDecree",
name: "DataDecree",
component: Decree,
meta: {
......
// 法案资源库
const CommerceControlList = () => import('@/views/dataLibrary/components/exportControl/commerceControlList/index.vue')
const CommerceControlListEvent = () => import('@/views/dataLibrary/components/exportControl/commerceControlListEvent/index.vue')
const EntityList = () => import('@/views/dataLibrary/components/exportControl/entityList/index.vue')
const EntityListEvent = () => import('@/views/dataLibrary/components/exportControl/entityListEvent/index.vue')
const CommerceControlList = () => import('@/views/dataLibrary/exportControl/commerceControlList/index.vue')
const CommerceControlListEvent = () => import('@/views/dataLibrary/exportControl/commerceControlListEvent/index.vue')
const EntityList = () => import('@/views/dataLibrary/exportControl/entityList/index.vue')
const EntityListEvent = () => import('@/views/dataLibrary/exportControl/entityListEvent/index.vue')
const dataDecreeRoutes = [
// 科技法案资源库路由
{
path: "/dataCommerceControlList",
path: "/dataLibrary/dataCommerceControlList",
name: "CommerceControlList",
component: CommerceControlList,
meta: {
......@@ -17,7 +17,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/dataCommerceControlListEvent",
path: "/dataLibrary/dataCommerceControlListEvent",
name: "CommerceControlListEvent",
component: CommerceControlListEvent,
meta: {
......@@ -27,7 +27,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/dataEntityList",
path: "/dataLibrary/dataEntityList",
name: "EntityList",
component: EntityList,
meta: {
......@@ -37,7 +37,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/dataEntityListEvent",
path: "/dataLibrary/dataEntityListEvent",
name: "EntityListEvent",
component: EntityListEvent,
meta: {
......
// 法案资源库
const MREList = () => import('@/views/dataLibrary/components/financeControl/mREList/index.vue')
const MREListEvent = () => import('@/views/dataLibrary/components/financeControl/mREListEvent/index.vue')
const SDNList = () => import('@/views/dataLibrary/components/financeControl/sDNList/index.vue')
const SDNListEvent = () => import('@/views/dataLibrary/components/financeControl/sDNListEvent/index.vue')
const MREList = () => import('@/views/dataLibrary/financeControl/mREList/index.vue')
const MREListEvent = () => import('@/views/dataLibrary/financeControl/mREListEvent/index.vue')
const SDNList = () => import('@/views/dataLibrary/financeControl/sDNList/index.vue')
const SDNListEvent = () => import('@/views/dataLibrary/financeControl/sDNListEvent/index.vue')
const dataDecreeRoutes = [
// 科技法案资源库路由
{
path: "/mREList",
path: "/dataLibrary/mREList",
name: "MREList",
component: MREList,
meta: {
......@@ -17,7 +17,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/mREListEvent",
path: "/dataLibrary/mREListEvent",
name: "MREListEvent",
component: MREListEvent,
meta: {
......@@ -27,7 +27,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/sDNList",
path: "/dataLibrary/sDNList",
name: "SDNList",
component: SDNList,
meta: {
......@@ -37,7 +37,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/sDNListEvent",
path: "/dataLibrary/sDNListEvent",
name: "SDNListEvent",
component: SDNListEvent,
meta: {
......
// 法案资源库
const KeyLab = () => import('@/views/dataLibrary/components/innovationSubject/keyLab/index.vue')
const ResearchUniversity = () => import('@/views/dataLibrary/components/innovationSubject/researchUniversity/index.vue')
const TechnologyCompany = () => import('@/views/dataLibrary/components/innovationSubject/technologyCompany/index.vue')
const KeyLab = () => import('@/views/dataLibrary/innovationSubject/keyLab/index.vue')
const ResearchUniversity = () => import('@/views/dataLibrary/innovationSubject/researchUniversity/index.vue')
const TechnologyCompany = () => import('@/views/dataLibrary/innovationSubject/technologyCompany/index.vue')
const dataDecreeRoutes = [
// 科技法案资源库路由
{
path: "/keyLab",
path: "/dataLibrary/keyLab",
name: "KeyLab",
component: KeyLab,
meta: {
......@@ -17,7 +17,7 @@ const dataDecreeRoutes = [
},
{
path: "/researchUniversity",
path: "/dataLibrary/researchUniversity",
name: "ResearchUniversity",
component: ResearchUniversity,
meta: {
......@@ -28,7 +28,7 @@ const dataDecreeRoutes = [
},
{
path: "/technologyCompany",
path: "/dataLibrary/technologyCompany",
name: "TechnologyCompany",
component: TechnologyCompany,
meta: {
......
// 法案资源库
const Case337 = () => import('@/views/dataLibrary/components/marketControl/case337/index.vue')
const Case232 = () => import('@/views/dataLibrary/components/marketControl/case232/index.vue')
const Case301 = () => import('@/views/dataLibrary/components/marketControl/case301/index.vue')
const Case337 = () => import('@/views/dataLibrary/marketControl/case337/index.vue')
const Case232 = () => import('@/views/dataLibrary/marketControl/case232/index.vue')
const Case301 = () => import('@/views/dataLibrary/marketControl/case301/index.vue')
const dataDecreeRoutes = [
// 科技法案资源库路由
{
path: "/case337",
path: "/dataLibrary/case337",
name: "Case337",
component: Case337,
meta: {
......@@ -16,7 +16,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/case232",
path: "/dataLibrary/case232",
name: "Case232",
component: Case232,
meta: {
......@@ -26,7 +26,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/case301",
path: "/dataLibrary/case301",
name: "Case301",
component: Case301,
meta: {
......
// 法案资源库
const CongressMan = () => import('@/views/dataLibrary/components/technologyFigures/congressMan/index.vue')
const Minister = () => import('@/views/dataLibrary/components/technologyFigures/minister/index.vue')
const TechnologyLeader = () => import('@/views/dataLibrary/components/technologyFigures/technologyLeader/index.vue')
const ThinkTankResearcher = () => import('@/views/dataLibrary/components/technologyFigures/thinkTankResearcher/index.vue')
const CongressMan = () => import('@/views/dataLibrary/technologyFigures/congressMan/index.vue')
const Minister = () => import('@/views/dataLibrary/technologyFigures/minister/index.vue')
const TechnologyLeader = () => import('@/views/dataLibrary/technologyFigures/technologyLeader/index.vue')
const ThinkTankResearcher = () => import('@/views/dataLibrary/technologyFigures/thinkTankResearcher/index.vue')
const dataDecreeRoutes = [
// 科技法案资源库路由
{
path: "/congressMan",
path: "/dataLibrary/congressMan",
name: "CongressMan",
component: CongressMan,
meta: {
......@@ -17,7 +17,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/minister",
path: "/dataLibrary/minister",
name: "Minister",
component: Minister,
meta: {
......@@ -27,7 +27,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/technologyLeader",
path: "/dataLibrary/technologyLeader",
name: "TechnologyLeader",
component: TechnologyLeader,
meta: {
......@@ -37,7 +37,7 @@ const dataDecreeRoutes = [
}
},
{
path: "/thinkTankResearcher",
path: "/dataLibrary/thinkTankResearcher",
name: "ThinkTankResearcher",
component: ThinkTankResearcher,
meta: {
......
// 法案资源库
const ThinkTank = () => import('@/views/dataLibrary/components/thinkTank/index.vue')
const ThinkTank = () => import('@/views/dataLibrary/thinkTank/index.vue')
const dataThinkTankRoutes = [
// 科技法案资源库路由
{
path: "/dataThinkTank",
path: "/dataLibrary/dataThinkTank",
name: "DataThinkTank",
component: ThinkTank,
meta: {
......
......@@ -5,31 +5,26 @@
{{
`
import AiButton from '@/components/base/AiButton/index.vue'
<AiButton />
import AiPane from '@/components/base/AiPane/index.vue'
<div class="chart-box">
<div class="btn-box" @mouseenter="handleSwitchAiContentShow(true)">
<AiButton />
</div>
<div class="content-box" v-if="isShowAiContent" @mouseleave="handleSwitchAiContentShow(false)">
<AiPane :aiContent="aiContent" />
</div>
</div>
`
}}
</pre>
<div class="chart-box">
<div class="btn-box">
<div class="btn-box" @mouseenter="handleSwitchAiContentShow(true)">
<AiButton />
</div>
</div>
</el-col>
<el-col :span="span">
<pre>
{{
`
import AiPane from '@/components/base/AiPane/index.vue'
<AiPane :aiContent="aiContent" />
`
}}
</pre>
<div class="chart-box">
<div class="content-box">
<div class="content-box" v-if="isShowAiContent" @mouseleave="handleSwitchAiContentShow(false)">
<AiPane :aiContent="aiContent" />
</div>
</div>
</el-col>
......@@ -43,7 +38,13 @@ import AiButton from '@/components/base/Ai/AiButton/index.vue'
import AiPane from '@/components/base/Ai/AiPane/index.vue'
const span = 12
const aiContent = ref(`整个立法过程反映了美国政治的高度极化特点。民主党全员反对该法案,批评其"劫贫济富"。而共和党内部也有分歧,特别是在财政赤字问题上。马斯克多次公开批评该法案是"疯狂的支出计划"。`)
const handleSwitchAiContentShow = (isShow) => {
isShowAiContent.value = isShow
}
const isShowAiContent = ref(false)
const aiContent = ref(`整个立法过程反映了美国政治的高度极化特点。民主党全员反对该法案,批评其"劫贫济富"。而共和党内部也有分歧,特别是在财政赤字问题上。马斯克多次公开批评该法案是"疯狂的支出计划"。整个立法过程反映了美国政治的高度极化特点。民主党全员反对该法案,批评其"劫贫济富"。而共和党内部也有分歧,特别是在财政赤字问题上。马斯克多次公开批评该法案是"疯狂的支出计划"。`)
</script>
......@@ -60,7 +61,8 @@ const aiContent = ref(`整个立法过程反映了美国政治的高度极化特
right: 0;
bottom: 18px;
}
.content-box{
.content-box {
position: absolute;
left: 0;
bottom: 0;
......
<template>
<el-row class="wrapper layout-grid-line">
<el-col :span="span">
<pre>
{{
`
import AiSummary from '@/components/base/Ai/AiSummary/index.vue'
<div class="summary-box">
<AiSummary />
</div>
`
}}
</pre>
<div class="summary-box">
<AiSummary>
<template #summary-content>
<div class="content-box">
我是插槽内容区域(忽略背景色)
</div>
</template>
</AiSummary>
</div>
</el-col>
</el-row>
</template>
<script setup>
import { ref } from 'vue'
import '@/styles/common.scss'
import AiSummary from '@/components/base/Ai/AiSummary/index.vue'
const span = 24
const aiContent = ref(`整个立法过程反映了美国政治的高度极化特点。民主党全员反对该法案,批评其"劫贫济富"。而共和党内部也有分歧,特别是在财政赤字问题上。马斯克多次公开批评该法案是"疯狂的支出计划"。整个立法过程反映了美国政治的高度极化特点。民主党全员反对该法案,批评其"劫贫济富"。而共和党内部也有分歧,特别是在财政赤字问题上。马斯克多次公开批评该法案是"疯狂的支出计划"。`)
</script>
<style lang="scss" scoped>
.summary-box {
margin-left: 10px;
margin-bottom: 10px;
width: 1019px;
height: 453px;
.content-box{
width: 100%;
height: 100%;
background: var(--color-primary-2);
}
}
</style>
\ No newline at end of file
......@@ -46,6 +46,9 @@
<el-tab-pane label="Ai智能总结" lazy>
<AiInfo />
</el-tab-pane>
<el-tab-pane label="Ai内容摘要" lazy>
<AiSummary />
</el-tab-pane>
<el-tab-pane label="层级关系图" lazy>
<GraphChart />
</el-tab-pane>
......@@ -87,6 +90,7 @@ import WordCloudChart from './WordCloudChart/index.vue'
import NewsPage from './News/index.vue'
import TimeTabPane from './TimeTabPane/index.vue'
import AiInfo from './Ai/AiInfo/index.vue'
import AiSummary from './Ai/AiSummary/index.vue'
</script>
<style lang="scss" scoped>
......
......@@ -626,6 +626,7 @@ function createChart() {
map: "world",
roam: true,
zoom: 1.2,
nameMap: nameMap,
label: {
show: false
},
......
<svg viewBox="0 0 158 28" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="158.000000" height="28.000000" fill="none" clip-path="url(#clipPath_7)" customFrame="url(#clipPath_7)">
<svg viewBox="0 0 158 28" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="158.000000" height="28.000000" fill="none" clip-path="url(#clipPath_0)" customFrame="url(#clipPath_0)">
<defs>
<clipPath id="clipPath_7">
<clipPath id="clipPath_0">
<rect width="158.000000" height="28.000000" x="0.000000" y="0.000000" rx="14.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_8">
<clipPath id="clipPath_1">
<rect width="79.000000" height="28.000000" x="0.000000" y="0.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_9">
<clipPath id="clipPath_2">
<rect width="53.000000" height="16.000000" x="13.000000" y="6.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_10">
<clipPath id="clipPath_3">
<rect width="16.000000" height="16.000000" x="13.000000" y="6.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_11">
<clipPath id="clipPath_4">
<rect width="79.000000" height="28.000000" x="79.000000" y="0.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_12">
<clipPath id="clipPath_5">
<rect width="53.000000" height="16.000000" x="92.000000" y="6.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_13">
<clipPath id="clipPath_6">
<rect width="16.000000" height="16.000000" x="92.000000" y="6.000000" fill="rgb(255,255,255)" />
</clipPath>
</defs>
<rect id="双相选择" width="157.000000" height="27.000000" x="0.500000" y="0.500000" rx="13.500000" stroke="rgb(5,95,194)" stroke-width="1.000000" />
<g id="容器 208" customFrame="url(#clipPath_8)">
<rect id="容器 208" width="79.000000" height="28.000000" x="0.000000" y="0.000000" fill="rgb(255,255,255)" />
<g id="容器 207" customFrame="url(#clipPath_9)">
<g id="容器 208" customFrame="url(#clipPath_1)">
<rect id="容器 208" width="79.000000" height="28.000000" x="0.000000" y="0.000000" fill="rgb(5,95,194)" />
<g id="容器 207" customFrame="url(#clipPath_2)">
<rect id="容器 207" width="53.000000" height="16.000000" x="13.000000" y="6.000000" />
<g id="icon_图表1 1" clip-path="url(#clipPath_10)" customFrame="url(#clipPath_10)">
<g id="icon_图表1 1" clip-path="url(#clipPath_3)" customFrame="url(#clipPath_3)">
<rect id="icon_图表1 1" width="16.000000" height="16.000000" x="13.000000" y="6.000000" />
<path id="矢量 461" d="M24.9004 11.5078C24.4904 11.5078 24.1504 11.8478 24.1504 12.2578L24.1504 20.2578C24.1504 20.6678 24.4904 21.0078 24.9004 21.0078C25.3104 21.0078 25.6504 20.6678 25.6504 20.2578L25.6504 12.2578C25.6504 11.8478 25.3104 11.5078 24.9004 11.5078ZM21.0004 8.50781C20.5904 8.50781 20.2504 8.84781 20.2504 9.25781L20.2504 20.2578C20.2504 20.6678 20.5904 21.0078 21.0004 21.0078C21.4104 21.0078 21.7504 20.6678 21.7504 20.2578L21.7504 9.25781C21.7504 8.84781 21.4104 8.50781 21.0004 8.50781L21.0004 8.50781ZM16.9004 13.5078C16.4904 13.5078 16.1504 13.8478 16.1504 14.2578L16.1504 20.2578C16.1504 20.6678 16.4904 21.0078 16.9004 21.0078C17.3104 21.0078 17.6504 20.6678 17.6504 20.2578L17.6504 14.2578C17.6504 13.8478 17.3104 13.5078 16.9004 13.5078Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
<path id="矢量 461" d="M24.8999 11.5078C24.4899 11.5078 24.1499 11.8478 24.1499 12.2578L24.1499 20.2578C24.1499 20.6678 24.4899 21.0078 24.8999 21.0078C25.3099 21.0078 25.6499 20.6678 25.6499 20.2578L25.6499 12.2578C25.6499 11.8478 25.3099 11.5078 24.8999 11.5078ZM20.9999 8.50781C20.5899 8.50781 20.2499 8.84781 20.2499 9.25781L20.2499 20.2578C20.2499 20.6678 20.5899 21.0078 20.9999 21.0078C21.4099 21.0078 21.7499 20.6678 21.7499 20.2578L21.7499 9.25781C21.7499 8.84781 21.4099 8.50781 20.9999 8.50781L20.9999 8.50781ZM16.8999 13.5078C16.4899 13.5078 16.1499 13.8478 16.1499 14.2578L16.1499 20.2578C16.1499 20.6678 16.4899 21.0078 16.8999 21.0078C17.3099 21.0078 17.6499 20.6678 17.6499 20.2578L17.6499 14.2578C17.6499 13.8478 17.3099 13.5078 16.8999 13.5078Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
</g>
<path id="" d="M38.4492 17.5508C40.625 17.8086 43.375 18.4492 44.8789 18.9922L45.4258 18.1133C43.8711 17.5859 41.1367 16.9766 38.9922 16.7344L38.4492 17.5508ZM40.0312 15.5352C41.2969 15.8086 42.9102 16.3516 43.793 16.7852L44.2891 15.9844C43.3906 15.5859 41.793 15.0703 40.5117 14.8164L40.0312 15.5352ZM40.1602 10.9102L44.2891 10.9102C43.7109 11.5195 42.9609 12.0781 42.0977 12.5742C41.2812 12.1133 40.5938 11.5859 40.0625 11.0078L40.1602 10.9102ZM45.2812 9.9375L45.0898 9.98438L40.9766 9.98438C41.2148 9.67969 41.4414 9.375 41.6172 9.05469L40.6406 8.73438C39.8398 10.0312 38.4805 11.2656 37.1211 12.0625C37.3594 12.2227 37.7617 12.5938 37.9375 12.7852C38.4336 12.4648 38.9102 12.0781 39.3906 11.6484C39.8867 12.1602 40.4805 12.6406 41.1211 13.0703C39.7617 13.6953 38.2383 14.1914 36.832 14.4492C37.0234 14.6875 37.2812 15.1523 37.3906 15.4258C38.9609 15.0703 40.625 14.4805 42.1289 13.6641C43.457 14.3828 44.9609 14.9297 46.4648 15.2461C46.6094 14.9766 46.9102 14.5586 47.1211 14.3516C45.7266 14.0977 44.3203 13.6641 43.1055 13.0898C44.2734 12.3203 45.2812 11.4062 45.9531 10.3516L45.2812 9.9375ZM36.543 19.5039L36.543 8.39844L47.4414 8.39844L47.4414 19.5039L36.543 19.5039ZM35.3906 7.3125L35.3906 21.2305L36.543 21.2305L36.543 20.5586L47.4414 20.5586L47.4414 21.2305L48.6094 21.2305L48.6094 7.3125L35.3906 7.3125ZM63.4883 14.4648C62.8008 15.1367 61.6797 16.0156 60.7188 16.6719C60.0156 15.8398 59.457 14.8945 59.0234 13.8398L64.8789 13.8398L64.8789 12.8164L58.5586 12.8164L58.5586 11.3906L63.6641 11.3906L63.6641 10.3984L58.5586 10.3984L58.5586 9.05469L64.3828 9.05469L64.3828 8.03125L58.5586 8.03125L58.5586 6.60938L57.375 6.60938L57.375 8.03125L51.7266 8.03125L51.7266 9.05469L57.375 9.05469L57.375 10.3984L52.543 10.3984L52.543 11.3906L57.375 11.3906L57.375 12.8164L51.1055 12.8164L51.1055 13.8398L56.3828 13.8398C54.8789 15.1836 52.625 16.4336 50.6406 17.0547C50.8945 17.2969 51.2461 17.7266 51.4062 18.0156C52.2891 17.6797 53.2461 17.2461 54.1602 16.7188L54.1602 19.0898C54.1602 19.7109 53.8086 20 53.5508 20.1289C53.7422 20.3984 53.9844 20.9102 54.0625 21.2148C54.4336 20.9609 55.0078 20.7695 59.4414 19.3438C59.375 19.1055 59.2812 18.6406 59.2461 18.3203L55.375 19.4883L55.375 15.9531C56.3203 15.3125 57.1836 14.5938 57.8711 13.8398C59.0898 17.1836 61.3281 19.5859 64.6094 20.6875C64.7852 20.3672 65.1367 19.9023 65.3906 19.6641C63.8086 19.1992 62.4805 18.4141 61.375 17.375C62.3828 16.7539 63.5508 15.9375 64.4648 15.1523L63.4883 14.4648Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
<path id="" d="M38.4492 17.5508C40.625 17.8086 43.375 18.4492 44.8789 18.9922L45.4258 18.1133C43.8711 17.5859 41.1367 16.9766 38.9922 16.7344L38.4492 17.5508ZM40.0312 15.5352C41.2969 15.8086 42.9102 16.3516 43.793 16.7852L44.2891 15.9844C43.3906 15.5859 41.793 15.0703 40.5117 14.8164L40.0312 15.5352ZM40.1602 10.9102L44.2891 10.9102C43.7109 11.5195 42.9609 12.0781 42.0977 12.5742C41.2812 12.1133 40.5938 11.5859 40.0625 11.0078L40.1602 10.9102ZM45.2812 9.9375L45.0898 9.98438L40.9766 9.98438C41.2148 9.67969 41.4414 9.375 41.6172 9.05469L40.6406 8.73438C39.8398 10.0312 38.4805 11.2656 37.1211 12.0625C37.3594 12.2227 37.7617 12.5938 37.9375 12.7852C38.4336 12.4648 38.9102 12.0781 39.3906 11.6484C39.8867 12.1602 40.4805 12.6406 41.1211 13.0703C39.7617 13.6953 38.2383 14.1914 36.832 14.4492C37.0234 14.6875 37.2812 15.1523 37.3906 15.4258C38.9609 15.0703 40.625 14.4805 42.1289 13.6641C43.457 14.3828 44.9609 14.9297 46.4648 15.2461C46.6094 14.9766 46.9102 14.5586 47.1211 14.3516C45.7266 14.0977 44.3203 13.6641 43.1055 13.0898C44.2734 12.3203 45.2812 11.4062 45.9531 10.3516L45.2812 9.9375ZM36.543 19.5039L36.543 8.39844L47.4414 8.39844L47.4414 19.5039L36.543 19.5039ZM35.3906 7.3125L35.3906 21.2305L36.543 21.2305L36.543 20.5586L47.4414 20.5586L47.4414 21.2305L48.6094 21.2305L48.6094 7.3125L35.3906 7.3125ZM63.4883 14.4648C62.8008 15.1367 61.6797 16.0156 60.7188 16.6719C60.0156 15.8398 59.457 14.8945 59.0234 13.8398L64.8789 13.8398L64.8789 12.8164L58.5586 12.8164L58.5586 11.3906L63.6641 11.3906L63.6641 10.3984L58.5586 10.3984L58.5586 9.05469L64.3828 9.05469L64.3828 8.03125L58.5586 8.03125L58.5586 6.60938L57.375 6.60938L57.375 8.03125L51.7266 8.03125L51.7266 9.05469L57.375 9.05469L57.375 10.3984L52.543 10.3984L52.543 11.3906L57.375 11.3906L57.375 12.8164L51.1055 12.8164L51.1055 13.8398L56.3828 13.8398C54.8789 15.1836 52.625 16.4336 50.6406 17.0547C50.8945 17.2969 51.2461 17.7266 51.4062 18.0156C52.2891 17.6797 53.2461 17.2461 54.1602 16.7188L54.1602 19.0898C54.1602 19.7109 53.8086 20 53.5508 20.1289C53.7422 20.3984 53.9844 20.9102 54.0625 21.2148C54.4336 20.9609 55.0078 20.7695 59.4414 19.3438C59.375 19.1055 59.2812 18.6406 59.2461 18.3203L55.375 19.4883L55.375 15.9531C56.3203 15.3125 57.1836 14.5938 57.8711 13.8398C59.0898 17.1836 61.3281 19.5859 64.6094 20.6875C64.7852 20.3672 65.1367 19.9023 65.3906 19.6641C63.8086 19.1992 62.4805 18.4141 61.375 17.375C62.3828 16.7539 63.5508 15.9375 64.4648 15.1523L63.4883 14.4648Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
</g>
</g>
<g id="容器 209" customFrame="url(#clipPath_11)">
<rect id="容器 209" width="79.000000" height="28.000000" x="79.000000" y="0.000000" fill="rgb(5,95,194)" />
<g id="容器 207" customFrame="url(#clipPath_12)">
<g id="容器 209" customFrame="url(#clipPath_4)">
<rect id="容器 209" width="79.000000" height="28.000000" x="79.000000" y="0.000000" fill="rgb(255,255,255)" />
<g id="容器 207" customFrame="url(#clipPath_5)">
<rect id="容器 207" width="53.000000" height="16.000000" x="92.000000" y="6.000000" />
<g id="表格(1) 1" clip-path="url(#clipPath_13)" customFrame="url(#clipPath_13)">
<g id="表格(1) 1" clip-path="url(#clipPath_6)" customFrame="url(#clipPath_6)">
<rect id="表格(1) 1" width="16.000000" height="16.000000" x="92.000000" y="6.000000" />
<path id="矢量 462" d="M105.1 9L94.9 9C94.8409 9 94.7824 9.006 94.7244 9.01801C94.6665 9.03002 94.6102 9.04781 94.5556 9.07136C94.501 9.09492 94.4491 9.1238 94.4 9.158C94.3509 9.1922 94.3054 9.23106 94.2636 9.27459C94.2218 9.31811 94.1845 9.36547 94.1517 9.41665C94.1188 9.46784 94.0911 9.52186 94.0685 9.57873C94.0459 9.63561 94.0288 9.69423 94.0173 9.7546C94.0058 9.81498 94 9.87594 94 9.9375L94 18.0625C94 18.1241 94.0058 18.185 94.0173 18.2454C94.0288 18.3058 94.0459 18.3644 94.0685 18.4213C94.0911 18.4781 94.1188 18.5322 94.1517 18.5833C94.1845 18.6345 94.2218 18.6819 94.2636 18.7254C94.3054 18.7689 94.3509 18.8078 94.4 18.842C94.4491 18.8762 94.501 18.9051 94.5556 18.9286C94.6102 18.9522 94.6665 18.97 94.7244 18.982C94.7824 18.994 94.8409 19 94.9 19L105.1 19C105.159 19 105.218 18.994 105.276 18.982C105.334 18.97 105.39 18.9522 105.444 18.9286C105.499 18.9051 105.551 18.8762 105.6 18.842C105.649 18.8078 105.695 18.7689 105.736 18.7254C105.778 18.6819 105.815 18.6345 105.848 18.5833C105.881 18.5322 105.909 18.4781 105.931 18.4213C105.954 18.3644 105.971 18.3058 105.983 18.2454C105.994 18.185 106 18.1241 106 18.0625L106 9.9375C106 9.87594 105.994 9.81498 105.983 9.7546C105.971 9.69423 105.954 9.6356 105.931 9.57873C105.909 9.52186 105.881 9.46784 105.848 9.41665C105.815 9.36547 105.778 9.31811 105.736 9.27459C105.695 9.23106 105.649 9.1922 105.6 9.158C105.551 9.1238 105.499 9.09492 105.444 9.07136C105.39 9.04781 105.334 9.03002 105.276 9.01801C105.218 9.006 105.159 9 105.1 9ZM94.9 11.0312L97.75 11.0312L97.75 12.75L94.9 12.75L94.9 11.0312ZM94.9 13.6875L97.75 13.6875L97.75 15.4062L94.9 15.4062L94.9 13.6875ZM101.35 16.3438L101.35 18.0625L98.65 18.0625L98.65 16.3438L101.35 16.3438ZM98.65 15.4062L98.65 13.6875L101.35 13.6875L101.35 15.4062L98.65 15.4062ZM101.35 12.75L98.65 12.75L98.65 11.0312L101.35 11.0312L101.35 12.75ZM102.25 13.6875L105.1 13.6875L105.1 15.4062L102.25 15.4062L102.25 13.6875ZM102.25 12.75L102.25 11.0312L105.1 11.0312L105.1 12.75L102.25 12.75ZM94.9 16.3438L97.75 16.3438L97.75 18.0625L94.9 18.0625L94.9 16.3438ZM102.25 18.0625L102.25 16.3438L105.1 16.3438L105.1 18.0625L102.25 18.0625Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
<path id="矢量 462" d="M105.1 9L94.9 9C94.8409 9 94.7824 9.006 94.7244 9.01801C94.6665 9.03002 94.6102 9.04781 94.5556 9.07136C94.501 9.09492 94.4491 9.1238 94.4 9.158C94.3509 9.1922 94.3054 9.23106 94.2636 9.27459C94.2218 9.31811 94.1845 9.36547 94.1517 9.41665C94.1188 9.46784 94.0911 9.52186 94.0685 9.57873C94.0459 9.63561 94.0288 9.69423 94.0173 9.7546C94.0058 9.81498 94 9.87594 94 9.9375L94 18.0625C94 18.1241 94.0058 18.185 94.0173 18.2454C94.0288 18.3058 94.0459 18.3644 94.0685 18.4213C94.0911 18.4781 94.1188 18.5322 94.1517 18.5833C94.1845 18.6345 94.2218 18.6819 94.2636 18.7254C94.3054 18.7689 94.3509 18.8078 94.4 18.842C94.4491 18.8762 94.501 18.9051 94.5556 18.9286C94.6102 18.9522 94.6665 18.97 94.7244 18.982C94.7824 18.994 94.8409 19 94.9 19L105.1 19C105.159 19 105.218 18.994 105.276 18.982C105.334 18.97 105.39 18.9522 105.444 18.9286C105.499 18.9051 105.551 18.8762 105.6 18.842C105.649 18.8078 105.695 18.7689 105.736 18.7254C105.778 18.6819 105.815 18.6345 105.848 18.5833C105.881 18.5322 105.909 18.4781 105.931 18.4213C105.954 18.3644 105.971 18.3058 105.983 18.2454C105.994 18.185 106 18.1241 106 18.0625L106 9.9375C106 9.87594 105.994 9.81498 105.983 9.7546C105.971 9.69423 105.954 9.6356 105.931 9.57873C105.909 9.52186 105.881 9.46784 105.848 9.41665C105.815 9.36547 105.778 9.31811 105.736 9.27459C105.695 9.23106 105.649 9.1922 105.6 9.158C105.551 9.1238 105.499 9.09492 105.444 9.07136C105.39 9.04781 105.334 9.03002 105.276 9.01801C105.218 9.006 105.159 9 105.1 9ZM94.9 11.0312L97.75 11.0312L97.75 12.75L94.9 12.75L94.9 11.0312ZM94.9 13.6875L97.75 13.6875L97.75 15.4062L94.9 15.4062L94.9 13.6875ZM101.35 16.3438L101.35 18.0625L98.65 18.0625L98.65 16.3438L101.35 16.3438ZM98.65 15.4062L98.65 13.6875L101.35 13.6875L101.35 15.4062L98.65 15.4062ZM101.35 12.75L98.65 12.75L98.65 11.0312L101.35 11.0312L101.35 12.75ZM102.25 13.6875L105.1 13.6875L105.1 15.4062L102.25 15.4062L102.25 13.6875ZM102.25 12.75L102.25 11.0312L105.1 11.0312L105.1 12.75L102.25 12.75ZM94.9 16.3438L97.75 16.3438L97.75 18.0625L94.9 18.0625L94.9 16.3438ZM102.25 18.0625L102.25 16.3438L105.1 16.3438L105.1 18.0625L102.25 18.0625Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
</g>
<path id="" d="M120.105 6.91016C119.832 7.55078 119.305 8.46484 118.902 9.03906L119.672 9.40625C120.121 8.87891 120.633 8.07812 121.098 7.35938L120.105 6.91016ZM116.359 9.07031C116.199 8.48047 115.77 7.63281 115.32 7.00781L114.457 7.35938C114.887 8.01562 115.305 8.89453 115.449 9.45703L116.359 9.07031ZM117.145 13.5508L118.246 13.5508L118.246 11.3594C119.016 11.9023 120.008 12.6875 120.391 13.0547L121.047 12.1914C120.68 11.9219 119.305 11.0234 118.504 10.5586L121.512 10.5586L121.512 9.56641L118.246 9.56641L118.246 6.60938L117.145 6.60938L117.145 9.56641L113.848 9.56641L113.848 10.5586L116.777 10.5586C115.992 11.6016 114.809 12.5742 113.688 13.0547C113.91 13.2812 114.199 13.6797 114.328 13.9531C115.305 13.4414 116.344 12.5586 117.145 11.6172L117.145 13.5508ZM119.574 15.8398C119.223 16.6719 118.711 17.375 118.09 17.9531C117.512 17.6641 116.871 17.3594 116.281 17.1055C116.504 16.7344 116.742 16.2891 116.984 15.8398L119.574 15.8398ZM120.359 19.2812C120.008 19.0234 119.527 18.7344 119.016 18.4492C119.863 17.5508 120.52 16.4336 120.938 15.0547L120.266 14.7852L120.09 14.832L117.48 14.832C117.609 14.543 117.703 14.2734 117.816 14L116.762 13.8086C116.648 14.1445 116.504 14.4805 116.344 14.832L114.184 14.832L114.184 15.8398L115.848 15.8398C115.512 16.4648 115.16 17.0547 114.824 17.5352C115.609 17.8242 116.473 18.2227 117.273 18.6406C116.23 19.375 115.016 19.8867 113.719 20.1758C113.93 20.3984 114.168 20.832 114.281 21.0898C115.734 20.7031 117.098 20.0781 118.23 19.168C118.777 19.4727 119.258 19.793 119.625 20.0625L120.359 19.2812ZM125.91 10.8008C125.672 12.6406 125.289 14.2383 124.711 15.5859C124.105 14.1602 123.656 12.5273 123.352 10.8008L125.91 10.8008ZM128.105 10.8008L128.105 9.69531L123.594 9.69531C123.816 8.80078 124.008 7.87109 124.137 6.92969L123.047 6.76953C122.648 9.53516 121.93 12.207 120.711 13.8867C120.969 14.0469 121.414 14.4141 121.609 14.6094C122.008 14 122.375 13.2969 122.695 12.5117C123.047 14.0977 123.496 15.5352 124.105 16.7852C123.207 18.3047 121.961 19.4727 120.23 20.3203C120.441 20.543 120.777 21.0234 120.887 21.2812C122.52 20.3984 123.734 19.2812 124.68 17.8867C125.465 19.2461 126.473 20.3359 127.703 21.0898C127.879 20.7852 128.215 20.3828 128.488 20.1602C127.16 19.457 126.121 18.2734 125.305 16.8164C126.152 15.168 126.68 13.1836 127.047 10.8008L128.105 10.8008ZM134.648 14.6562L134.488 13.5664L132.824 14.0977L132.824 10.9297L134.633 10.9297L134.633 9.82422L132.824 9.82422L132.824 6.625L131.719 6.625L131.719 9.82422L129.734 9.82422L129.734 10.9297L131.719 10.9297L131.719 14.4336C130.887 14.6719 130.137 14.8945 129.543 15.0703L129.832 16.207C130.406 16.0312 131.047 15.8398 131.719 15.6172L131.719 19.7266C131.719 19.9688 131.641 20.0312 131.449 20.0312C131.273 20.0312 130.633 20.0312 129.945 20.0156C130.105 20.3516 130.246 20.832 130.297 21.1211C131.305 21.1367 131.91 21.0898 132.281 20.8945C132.68 20.7031 132.824 20.3984 132.824 19.7422L132.824 15.2461L134.648 14.6562ZM136.473 13.1836C136.488 12.8008 136.488 12.4648 136.488 12.1133L136.488 11.4258L139.574 11.4258L139.574 13.1836L136.473 13.1836ZM142.582 8.35156L142.582 10.3828L136.488 10.3828L136.488 8.35156L142.582 8.35156ZM142.695 19.6016L137.785 19.6016L137.785 17.1836L142.695 17.1836L142.695 19.6016ZM144.266 14.207L144.266 13.1836L140.711 13.1836L140.711 11.4258L143.719 11.4258L143.719 7.3125L135.336 7.3125L135.336 12.1133C135.336 14.6406 135.191 18.1133 133.543 20.5586C133.816 20.6719 134.312 21.0078 134.504 21.2305C135.848 19.2656 136.281 16.5742 136.426 14.207L139.574 14.207L139.574 16.1758L136.742 16.1758L136.742 21.2461L137.785 21.2461L137.785 20.5938L142.695 20.5938L142.695 21.1836L143.785 21.1836L143.785 16.1758L140.711 16.1758L140.711 14.207L144.266 14.207Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
<path id="" d="M120.105 6.91016C119.832 7.55078 119.305 8.46484 118.902 9.03906L119.672 9.40625C120.121 8.87891 120.633 8.07812 121.098 7.35938L120.105 6.91016ZM116.359 9.07031C116.199 8.48047 115.77 7.63281 115.32 7.00781L114.457 7.35938C114.887 8.01562 115.305 8.89453 115.449 9.45703L116.359 9.07031ZM117.145 13.5508L118.246 13.5508L118.246 11.3594C119.016 11.9023 120.008 12.6875 120.391 13.0547L121.047 12.1914C120.68 11.9219 119.305 11.0234 118.504 10.5586L121.512 10.5586L121.512 9.56641L118.246 9.56641L118.246 6.60938L117.145 6.60938L117.145 9.56641L113.848 9.56641L113.848 10.5586L116.777 10.5586C115.992 11.6016 114.809 12.5742 113.688 13.0547C113.91 13.2812 114.199 13.6797 114.328 13.9531C115.305 13.4414 116.344 12.5586 117.145 11.6172L117.145 13.5508ZM119.574 15.8398C119.223 16.6719 118.711 17.375 118.09 17.9531C117.512 17.6641 116.871 17.3594 116.281 17.1055C116.504 16.7344 116.742 16.2891 116.984 15.8398L119.574 15.8398ZM120.359 19.2812C120.008 19.0234 119.527 18.7344 119.016 18.4492C119.863 17.5508 120.52 16.4336 120.938 15.0547L120.266 14.7852L120.09 14.832L117.48 14.832C117.609 14.543 117.703 14.2734 117.816 14L116.762 13.8086C116.648 14.1445 116.504 14.4805 116.344 14.832L114.184 14.832L114.184 15.8398L115.848 15.8398C115.512 16.4648 115.16 17.0547 114.824 17.5352C115.609 17.8242 116.473 18.2227 117.273 18.6406C116.23 19.375 115.016 19.8867 113.719 20.1758C113.93 20.3984 114.168 20.832 114.281 21.0898C115.734 20.7031 117.098 20.0781 118.23 19.168C118.777 19.4727 119.258 19.793 119.625 20.0625L120.359 19.2812ZM125.91 10.8008C125.672 12.6406 125.289 14.2383 124.711 15.5859C124.105 14.1602 123.656 12.5273 123.352 10.8008L125.91 10.8008ZM128.105 10.8008L128.105 9.69531L123.594 9.69531C123.816 8.80078 124.008 7.87109 124.137 6.92969L123.047 6.76953C122.648 9.53516 121.93 12.207 120.711 13.8867C120.969 14.0469 121.414 14.4141 121.609 14.6094C122.008 14 122.375 13.2969 122.695 12.5117C123.047 14.0977 123.496 15.5352 124.105 16.7852C123.207 18.3047 121.961 19.4727 120.23 20.3203C120.441 20.543 120.777 21.0234 120.887 21.2812C122.52 20.3984 123.734 19.2812 124.68 17.8867C125.465 19.2461 126.473 20.3359 127.703 21.0898C127.879 20.7852 128.215 20.3828 128.488 20.1602C127.16 19.457 126.121 18.2734 125.305 16.8164C126.152 15.168 126.68 13.1836 127.047 10.8008L128.105 10.8008ZM134.648 14.6562L134.488 13.5664L132.824 14.0977L132.824 10.9297L134.633 10.9297L134.633 9.82422L132.824 9.82422L132.824 6.625L131.719 6.625L131.719 9.82422L129.734 9.82422L129.734 10.9297L131.719 10.9297L131.719 14.4336C130.887 14.6719 130.137 14.8945 129.543 15.0703L129.832 16.207C130.406 16.0312 131.047 15.8398 131.719 15.6172L131.719 19.7266C131.719 19.9688 131.641 20.0312 131.449 20.0312C131.273 20.0312 130.633 20.0312 129.945 20.0156C130.105 20.3516 130.246 20.832 130.297 21.1211C131.305 21.1367 131.91 21.0898 132.281 20.8945C132.68 20.7031 132.824 20.3984 132.824 19.7422L132.824 15.2461L134.648 14.6562ZM136.473 13.1836C136.488 12.8008 136.488 12.4648 136.488 12.1133L136.488 11.4258L139.574 11.4258L139.574 13.1836L136.473 13.1836ZM142.582 8.35156L142.582 10.3828L136.488 10.3828L136.488 8.35156L142.582 8.35156ZM142.695 19.6016L137.785 19.6016L137.785 17.1836L142.695 17.1836L142.695 19.6016ZM144.266 14.207L144.266 13.1836L140.711 13.1836L140.711 11.4258L143.719 11.4258L143.719 7.3125L135.336 7.3125L135.336 12.1133C135.336 14.6406 135.191 18.1133 133.543 20.5586C133.816 20.6719 134.312 21.0078 134.504 21.2305C135.848 19.2656 136.281 16.5742 136.426 14.207L139.574 14.207L139.574 16.1758L136.742 16.1758L136.742 21.2461L137.785 21.2461L137.785 20.5938L142.695 20.5938L142.695 21.1836L143.785 21.1836L143.785 16.1758L140.711 16.1758L140.711 14.207L144.266 14.207Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
</g>
</g>
</svg>
<svg viewBox="0 0 158 28" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="158.000000" height="28.000000" fill="none" clip-path="url(#clipPath_0)" customFrame="url(#clipPath_0)">
<svg viewBox="0 0 158 28" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="158.000000" height="28.000000" fill="none" clip-path="url(#clipPath_7)" customFrame="url(#clipPath_7)">
<defs>
<clipPath id="clipPath_0">
<clipPath id="clipPath_7">
<rect width="158.000000" height="28.000000" x="0.000000" y="0.000000" rx="14.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_1">
<clipPath id="clipPath_8">
<rect width="79.000000" height="28.000000" x="0.000000" y="0.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_2">
<clipPath id="clipPath_9">
<rect width="53.000000" height="16.000000" x="13.000000" y="6.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_3">
<clipPath id="clipPath_10">
<rect width="16.000000" height="16.000000" x="13.000000" y="6.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_4">
<clipPath id="clipPath_11">
<rect width="79.000000" height="28.000000" x="79.000000" y="0.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_5">
<clipPath id="clipPath_12">
<rect width="53.000000" height="16.000000" x="92.000000" y="6.000000" fill="rgb(255,255,255)" />
</clipPath>
<clipPath id="clipPath_6">
<clipPath id="clipPath_13">
<rect width="16.000000" height="16.000000" x="92.000000" y="6.000000" fill="rgb(255,255,255)" />
</clipPath>
</defs>
<rect id="双相选择" width="157.000000" height="27.000000" x="0.500000" y="0.500000" rx="13.500000" stroke="rgb(5,95,194)" stroke-width="1.000000" />
<g id="容器 208" customFrame="url(#clipPath_1)">
<rect id="容器 208" width="79.000000" height="28.000000" x="0.000000" y="0.000000" fill="rgb(5,95,194)" />
<g id="容器 207" customFrame="url(#clipPath_2)">
<g id="容器 208" customFrame="url(#clipPath_8)">
<rect id="容器 208" width="79.000000" height="28.000000" x="0.000000" y="0.000000" fill="rgb(255,255,255)" />
<g id="容器 207" customFrame="url(#clipPath_9)">
<rect id="容器 207" width="53.000000" height="16.000000" x="13.000000" y="6.000000" />
<g id="icon_图表1 1" clip-path="url(#clipPath_3)" customFrame="url(#clipPath_3)">
<g id="icon_图表1 1" clip-path="url(#clipPath_10)" customFrame="url(#clipPath_10)">
<rect id="icon_图表1 1" width="16.000000" height="16.000000" x="13.000000" y="6.000000" />
<path id="矢量 461" d="M24.8999 11.5078C24.4899 11.5078 24.1499 11.8478 24.1499 12.2578L24.1499 20.2578C24.1499 20.6678 24.4899 21.0078 24.8999 21.0078C25.3099 21.0078 25.6499 20.6678 25.6499 20.2578L25.6499 12.2578C25.6499 11.8478 25.3099 11.5078 24.8999 11.5078ZM20.9999 8.50781C20.5899 8.50781 20.2499 8.84781 20.2499 9.25781L20.2499 20.2578C20.2499 20.6678 20.5899 21.0078 20.9999 21.0078C21.4099 21.0078 21.7499 20.6678 21.7499 20.2578L21.7499 9.25781C21.7499 8.84781 21.4099 8.50781 20.9999 8.50781L20.9999 8.50781ZM16.8999 13.5078C16.4899 13.5078 16.1499 13.8478 16.1499 14.2578L16.1499 20.2578C16.1499 20.6678 16.4899 21.0078 16.8999 21.0078C17.3099 21.0078 17.6499 20.6678 17.6499 20.2578L17.6499 14.2578C17.6499 13.8478 17.3099 13.5078 16.8999 13.5078Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
<path id="矢量 461" d="M24.9004 11.5078C24.4904 11.5078 24.1504 11.8478 24.1504 12.2578L24.1504 20.2578C24.1504 20.6678 24.4904 21.0078 24.9004 21.0078C25.3104 21.0078 25.6504 20.6678 25.6504 20.2578L25.6504 12.2578C25.6504 11.8478 25.3104 11.5078 24.9004 11.5078ZM21.0004 8.50781C20.5904 8.50781 20.2504 8.84781 20.2504 9.25781L20.2504 20.2578C20.2504 20.6678 20.5904 21.0078 21.0004 21.0078C21.4104 21.0078 21.7504 20.6678 21.7504 20.2578L21.7504 9.25781C21.7504 8.84781 21.4104 8.50781 21.0004 8.50781L21.0004 8.50781ZM16.9004 13.5078C16.4904 13.5078 16.1504 13.8478 16.1504 14.2578L16.1504 20.2578C16.1504 20.6678 16.4904 21.0078 16.9004 21.0078C17.3104 21.0078 17.6504 20.6678 17.6504 20.2578L17.6504 14.2578C17.6504 13.8478 17.3104 13.5078 16.9004 13.5078Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
</g>
<path id="" d="M38.4492 17.5508C40.625 17.8086 43.375 18.4492 44.8789 18.9922L45.4258 18.1133C43.8711 17.5859 41.1367 16.9766 38.9922 16.7344L38.4492 17.5508ZM40.0312 15.5352C41.2969 15.8086 42.9102 16.3516 43.793 16.7852L44.2891 15.9844C43.3906 15.5859 41.793 15.0703 40.5117 14.8164L40.0312 15.5352ZM40.1602 10.9102L44.2891 10.9102C43.7109 11.5195 42.9609 12.0781 42.0977 12.5742C41.2812 12.1133 40.5938 11.5859 40.0625 11.0078L40.1602 10.9102ZM45.2812 9.9375L45.0898 9.98438L40.9766 9.98438C41.2148 9.67969 41.4414 9.375 41.6172 9.05469L40.6406 8.73438C39.8398 10.0312 38.4805 11.2656 37.1211 12.0625C37.3594 12.2227 37.7617 12.5938 37.9375 12.7852C38.4336 12.4648 38.9102 12.0781 39.3906 11.6484C39.8867 12.1602 40.4805 12.6406 41.1211 13.0703C39.7617 13.6953 38.2383 14.1914 36.832 14.4492C37.0234 14.6875 37.2812 15.1523 37.3906 15.4258C38.9609 15.0703 40.625 14.4805 42.1289 13.6641C43.457 14.3828 44.9609 14.9297 46.4648 15.2461C46.6094 14.9766 46.9102 14.5586 47.1211 14.3516C45.7266 14.0977 44.3203 13.6641 43.1055 13.0898C44.2734 12.3203 45.2812 11.4062 45.9531 10.3516L45.2812 9.9375ZM36.543 19.5039L36.543 8.39844L47.4414 8.39844L47.4414 19.5039L36.543 19.5039ZM35.3906 7.3125L35.3906 21.2305L36.543 21.2305L36.543 20.5586L47.4414 20.5586L47.4414 21.2305L48.6094 21.2305L48.6094 7.3125L35.3906 7.3125ZM63.4883 14.4648C62.8008 15.1367 61.6797 16.0156 60.7188 16.6719C60.0156 15.8398 59.457 14.8945 59.0234 13.8398L64.8789 13.8398L64.8789 12.8164L58.5586 12.8164L58.5586 11.3906L63.6641 11.3906L63.6641 10.3984L58.5586 10.3984L58.5586 9.05469L64.3828 9.05469L64.3828 8.03125L58.5586 8.03125L58.5586 6.60938L57.375 6.60938L57.375 8.03125L51.7266 8.03125L51.7266 9.05469L57.375 9.05469L57.375 10.3984L52.543 10.3984L52.543 11.3906L57.375 11.3906L57.375 12.8164L51.1055 12.8164L51.1055 13.8398L56.3828 13.8398C54.8789 15.1836 52.625 16.4336 50.6406 17.0547C50.8945 17.2969 51.2461 17.7266 51.4062 18.0156C52.2891 17.6797 53.2461 17.2461 54.1602 16.7188L54.1602 19.0898C54.1602 19.7109 53.8086 20 53.5508 20.1289C53.7422 20.3984 53.9844 20.9102 54.0625 21.2148C54.4336 20.9609 55.0078 20.7695 59.4414 19.3438C59.375 19.1055 59.2812 18.6406 59.2461 18.3203L55.375 19.4883L55.375 15.9531C56.3203 15.3125 57.1836 14.5938 57.8711 13.8398C59.0898 17.1836 61.3281 19.5859 64.6094 20.6875C64.7852 20.3672 65.1367 19.9023 65.3906 19.6641C63.8086 19.1992 62.4805 18.4141 61.375 17.375C62.3828 16.7539 63.5508 15.9375 64.4648 15.1523L63.4883 14.4648Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
<path id="" d="M38.4492 17.5508C40.625 17.8086 43.375 18.4492 44.8789 18.9922L45.4258 18.1133C43.8711 17.5859 41.1367 16.9766 38.9922 16.7344L38.4492 17.5508ZM40.0312 15.5352C41.2969 15.8086 42.9102 16.3516 43.793 16.7852L44.2891 15.9844C43.3906 15.5859 41.793 15.0703 40.5117 14.8164L40.0312 15.5352ZM40.1602 10.9102L44.2891 10.9102C43.7109 11.5195 42.9609 12.0781 42.0977 12.5742C41.2812 12.1133 40.5938 11.5859 40.0625 11.0078L40.1602 10.9102ZM45.2812 9.9375L45.0898 9.98438L40.9766 9.98438C41.2148 9.67969 41.4414 9.375 41.6172 9.05469L40.6406 8.73438C39.8398 10.0312 38.4805 11.2656 37.1211 12.0625C37.3594 12.2227 37.7617 12.5938 37.9375 12.7852C38.4336 12.4648 38.9102 12.0781 39.3906 11.6484C39.8867 12.1602 40.4805 12.6406 41.1211 13.0703C39.7617 13.6953 38.2383 14.1914 36.832 14.4492C37.0234 14.6875 37.2812 15.1523 37.3906 15.4258C38.9609 15.0703 40.625 14.4805 42.1289 13.6641C43.457 14.3828 44.9609 14.9297 46.4648 15.2461C46.6094 14.9766 46.9102 14.5586 47.1211 14.3516C45.7266 14.0977 44.3203 13.6641 43.1055 13.0898C44.2734 12.3203 45.2812 11.4062 45.9531 10.3516L45.2812 9.9375ZM36.543 19.5039L36.543 8.39844L47.4414 8.39844L47.4414 19.5039L36.543 19.5039ZM35.3906 7.3125L35.3906 21.2305L36.543 21.2305L36.543 20.5586L47.4414 20.5586L47.4414 21.2305L48.6094 21.2305L48.6094 7.3125L35.3906 7.3125ZM63.4883 14.4648C62.8008 15.1367 61.6797 16.0156 60.7188 16.6719C60.0156 15.8398 59.457 14.8945 59.0234 13.8398L64.8789 13.8398L64.8789 12.8164L58.5586 12.8164L58.5586 11.3906L63.6641 11.3906L63.6641 10.3984L58.5586 10.3984L58.5586 9.05469L64.3828 9.05469L64.3828 8.03125L58.5586 8.03125L58.5586 6.60938L57.375 6.60938L57.375 8.03125L51.7266 8.03125L51.7266 9.05469L57.375 9.05469L57.375 10.3984L52.543 10.3984L52.543 11.3906L57.375 11.3906L57.375 12.8164L51.1055 12.8164L51.1055 13.8398L56.3828 13.8398C54.8789 15.1836 52.625 16.4336 50.6406 17.0547C50.8945 17.2969 51.2461 17.7266 51.4062 18.0156C52.2891 17.6797 53.2461 17.2461 54.1602 16.7188L54.1602 19.0898C54.1602 19.7109 53.8086 20 53.5508 20.1289C53.7422 20.3984 53.9844 20.9102 54.0625 21.2148C54.4336 20.9609 55.0078 20.7695 59.4414 19.3438C59.375 19.1055 59.2812 18.6406 59.2461 18.3203L55.375 19.4883L55.375 15.9531C56.3203 15.3125 57.1836 14.5938 57.8711 13.8398C59.0898 17.1836 61.3281 19.5859 64.6094 20.6875C64.7852 20.3672 65.1367 19.9023 65.3906 19.6641C63.8086 19.1992 62.4805 18.4141 61.375 17.375C62.3828 16.7539 63.5508 15.9375 64.4648 15.1523L63.4883 14.4648Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
</g>
</g>
<g id="容器 209" customFrame="url(#clipPath_4)">
<rect id="容器 209" width="79.000000" height="28.000000" x="79.000000" y="0.000000" fill="rgb(255,255,255)" />
<g id="容器 207" customFrame="url(#clipPath_5)">
<g id="容器 209" customFrame="url(#clipPath_11)">
<rect id="容器 209" width="79.000000" height="28.000000" x="79.000000" y="0.000000" fill="rgb(5,95,194)" />
<g id="容器 207" customFrame="url(#clipPath_12)">
<rect id="容器 207" width="53.000000" height="16.000000" x="92.000000" y="6.000000" />
<g id="表格(1) 1" clip-path="url(#clipPath_6)" customFrame="url(#clipPath_6)">
<g id="表格(1) 1" clip-path="url(#clipPath_13)" customFrame="url(#clipPath_13)">
<rect id="表格(1) 1" width="16.000000" height="16.000000" x="92.000000" y="6.000000" />
<path id="矢量 462" d="M105.1 9L94.9 9C94.8409 9 94.7824 9.006 94.7244 9.01801C94.6665 9.03002 94.6102 9.04781 94.5556 9.07136C94.501 9.09492 94.4491 9.1238 94.4 9.158C94.3509 9.1922 94.3054 9.23106 94.2636 9.27459C94.2218 9.31811 94.1845 9.36547 94.1517 9.41665C94.1188 9.46784 94.0911 9.52186 94.0685 9.57873C94.0459 9.63561 94.0288 9.69423 94.0173 9.7546C94.0058 9.81498 94 9.87594 94 9.9375L94 18.0625C94 18.1241 94.0058 18.185 94.0173 18.2454C94.0288 18.3058 94.0459 18.3644 94.0685 18.4213C94.0911 18.4781 94.1188 18.5322 94.1517 18.5833C94.1845 18.6345 94.2218 18.6819 94.2636 18.7254C94.3054 18.7689 94.3509 18.8078 94.4 18.842C94.4491 18.8762 94.501 18.9051 94.5556 18.9286C94.6102 18.9522 94.6665 18.97 94.7244 18.982C94.7824 18.994 94.8409 19 94.9 19L105.1 19C105.159 19 105.218 18.994 105.276 18.982C105.334 18.97 105.39 18.9522 105.444 18.9286C105.499 18.9051 105.551 18.8762 105.6 18.842C105.649 18.8078 105.695 18.7689 105.736 18.7254C105.778 18.6819 105.815 18.6345 105.848 18.5833C105.881 18.5322 105.909 18.4781 105.931 18.4213C105.954 18.3644 105.971 18.3058 105.983 18.2454C105.994 18.185 106 18.1241 106 18.0625L106 9.9375C106 9.87594 105.994 9.81498 105.983 9.7546C105.971 9.69423 105.954 9.6356 105.931 9.57873C105.909 9.52186 105.881 9.46784 105.848 9.41665C105.815 9.36547 105.778 9.31811 105.736 9.27459C105.695 9.23106 105.649 9.1922 105.6 9.158C105.551 9.1238 105.499 9.09492 105.444 9.07136C105.39 9.04781 105.334 9.03002 105.276 9.01801C105.218 9.006 105.159 9 105.1 9ZM94.9 11.0312L97.75 11.0312L97.75 12.75L94.9 12.75L94.9 11.0312ZM94.9 13.6875L97.75 13.6875L97.75 15.4062L94.9 15.4062L94.9 13.6875ZM101.35 16.3438L101.35 18.0625L98.65 18.0625L98.65 16.3438L101.35 16.3438ZM98.65 15.4062L98.65 13.6875L101.35 13.6875L101.35 15.4062L98.65 15.4062ZM101.35 12.75L98.65 12.75L98.65 11.0312L101.35 11.0312L101.35 12.75ZM102.25 13.6875L105.1 13.6875L105.1 15.4062L102.25 15.4062L102.25 13.6875ZM102.25 12.75L102.25 11.0312L105.1 11.0312L105.1 12.75L102.25 12.75ZM94.9 16.3438L97.75 16.3438L97.75 18.0625L94.9 18.0625L94.9 16.3438ZM102.25 18.0625L102.25 16.3438L105.1 16.3438L105.1 18.0625L102.25 18.0625Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
<path id="矢量 462" d="M105.1 9L94.9 9C94.8409 9 94.7824 9.006 94.7244 9.01801C94.6665 9.03002 94.6102 9.04781 94.5556 9.07136C94.501 9.09492 94.4491 9.1238 94.4 9.158C94.3509 9.1922 94.3054 9.23106 94.2636 9.27459C94.2218 9.31811 94.1845 9.36547 94.1517 9.41665C94.1188 9.46784 94.0911 9.52186 94.0685 9.57873C94.0459 9.63561 94.0288 9.69423 94.0173 9.7546C94.0058 9.81498 94 9.87594 94 9.9375L94 18.0625C94 18.1241 94.0058 18.185 94.0173 18.2454C94.0288 18.3058 94.0459 18.3644 94.0685 18.4213C94.0911 18.4781 94.1188 18.5322 94.1517 18.5833C94.1845 18.6345 94.2218 18.6819 94.2636 18.7254C94.3054 18.7689 94.3509 18.8078 94.4 18.842C94.4491 18.8762 94.501 18.9051 94.5556 18.9286C94.6102 18.9522 94.6665 18.97 94.7244 18.982C94.7824 18.994 94.8409 19 94.9 19L105.1 19C105.159 19 105.218 18.994 105.276 18.982C105.334 18.97 105.39 18.9522 105.444 18.9286C105.499 18.9051 105.551 18.8762 105.6 18.842C105.649 18.8078 105.695 18.7689 105.736 18.7254C105.778 18.6819 105.815 18.6345 105.848 18.5833C105.881 18.5322 105.909 18.4781 105.931 18.4213C105.954 18.3644 105.971 18.3058 105.983 18.2454C105.994 18.185 106 18.1241 106 18.0625L106 9.9375C106 9.87594 105.994 9.81498 105.983 9.7546C105.971 9.69423 105.954 9.6356 105.931 9.57873C105.909 9.52186 105.881 9.46784 105.848 9.41665C105.815 9.36547 105.778 9.31811 105.736 9.27459C105.695 9.23106 105.649 9.1922 105.6 9.158C105.551 9.1238 105.499 9.09492 105.444 9.07136C105.39 9.04781 105.334 9.03002 105.276 9.01801C105.218 9.006 105.159 9 105.1 9ZM94.9 11.0312L97.75 11.0312L97.75 12.75L94.9 12.75L94.9 11.0312ZM94.9 13.6875L97.75 13.6875L97.75 15.4062L94.9 15.4062L94.9 13.6875ZM101.35 16.3438L101.35 18.0625L98.65 18.0625L98.65 16.3438L101.35 16.3438ZM98.65 15.4062L98.65 13.6875L101.35 13.6875L101.35 15.4062L98.65 15.4062ZM101.35 12.75L98.65 12.75L98.65 11.0312L101.35 11.0312L101.35 12.75ZM102.25 13.6875L105.1 13.6875L105.1 15.4062L102.25 15.4062L102.25 13.6875ZM102.25 12.75L102.25 11.0312L105.1 11.0312L105.1 12.75L102.25 12.75ZM94.9 16.3438L97.75 16.3438L97.75 18.0625L94.9 18.0625L94.9 16.3438ZM102.25 18.0625L102.25 16.3438L105.1 16.3438L105.1 18.0625L102.25 18.0625Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
</g>
<path id="" d="M120.105 6.91016C119.832 7.55078 119.305 8.46484 118.902 9.03906L119.672 9.40625C120.121 8.87891 120.633 8.07812 121.098 7.35938L120.105 6.91016ZM116.359 9.07031C116.199 8.48047 115.77 7.63281 115.32 7.00781L114.457 7.35938C114.887 8.01562 115.305 8.89453 115.449 9.45703L116.359 9.07031ZM117.145 13.5508L118.246 13.5508L118.246 11.3594C119.016 11.9023 120.008 12.6875 120.391 13.0547L121.047 12.1914C120.68 11.9219 119.305 11.0234 118.504 10.5586L121.512 10.5586L121.512 9.56641L118.246 9.56641L118.246 6.60938L117.145 6.60938L117.145 9.56641L113.848 9.56641L113.848 10.5586L116.777 10.5586C115.992 11.6016 114.809 12.5742 113.688 13.0547C113.91 13.2812 114.199 13.6797 114.328 13.9531C115.305 13.4414 116.344 12.5586 117.145 11.6172L117.145 13.5508ZM119.574 15.8398C119.223 16.6719 118.711 17.375 118.09 17.9531C117.512 17.6641 116.871 17.3594 116.281 17.1055C116.504 16.7344 116.742 16.2891 116.984 15.8398L119.574 15.8398ZM120.359 19.2812C120.008 19.0234 119.527 18.7344 119.016 18.4492C119.863 17.5508 120.52 16.4336 120.938 15.0547L120.266 14.7852L120.09 14.832L117.48 14.832C117.609 14.543 117.703 14.2734 117.816 14L116.762 13.8086C116.648 14.1445 116.504 14.4805 116.344 14.832L114.184 14.832L114.184 15.8398L115.848 15.8398C115.512 16.4648 115.16 17.0547 114.824 17.5352C115.609 17.8242 116.473 18.2227 117.273 18.6406C116.23 19.375 115.016 19.8867 113.719 20.1758C113.93 20.3984 114.168 20.832 114.281 21.0898C115.734 20.7031 117.098 20.0781 118.23 19.168C118.777 19.4727 119.258 19.793 119.625 20.0625L120.359 19.2812ZM125.91 10.8008C125.672 12.6406 125.289 14.2383 124.711 15.5859C124.105 14.1602 123.656 12.5273 123.352 10.8008L125.91 10.8008ZM128.105 10.8008L128.105 9.69531L123.594 9.69531C123.816 8.80078 124.008 7.87109 124.137 6.92969L123.047 6.76953C122.648 9.53516 121.93 12.207 120.711 13.8867C120.969 14.0469 121.414 14.4141 121.609 14.6094C122.008 14 122.375 13.2969 122.695 12.5117C123.047 14.0977 123.496 15.5352 124.105 16.7852C123.207 18.3047 121.961 19.4727 120.23 20.3203C120.441 20.543 120.777 21.0234 120.887 21.2812C122.52 20.3984 123.734 19.2812 124.68 17.8867C125.465 19.2461 126.473 20.3359 127.703 21.0898C127.879 20.7852 128.215 20.3828 128.488 20.1602C127.16 19.457 126.121 18.2734 125.305 16.8164C126.152 15.168 126.68 13.1836 127.047 10.8008L128.105 10.8008ZM134.648 14.6562L134.488 13.5664L132.824 14.0977L132.824 10.9297L134.633 10.9297L134.633 9.82422L132.824 9.82422L132.824 6.625L131.719 6.625L131.719 9.82422L129.734 9.82422L129.734 10.9297L131.719 10.9297L131.719 14.4336C130.887 14.6719 130.137 14.8945 129.543 15.0703L129.832 16.207C130.406 16.0312 131.047 15.8398 131.719 15.6172L131.719 19.7266C131.719 19.9688 131.641 20.0312 131.449 20.0312C131.273 20.0312 130.633 20.0312 129.945 20.0156C130.105 20.3516 130.246 20.832 130.297 21.1211C131.305 21.1367 131.91 21.0898 132.281 20.8945C132.68 20.7031 132.824 20.3984 132.824 19.7422L132.824 15.2461L134.648 14.6562ZM136.473 13.1836C136.488 12.8008 136.488 12.4648 136.488 12.1133L136.488 11.4258L139.574 11.4258L139.574 13.1836L136.473 13.1836ZM142.582 8.35156L142.582 10.3828L136.488 10.3828L136.488 8.35156L142.582 8.35156ZM142.695 19.6016L137.785 19.6016L137.785 17.1836L142.695 17.1836L142.695 19.6016ZM144.266 14.207L144.266 13.1836L140.711 13.1836L140.711 11.4258L143.719 11.4258L143.719 7.3125L135.336 7.3125L135.336 12.1133C135.336 14.6406 135.191 18.1133 133.543 20.5586C133.816 20.6719 134.312 21.0078 134.504 21.2305C135.848 19.2656 136.281 16.5742 136.426 14.207L139.574 14.207L139.574 16.1758L136.742 16.1758L136.742 21.2461L137.785 21.2461L137.785 20.5938L142.695 20.5938L142.695 21.1836L143.785 21.1836L143.785 16.1758L140.711 16.1758L140.711 14.207L144.266 14.207Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
<path id="" d="M120.105 6.91016C119.832 7.55078 119.305 8.46484 118.902 9.03906L119.672 9.40625C120.121 8.87891 120.633 8.07812 121.098 7.35938L120.105 6.91016ZM116.359 9.07031C116.199 8.48047 115.77 7.63281 115.32 7.00781L114.457 7.35938C114.887 8.01562 115.305 8.89453 115.449 9.45703L116.359 9.07031ZM117.145 13.5508L118.246 13.5508L118.246 11.3594C119.016 11.9023 120.008 12.6875 120.391 13.0547L121.047 12.1914C120.68 11.9219 119.305 11.0234 118.504 10.5586L121.512 10.5586L121.512 9.56641L118.246 9.56641L118.246 6.60938L117.145 6.60938L117.145 9.56641L113.848 9.56641L113.848 10.5586L116.777 10.5586C115.992 11.6016 114.809 12.5742 113.688 13.0547C113.91 13.2812 114.199 13.6797 114.328 13.9531C115.305 13.4414 116.344 12.5586 117.145 11.6172L117.145 13.5508ZM119.574 15.8398C119.223 16.6719 118.711 17.375 118.09 17.9531C117.512 17.6641 116.871 17.3594 116.281 17.1055C116.504 16.7344 116.742 16.2891 116.984 15.8398L119.574 15.8398ZM120.359 19.2812C120.008 19.0234 119.527 18.7344 119.016 18.4492C119.863 17.5508 120.52 16.4336 120.938 15.0547L120.266 14.7852L120.09 14.832L117.48 14.832C117.609 14.543 117.703 14.2734 117.816 14L116.762 13.8086C116.648 14.1445 116.504 14.4805 116.344 14.832L114.184 14.832L114.184 15.8398L115.848 15.8398C115.512 16.4648 115.16 17.0547 114.824 17.5352C115.609 17.8242 116.473 18.2227 117.273 18.6406C116.23 19.375 115.016 19.8867 113.719 20.1758C113.93 20.3984 114.168 20.832 114.281 21.0898C115.734 20.7031 117.098 20.0781 118.23 19.168C118.777 19.4727 119.258 19.793 119.625 20.0625L120.359 19.2812ZM125.91 10.8008C125.672 12.6406 125.289 14.2383 124.711 15.5859C124.105 14.1602 123.656 12.5273 123.352 10.8008L125.91 10.8008ZM128.105 10.8008L128.105 9.69531L123.594 9.69531C123.816 8.80078 124.008 7.87109 124.137 6.92969L123.047 6.76953C122.648 9.53516 121.93 12.207 120.711 13.8867C120.969 14.0469 121.414 14.4141 121.609 14.6094C122.008 14 122.375 13.2969 122.695 12.5117C123.047 14.0977 123.496 15.5352 124.105 16.7852C123.207 18.3047 121.961 19.4727 120.23 20.3203C120.441 20.543 120.777 21.0234 120.887 21.2812C122.52 20.3984 123.734 19.2812 124.68 17.8867C125.465 19.2461 126.473 20.3359 127.703 21.0898C127.879 20.7852 128.215 20.3828 128.488 20.1602C127.16 19.457 126.121 18.2734 125.305 16.8164C126.152 15.168 126.68 13.1836 127.047 10.8008L128.105 10.8008ZM134.648 14.6562L134.488 13.5664L132.824 14.0977L132.824 10.9297L134.633 10.9297L134.633 9.82422L132.824 9.82422L132.824 6.625L131.719 6.625L131.719 9.82422L129.734 9.82422L129.734 10.9297L131.719 10.9297L131.719 14.4336C130.887 14.6719 130.137 14.8945 129.543 15.0703L129.832 16.207C130.406 16.0312 131.047 15.8398 131.719 15.6172L131.719 19.7266C131.719 19.9688 131.641 20.0312 131.449 20.0312C131.273 20.0312 130.633 20.0312 129.945 20.0156C130.105 20.3516 130.246 20.832 130.297 21.1211C131.305 21.1367 131.91 21.0898 132.281 20.8945C132.68 20.7031 132.824 20.3984 132.824 19.7422L132.824 15.2461L134.648 14.6562ZM136.473 13.1836C136.488 12.8008 136.488 12.4648 136.488 12.1133L136.488 11.4258L139.574 11.4258L139.574 13.1836L136.473 13.1836ZM142.582 8.35156L142.582 10.3828L136.488 10.3828L136.488 8.35156L142.582 8.35156ZM142.695 19.6016L137.785 19.6016L137.785 17.1836L142.695 17.1836L142.695 19.6016ZM144.266 14.207L144.266 13.1836L140.711 13.1836L140.711 11.4258L143.719 11.4258L143.719 7.3125L135.336 7.3125L135.336 12.1133C135.336 14.6406 135.191 18.1133 133.543 20.5586C133.816 20.6719 134.312 21.0078 134.504 21.2305C135.848 19.2656 136.281 16.5742 136.426 14.207L139.574 14.207L139.574 16.1758L136.742 16.1758L136.742 21.2461L137.785 21.2461L137.785 20.5938L142.695 20.5938L142.695 21.1836L143.785 21.1836L143.785 16.1758L140.711 16.1758L140.711 14.207L144.266 14.207Z" fill="rgb(255,255,255)" fill-rule="nonzero" />
</g>
</g>
</svg>
<svg viewBox="0 0 16 14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.000000" height="14.000000" fill="none">
<rect id="降序 1" width="16.000000" height="14.000000" x="0.000000" y="0.000000" />
<path id="矢量 469" d="M5.19867 14C5.1619 14 5.12548 13.9955 5.08942 13.9865C5.05336 13.9776 5.01834 13.9643 4.98437 13.9467C4.9504 13.9291 4.91813 13.9076 4.88755 13.882C4.85698 13.8565 4.82869 13.8275 4.80269 13.795C4.77669 13.7625 4.75348 13.7271 4.73305 13.6889C4.71262 13.6507 4.69537 13.6103 4.6813 13.5679C4.66723 13.5254 4.65661 13.4816 4.64943 13.4366C4.64226 13.3915 4.63867 13.346 4.63867 13.3L4.63867 0.7C4.63867 0.654037 4.64226 0.608516 4.64943 0.563437C4.65661 0.518357 4.66723 0.474586 4.6813 0.432122C4.69537 0.389658 4.71262 0.349317 4.73305 0.311101C4.75348 0.272884 4.77669 0.237526 4.80269 0.205025C4.82869 0.172525 4.85698 0.143507 4.88755 0.117971C4.91813 0.0924358 4.9504 0.0708735 4.98437 0.0532843C5.01834 0.0356952 5.05336 0.0224172 5.08942 0.0134503C5.12548 0.00448343 5.1619 0 5.19867 0C5.23544 0 5.27186 0.00448343 5.30792 0.0134503C5.34399 0.0224172 5.379 0.0356952 5.41297 0.0532843C5.44695 0.0708735 5.47922 0.0924358 5.50979 0.117971C5.54036 0.143507 5.56865 0.172525 5.59465 0.205025C5.62065 0.237526 5.64387 0.272884 5.66429 0.311101C5.68472 0.349317 5.70197 0.389658 5.71604 0.432122C5.73012 0.474586 5.74074 0.518357 5.74791 0.563437C5.75508 0.608516 5.75867 0.654037 5.75867 0.7L5.75867 13.3C5.75867 13.346 5.75508 13.3915 5.74791 13.4366C5.74074 13.4816 5.73012 13.5254 5.71604 13.5679C5.70197 13.6103 5.68472 13.6507 5.66429 13.6889C5.64387 13.7271 5.62065 13.7625 5.59465 13.795C5.56865 13.8275 5.54036 13.8565 5.50979 13.882C5.47922 13.9076 5.44695 13.9291 5.41297 13.9467C5.379 13.9643 5.34399 13.9776 5.30792 13.9865C5.27186 13.9955 5.23544 14 5.19867 14L5.19867 14ZM11.1963 10.297L8.39627 13.797C8.34144 13.8593 8.27984 13.9083 8.21147 13.944C8.1433 13.979 8.07237 13.9965 7.99867 13.9965C7.92498 13.9965 7.85404 13.979 7.78587 13.944C7.71745 13.9085 7.65705 13.858 7.60467 13.7925C7.55228 13.727 7.51188 13.6515 7.48347 13.566C7.4545 13.481 7.43957 13.3924 7.43867 13.3L7.43867 0.7C7.43867 0.654037 7.44226 0.608516 7.44943 0.563437C7.4566 0.518357 7.46723 0.474586 7.4813 0.432122C7.49537 0.389658 7.51262 0.349317 7.53305 0.311101C7.55348 0.272884 7.57669 0.237526 7.60269 0.205025C7.62869 0.172525 7.65698 0.143507 7.68755 0.117971C7.71813 0.0924358 7.7504 0.0708735 7.78437 0.0532843C7.81834 0.0356952 7.85336 0.0224172 7.88942 0.0134503C7.92548 0.00448343 7.9619 0 7.99867 0C8.03544 0 8.07186 0.00448343 8.10792 0.0134503C8.14399 0.0224172 8.179 0.0356952 8.21297 0.0532843C8.24694 0.0708735 8.27922 0.0924358 8.30979 0.117971C8.34036 0.143507 8.36865 0.172525 8.39465 0.205025C8.42065 0.237526 8.44387 0.272884 8.46429 0.311101C8.48472 0.349317 8.50197 0.389658 8.51604 0.432122C8.53012 0.474586 8.54074 0.518357 8.54791 0.563437C8.55509 0.608516 8.55867 0.654037 8.55867 0.7L8.55867 11.613L10.4011 9.303C10.4272 9.27036 10.4556 9.24123 10.4863 9.21559C10.517 9.18995 10.5494 9.1683 10.5835 9.15064C10.6176 9.13298 10.6528 9.11964 10.689 9.11064C10.7252 9.10164 10.7618 9.09713 10.7987 9.09713C10.8356 9.09713 10.8722 9.10164 10.9084 9.11064C10.9446 9.11964 10.9797 9.13298 11.0139 9.15064C11.048 9.1683 11.0804 9.18995 11.1111 9.21559C11.1418 9.24123 11.1702 9.27036 11.1963 9.303C11.2224 9.33563 11.2457 9.37114 11.2662 9.40951C11.2867 9.44788 11.304 9.48839 11.3182 9.53102C11.3323 9.57366 11.343 9.61761 11.3502 9.66288C11.3574 9.70814 11.361 9.75385 11.361 9.8C11.361 9.84615 11.3574 9.89186 11.3502 9.93712C11.343 9.98238 11.3323 10.0263 11.3182 10.069C11.304 10.1116 11.2867 10.1521 11.2662 10.1905C11.2457 10.2289 11.2224 10.2644 11.1963 10.297L11.1963 10.297Z" fill="rgb(95,101,108)" fill-rule="nonzero" />
</svg>
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.000000" height="16.000000" fill="none" customFrame="#000000">
<rect id="Line/Download" width="16.000000" height="16.000000" x="0.000000" y="0.000000" />
<path id="形状" d="M7.90156 10.3281C7.95156 10.3922 8.04844 10.3922 8.09844 10.3281L9.84844 8.11406C9.9125 8.03281 9.85469 7.9125 9.75 7.9125L8.59219 7.9125L8.59219 2.625C8.59219 2.55625 8.53594 2.5 8.46719 2.5L7.52969 2.5C7.46094 2.5 7.40469 2.55625 7.40469 2.625L7.40469 7.91094L6.25 7.91094C6.14531 7.91094 6.0875 8.03125 6.15156 8.1125L7.90156 10.3281ZM12.7812 9.78125L13.7188 9.78125C13.7875 9.78125 13.8438 9.8375 13.8438 9.90625L13.8438 13C13.8438 13.2766 13.6203 13.5 13.3438 13.5L2.65625 13.5C2.37969 13.5 2.15625 13.2766 2.15625 13L2.15625 9.90625C2.15625 9.8375 2.2125 9.78125 2.28125 9.78125L3.21875 9.78125C3.2875 9.78125 3.34375 9.8375 3.34375 9.90625L3.34375 12.3125L12.6562 12.3125L12.6562 9.90625C12.6562 9.8375 12.7125 9.78125 12.7812 9.78125Z" fill="rgb(95,101,108)" fill-rule="evenodd" />
</svg>
<template>
<div class="countrybill-wrapper">
<div class="header-box">
<div class="header-top">
<SelectBox :placeholder-name="areaPlaceHolder" select-title="科技领域" :select-list="areaList"
:select-name="selectedArea" @update:select-text="handleSelectArea" />
<SelectBox :placeholder-name="DatePlaceHolder" select-title="提出时间" :select-list="dateList"
:select-name="selectedDate" :custom-time="customTime" @update:select-text="handleSelectDate"
@update:custom-time="handleCustomDate" />
<SelectBox v-if="isFolderAll" :placeholder-name="areaPlaceHolder" select-title="科技领域" :select-list="areaList"
:select-name="selectedArea" @update:select-text="handleSelectArea" />
<SelectBox v-if="isFolderAll" :placeholder-name="areaPlaceHolder" select-title="科技领域" :select-list="areaList"
:select-name="selectedArea" @update:select-text="handleSelectArea" />
<SelectBox v-if="isFolderAll" :placeholder-name="areaPlaceHolder" select-title="科技领域" :select-list="areaList"
:select-name="selectedArea" @update:select-text="handleSelectArea" />
<SelectBox v-if="isFolderAll" :placeholder-name="areaPlaceHolder" select-title="科技领域" :select-list="areaList"
:select-name="selectedArea" @update:select-text="handleSelectArea" />
<SelectBox v-if="isFolderAll" :placeholder-name="areaPlaceHolder" select-title="科技领域" :select-list="areaList"
:select-name="selectedArea" @update:select-text="handleSelectArea" />
</div>
<div class="header-footer">
<div class="header-footer-left">
<ActiveTag v-for="tag, index in activeTagList" :key="index" :tagName="tag.name"
@close="handleCloseCurTag(tag, index)" />
</div>
<div class="header-footer-right">
<HeaderBtnBox :isShowAll="isFolderAll" @show-all="handleSwitchFolderAll" />
</div>
</div>
</div>
<div class="chart-main-box" v-if="isShowChart">
<div class="info-box">
<div class="switch-box" @click="handleSwitchChartData">
<img src="@/views/dataLibrary/assets/icons/chart-active.svg" alt="">
</div>
<div class="num-box text-title-3-bold">
{{ `共 ${totalNum} 条数据` }}
</div>
</div>
<div class="content-box">
<div class="content-header">
<ChartHeader :list="staticsDemensionList" @clickItem="handleClickDemensionItem">
<template #chart-header-right>
<el-select v-model="selectedTime" placeholder="选择时间" style="width: 150px"
v-show="curDemension === '提案时间'">
<el-option v-for="item in timeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
</ChartHeader>
</div>
<div class="content-main">
<ChartContainer
chartTitle="美国会法案提出数量随时间变化趋势"
:chartTypeList="curChartTypeList"
@clickChartItem="handleSwitchActiveChart">
<template #chart-box>
<LineChart v-if="activeChart === '折线图'" :lineChartData="lineChartData" />
<PieChart v-if="activeChart === '饼状图'" :pieChartData="pieChartData" />
<BarChart v-if="activeChart === '柱状图'" :barChartData="barChartData" />
<RaderChart v-if="activeChart === '雷达图'" :radarChartData="radarChartData" />
</template>
</ChartContainer>
</div>
</div>
</div>
<div class="data-main-box" v-else>
<div class="data-main-box-header">
<div class="switch-box" @click="handleSwitchChartData">
<img src="@/views/dataLibrary/assets/icons/data-active.svg" alt="">
</div>
<div class="num-box text-title-3-bold">
{{ `共 ${totalNum} 条数据` }}
</div>
</div>
<div class="data-main-box-main">
<div class="data-main-box-main-header">
<div class="header-left">
<div class="header-left-item1">
<el-checkbox v-model="isSelectedAll" label="全选" size="large" />
</div>
<div class="header-left-item2 text-tip-1">{{ `已选择${selectedNum}项` }}</div>
<div class="header-left-item2 text-tip-1 cancel">{{ '取消' }}</div>
</div>
<div class="header-right">
<div class="header-right-item item1">
<div class="icon">
<img src="../../assets/icons/download.svg" alt="">
</div>
<div class="text text-tip-1">{{ '导出' }}</div>
</div>
<div class="header-right-item2 item2">
<el-select v-model="curOperation" placeholder="批量操作" style="width: 120px">
<el-option v-for="item in operationList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</div>
<div class="header-right-item3 item3">
<el-select v-model="isSort" placeholder="发布时间" style="width: 166px" @change="handlePxChange">
<template #prefix>
<div style="display: flex; align-items: center; height: 100%">
<img src="../../assets/icons/desc-icon.svg" style="width: 14px; height: 14px" />
</div>
</template>
<el-option v-for="item in releaseTimeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
</div>
<div class="data-main-box-main-content">
<el-table :data="tableData" style="width: 100%" :row-style="{ height: '52px' }">
<el-table-column type="selection" width="55" />
<el-table-column label="Date" width="180" class-name="date-column">
<template #default="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column property="name" label="Name" width="180" />
<el-table-column property="address" label="use show-overflow-tooltip" width="360" show-overflow-tooltip />
<el-table-column property="address" label="address" />
</el-table>
</div>
</div>
<div class="data-main-box-footer">
<el-pagination background layout="prev, pager, next" :total="totalNum" v-model:current-page="currentPage"
:page-size="pageSize" @current-change="handleGetData" />
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import ChartContainer from '../../components/ChartContainer/index.vue'
import ChartHeader from '../../components/ChartHeader/index.vue'
import ActiveTag from '../../components/ActiveTag/index.vue'
import HeaderBtnBox from '../../components/HeaderBtnBox/index.vue'
import LineChart from '../../components/LineChart/index.vue'
import PieChart from '../../components/PieChart/index.vue'
import BarChart from '../../components/BarChart/index.vue'
import RaderChart from '../../components/RadarChart/idnex.vue'
import SelectBox from '../../components/SelectBox/index.vue'
// 图表/数据
const isShowChart = ref(true)
const handleSwitchChartData = () => {
isShowChart.value = !isShowChart.value
}
// 总计数据
const totalNum = ref(12)
// 统计维度列表
const staticsDemensionList = ref([
{
name: '提案时间',
active: true,
chartTypeList: ['折线图', '柱状图']
},
{
name: '科技领域',
active: false,
chartTypeList: ['饼状图']
},
{
name: '提出议院',
active: false,
chartTypeList: ['饼状图']
},
{
name: '提出委员会',
active: false,
chartTypeList: ['饼状图']
},
{
name: '提出议员党派',
active: false,
chartTypeList: ['饼状图']
},
{
name: '立法阶段',
active: false,
chartTypeList: ['饼状图']
},
])
const curChartTypeList = computed(() => {
let arr = staticsDemensionList.value.filter(item =>item.active)
return arr[0].chartTypeList
})
// 当前维度
const curDemension = ref('提案时间')
const handleClickDemensionItem = (val) => {
staticsDemensionList.value.forEach(item => {
item.active = false
})
val.active = true
curDemension.value = val.name
activeChart.value = val.chartTypeList[0]
}
const selectedTime = ref('按月统计')
const timeList = ref([
{
label: '按年统计',
value: '按年统计'
},
{
label: '按季统计',
value: '按季统计'
},
{
label: '按月统计',
value: '按月统计'
},
])
// 激活的标签列表
const activeTagList = ref([
{
name: '人工智能'
},
{
name: '共和党'
},
{
name: '2025-01-01 至 2025-12-31'
},
])
const handleCloseCurTag = (tag, index) => {
// alert(tag.name)
activeTagList.value.splice(index, 1)
}
const activeChart = ref('折线图')
const handleSwitchActiveChart = val => {
activeChart.value = val.name
}
const lineChartData = ref({
dataX: ['2025-08', '2025-09', '2025-10', '2025-11', '2025-12', '2026-01', '2026-02',],
dataY: [123, 51, 64, 72, 58, 69, 105]
})
const pieChartData = ref([
{
name: '核',
value: 24
},
{
name: '极地',
value: 24
},
{
name: '新材料',
value: 24
},
{
name: '深海',
value: 30
},
{
name: '海洋',
value: 31
},
{
name: '先进制造',
value: 31
},
{
name: '生物科技',
value: 32
},
{
name: '新能源',
value: 35
},
{
name: '集成电路',
value: 16
},
{
name: '新一代通信网络',
value: 55
},
{
name: '量子科技',
value: 33
},
{
name: '人工智能',
value: 55
}
])
const barChartData = ref({
dataX: ['2025-08', '2025-09', '2025-10', '2025-11', '2025-12', '2026-01', '2026-02',],
dataY: [123, 51, 64, 72, 58, 69, 105]
})
const radarChartData = ref({
title: [
{
name: '航空航天',
max: 10
},
{
name: '先进制造',
max: 10
},
{
name: '量子科技',
max: 10
},
{
name: '人工智能',
max: 10
},
{
name: '新材料',
max: 10
},
{
name: '集成电路',
max: 10
},
],
data: [
{
name: "337调查",
value: [10, 5, 2, 8, 5, 7
]
},
{
name: "232调查",
value: [2, 5, 3, 8, 10, 2]
},
{
name: "301调查",
value: [5, 8, 2, 9, 1, 5]
}
]
}
)
// 数据- 是否全选
const isSelectedAll = ref(false)
const selectedNum = ref(8) // 选择项数
const curOperation = ref('')
const operationList = ref([
{
name: 'aaa',
id: 'aaa'
},
{
name: 'bbb',
id: 'bbb'
},
{
name: 'ccc',
id: 'ccc'
},
])
const releaseTimeList = ref([
{
label: "按发布时间倒序",
value: true
},
{
label: "按发布时间升序",
value: false
}
]);
const isSort = ref(true); // true 倒序 false 升序
// const handleSwithSort = () => {
// isSort.value = !isSort.value;
// };
const handlePxChange = val => {
};
const currentPage = ref(1);
const pageSize = ref(10)
const handleGetData = () => {
}
// 领域
const areaPlaceHolder = ref('请选择领域')
const selectedArea = ref('人工智能')
const areaList = ref([
{
name: '人工智能',
id: '人工智能'
},
{
name: '集成电路',
id: '集成电路'
},
{
name: '先进制造',
id: '先进制造'
},
])
const handleSelectArea = (value) => {
selectedArea.value = value
}
// 提出时间
const DatePlaceHolder = ref('请选择时间')
const selectedDate = ref('时间1')
const dateList = ref([
{
name: '时间1',
id: '时间1'
},
{
name: '时间2',
id: '时间2'
},
{
name: '自定义',
id: '自定义'
},
])
const customTime = ref('') // 自定义时间
const handleCustomDate = value => {
console.log('value', value);
customTime.value = value
}
const handleSelectDate = (value) => {
selectedDate.value = value
}
// 展开全部 / 收起
const isFolderAll = ref(false)
const handleSwitchFolderAll = () => {
isFolderAll.value = !isFolderAll.value
}
// 表格数据
const tableData = [
{
date: '2016-05-04',
name: 'Aleyna Kutzner',
address: 'Lohrbergstr. 86c, Süd Lilli, Saarland',
},
{
date: '2016-05-03',
name: 'Helen Jacobi',
address: '760 A Street, South Frankfield, Illinois',
},
{
date: '2016-05-02',
name: 'Brandon Deckert',
address: 'Arnold-Ohletz-Str. 41a, Alt Malinascheid, Thüringen',
},
{
date: '2016-05-01',
name: 'Margie Smith',
address: '23618 Windsor Drive, West Ricardoview, Idaho',
},
{
date: '2016-05-01',
name: 'Margie Smith',
address: '23618 Windsor Drive, West Ricardoview, Idaho',
},
{
date: '2016-05-01',
name: 'Margie Smith',
address: '23618 Windsor Drive, West Ricardoview, Idaho',
},
{
date: '2016-05-01',
name: 'Margie Smith',
address: '23618 Windsor Drive, West Ricardoview, Idaho',
},
{
date: '2016-05-01',
name: 'Margie Smith',
address: '23618 Windsor Drive, West Ricardoview, Idaho',
},
{
date: '2016-05-01',
name: 'Margie Smith',
address: '23618 Windsor Drive, West Ricardoview, Idaho',
},
{
date: '2016-05-01',
name: 'Margie Smith',
address: '23618 Windsor Drive, West Ricardoview, Idaho',
}
]
</script>
<style lang="scss" scoped>
.countrybill-wrapper {
width: 1600px;
height: 968px;
overflow: hidden;
overflow-y: auto;
.headere-box {
width: 1568px;
height: 112px;
border-radius: 10px;
background: rgb(255, 255, 255);
border: 1px solid var(--bg-black-5);
margin: 16px auto;
}
.header-box {
width: 1568px;
min-height: 112px;
border-radius: 10px;
background: rgb(255, 255, 255);
border: 1px solid var(--bg-black-5);
margin: 16px auto;
box-sizing: border-box;
padding: 16px 24px;
.header-top {
min-height: 28px;
display: flex;
flex-wrap: wrap;
gap: 12px 42px;
// transition: all ease 1s;
}
.header-footer {
margin-top: 16px;
display: flex;
justify-content: space-between;
.header-footer-left {
display: flex;
justify-content: space-between;
gap: 8px;
}
}
}
.chart-main-box {
.info-box {
margin: 0 auto;
width: 1568px;
height: 30px;
display: flex;
justify-content: space-between;
.switch-box {
width: 160px;
border-radius: 20px;
border: 1px solid var(--color-primary-100);
height: 30px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.num-box {
color: var(--color-red-100);
}
}
.content-box {
margin: 0 auto;
margin-top: 16px;
width: 1568px;
height: 766px;
border-radius: 10px;
background: rgba(255, 255, 255);
border: 1px solid var(--bg-black-5);
.content-header {
margin: 16px 24px;
width: 1520px;
height: 28px;
}
.content-main {
width: 1520px;
margin: 0 auto;
}
}
}
.data-main-box {
width: 1568px;
height: 810px;
border-radius: 10px;
background: var(--bg-white-100);
margin: 0 auto;
overflow: hidden;
.data-main-box-header {
margin: 16px auto;
width: 1520px;
height: 30px;
display: flex;
justify-content: space-between;
.switch-box {
width: 160px;
border-radius: 20px;
border: 1px solid var(--color-primary-100);
height: 30px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.num-box {
box-sizing: border-box;
padding: 2px 0;
color: var(--color-red-100);
}
}
.data-main-box-main {
width: 1520px;
// height: 633px;
height: 680px;
border-radius: 10px;
border: 1px solid var(--bg-black-5);
margin: 0 auto;
.data-main-box-main-header {
height: 48px;
background: var(--bg-black-2);
display: flex;
justify-content: space-between;
.header-left {
margin-left: 16px;
height: 48px;
display: flex;
gap: 16px;
align-items: center;
.header-left-item2 {
color: var(--color-primary-100);
}
.cancel {
cursor: pointer;
}
}
.header-right {
margin-right: 16px;
display: flex;
gap: 8px;
align-items: center;
.header-right-item {
height: 30px;
padding: 5px 16px;
border: 1px solid var(--bg-black-10);
border-radius: 4px;
background: var(--bg-white-100);
cursor: pointer;
}
.item1 {
display: flex;
gap: 2px;
justify-content: center;
align-items: center;
&:hover {
background: var(--color-primary-2);
}
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
color: var(--text-primary-65-color);
}
}
.item2 {}
.item3 {}
}
}
.data-main-box-main-content {}
}
.data-main-box-footer {
margin: 16px auto 0;
height: 40px;
width: 1520px;
display: flex;
align-items: center;
justify-content: flex-end;
}
}
}
.date-column {
background-color: #ecf5ff;
}
.date-column .cell {
color: #409eff !important;
font-weight: 500;
}
</style>
\ No newline at end of file
<svg viewBox="0 0 12.7275 12.7266" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12.727539" height="12.726562" fill="none" customFrame="#000000">
<path id="合并" d="M5 4L5 0L4 0L4 4L0 4L0 5L4 5L4 9L5 9L5 5L9 5L9 4L5 4Z" fill="rgb(5,95,194)" fill-rule="evenodd" transform="matrix(0.707107,-0.707107,0.707107,0.707107,0,6.36328)" />
</svg>
<template>
<div class="wrapper">
<div class="text text-tip-1">{{ tagName }}</div>
<div class="icon" @click="handleClose">
<img src="./close.svg" alt="">
</div>
</div>
</template>
<script setup>
const props = defineProps({
tagName: {
type: String,
default: ''
}
})
const emit = defineEmits(['close'])
const handleClose = () => {
emit('close')
}
</script>
<style lang="scss" scoped>
.wrapper{
height: 30px;
box-sizing: border-box;
display: flex;
padding: 3px 4px 3px 8px;
align-items: center;
justify-content: flex-start;
gap: 4px;
border-radius: 4px;
border: 1px solid var(--color-primary-35);
background: var(--color-primary-2);
cursor: pointer;
.text{
color: var(--color-primary-100);
}
.icon{
width: 15px;
height: 15px;
img{
width: 100%;
height: 100%;
}
}
}
</style>
\ No newline at end of file
import * as echarts from "echarts";
const getBarChart = (data) => {
const option = {
tooltip: {},
grid: {
top: 48,
right: 34,
bottom: 10,
left: 24,
containLabel: true
},
yAxis: {
type: 'value',
splitLine: {
show: true,
lineStyle: {
color: ['#DEE2E7'], // 线条颜色,可以是数组,用于不同间隔交替颜色
width: 1, // 线宽
type: 'dashed', // 类型:'solid'(实线), 'dashed'(虚线), 'dotted'(点线)
// opacity: 0.6 // 透明度
}
},
axisLine: {
show: false,
lineStyle: {
color: 'rgba(95, 101, 108, 1)',
}
},
show: true,
textStyle: {
color: 'rgba(95, 101, 108, 1)',
fontFamily: 'Microsoft YaHei',
fontsize: 14,
}
},
xAxis: {
type: 'category',
data: data.dataX,
splitLine: {
show: false
},
axisTick: {
show: true
},
axisLine: {
show: true,
lineStyle: {
color: '#e7f3ff',
}
},
axisLabel: {
show: true,
textStyle: {
color: 'rgba(95, 101, 108, 1)',
fontFamily: 'Microsoft YaHei',
fontsize: 14,
}
}
},
series: [{
type: 'bar',
data: data.dataY,
label: {
show: true,
position: 'top',
color: 'rgb(59, 65, 75)',
fontWeight: 'regular', // 文字加粗
fontSize: 16,
fontFamily: 'Source Han Sans CN',
formatter: function (params) {
return params.value
},
},
barWidth: 20,
itemStyle: {
color: function (params) {
return new echarts.graphic.LinearGradient(0, 1, 0, 0,
[{
offset: 0,
color: 'rgba(10, 87, 166, 0)'
},
{
offset: 1,
color: 'rgba(5, 95, 194, 1)'
}
]);
},
// barBorderRadius: 10,
}
}]
}
return option
}
export default getBarChart
\ No newline at end of file
<template>
<div class="bar-chart-wrapper" id="bar-chart"></div>
</template>
<script setup>
import { ref, onMounted, nextTick } from 'vue'
import setChart from '@/utils/setChart';
import getBarChart from './barchart';
const props = defineProps({
barChartData: {
type: Array,
default: [
]
}
})
onMounted(() => {
const barChart = getBarChart(props.barChartData)
setChart(barChart, 'bar-chart', )
})
</script>
<style lang="scss">
.bar-chart-wrapper {
width: 100%;
height: 100%;
}
</style>
\ No newline at end of file
......@@ -2,7 +2,7 @@
<div class="chart-wrapper">
<div class="header">
<div class="header-left">
<div class="chart-item" v-for="item, index in chartItemList" :key="index">
<div class="chart-item" v-for="item, index in chartItemList" :key="index" @click="handleClickChartItem(item)">
<img v-if="!item.active" :src="item.icon" alt="">
<img v-else :src="item.activeIcon" alt="">
</div>
......@@ -13,14 +13,18 @@
</div>
</div>
<div class="main">
<div class="chart-box" id="chart-box"></div>
<div class="tip-box"></div>
<div class="chart-box">
<slot name="chart-box"></slot>
</div>
<div class="tip-box">
<TipTab />
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed, onMounted, nextTick } from 'vue'
import Line from './assets/icons/line.svg'
import LineActive from './assets/icons/line-active.svg'
import Bar from './assets/icons/bar.svg'
......@@ -29,10 +33,12 @@ import Pie from './assets/icons/pie.svg'
import PieActive from './assets/icons/pie-active.svg'
import Radar from './assets/icons/radar.svg'
import RadarActive from './assets/icons/radar-active.svg'
const chartItemList = ref([
import TipTab from '@/components/base/TipTab/index.vue'
const defaultChartTypeList = [
{
name: '折线图',
active: true,
active: false,
icon: Line,
activeIcon: LineActive
},
......@@ -54,15 +60,56 @@ const chartItemList = ref([
icon: Radar,
activeIcon: RadarActive
},
])
]
const emit = defineEmits('clickChartItem')
const handleClickChartItem = (item) => {
chartItemList.value.forEach(chart => {
chart.active = false
})
item.active = true
emit('clickChartItem', item)
}
const props = defineProps({
chartTitle: {
type: String,
default: ''
},
chartTypeList : {
type: Array,
default: []
}
})
const chartItemList = computed(() => {
let arr = []
props.chartTypeList.forEach(item => {
defaultChartTypeList.forEach(val => {
if(val.name === item) {
arr.push(val)
}
})
})
arr.forEach(item => {
item.active = false
})
arr[0].active = true
return arr
})
// nextTick(() => {
// let arr = chartItemList.value.filter(item => item.active)
// if(!arr.length) {
// alert(1)
// chartItemList.value[0].active = true
// }
// })
</script>
<style lang="scss" scoped>
......@@ -92,9 +139,11 @@ const props = defineProps({
height: 32px;
border-radius: 4px;
cursor: pointer;
&:hover{
&:hover {
background: var(--color-primary-2);
}
img {
width: 100%;
height: 100%;
......@@ -108,13 +157,14 @@ const props = defineProps({
height: 24px;
text-align: center;
left: 200px;
height: 12px;
top: 12px;
color: var(--text-primary-80-color);
}
.header-right {
width: 32px;
height: 32px;
cursor: pointer;
img {
width: 100%;
......@@ -122,5 +172,19 @@ const props = defineProps({
}
}
}
.main {
.chart-box {
width: 1520px;
height: 580px;
}
.tip-box {
height: 54px;
box-sizing: border-box;
padding-top: 10px;
// background: orange;
}
}
}
</style>
\ No newline at end of file
<template>
<div class="wrapper">
<div class="left">
<div class="left-text text-tip-1">{{ '统计维度:' }}</div>
<div class="left-list">
<ActionButton v-for="item, index in list" :key="index" :name="item.name"
:type="item.active ? 'active' : 'normal'" @click="handleClickItem(item)" />
</div>
</div>
<div class="right">
<slot name="chart-header-right"></slot>
</div>
</div>
</template>
<script setup>
import ActionButton from '@/components/base/ActionButton/index.vue'
const props = defineProps({
list: {
type: Array,
default: [
]
}
})
const emit = defineEmits(['clickItem'])
const handleClickItem = (item) => {
emit('clickItem', item)
}
</script>
<style lang="scss" scoped>
.wrapper {
width: 1520px;
height: 28px;
display: flex;
justify-content: space-between;
align-items: center;
.left {
display: flex;
gap: 8px;
align-items: center;
justify-content: flex-start;
.left-text {
color: var(--text-primary-80-color);
}
.left-list {
display: flex;
gap: 8px;
align-items: center;
justify-content: flex-start;
}
}
}
</style>
\ No newline at end of file
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.000000" height="16.000000" fill="none" customFrame="#000000">
<rect id="Line/Up" width="16.000000" height="16.000000" x="0.000000" y="0.000000" transform="matrix(1,0,0,-1,0,16)" />
<path id="路径" d="M11.852 7.80156L6.34264 0.20625C6.14264 -0.06875 5.73327 -0.06875 5.53483 0.20625L0.0238932 7.80156C-0.0354818 7.88438 0.0223307 8 0.125456 8L1.29733 8C1.37702 8 1.45202 7.96094 1.49889 7.89687L5.93796 1.77813L10.377 7.89687C10.4239 7.96094 10.4989 8 10.5786 8L11.7505 8C11.852 8 11.9114 7.88438 11.852 7.80156L11.852 7.80156Z" fill="rgb(5,95,194)" fill-rule="evenodd" transform="matrix(1,0,0,-1,2.0625,12)" />
</svg>
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.000000" height="16.000000" fill="none" customFrame="#000000">
<rect id="Line/Up" width="16.000000" height="16.000000" x="0.000000" y="0.000000" />
<path id="路径" d="M13.9145 11.8016L8.40514 4.20625C8.20514 3.93125 7.79577 3.93125 7.59733 4.20625L2.08639 11.8016C2.02702 11.8844 2.08483 12 2.18796 12L3.35983 12C3.43952 12 3.51452 11.9609 3.56139 11.8969L8.00046 5.77812L12.4395 11.8969C12.4864 11.9609 12.5614 12 12.6411 12L13.813 12C13.9145 12 13.9739 11.8844 13.9145 11.8016L13.9145 11.8016Z" fill="rgb(5,95,194)" fill-rule="evenodd" />
</svg>
<template>
<div class="wrapper">
<div class="show" @click="handleSwitchShowAll">
<div class="text text-compact">{{ isShowAll ? '收起' : '展开全部' }}</div>
<div class="icon">
<img v-if="isShowAll" src="./arrow-up.svg" alt="">
<img v-else src="./arrow-down.svg" alt="">
</div>
</div>
<div class="clear text-tip-1" @click="handleClear">
{{ '清空条件' }}
</div>
<div class="confirm text-tip-1" @click="handleConfirm">
{{ '确定' }}
</div>
</div>
</template>
<script setup>
import {ref} from 'vue'
const props = defineProps({
isShowAll: {
type: Boolean,
default: false
}
})
const handleSwitchShowAll = () => {
emit('showAll')
}
const emit = defineEmits(['showAll', 'clear', 'confirm'])
const handleClear = () => {
emit('clear')
}
const handleConfirm = () => {
emit('confirm')
}
</script>
<style lang="scss" scoped>
.wrapper {
height: 36px;
display: flex;
gap: 12px;
justify-content: flex-end;
align-items: center;
.show {
display: flex;
justify-content: center;
align-items: center;
gap: 4px;
cursor: pointer;
.text {
color: var(--color-primary-100);
}
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
}
.clear {
width: 98px;
height: 36px;
border-radius: 4px;
box-sizing: border-box;
border: 1px solid var(--bg-black-10);
text-align: center;
padding: 6px 16px;
color: var(--text-primary-65-color);
cursor: pointer;
}
.confirm {
width: 150px;
height: 36px;
border-radius: 4px;
box-sizing: border-box;
padding: 6px 59px;
background: var(--color-primary-100);
color: var(--bg-white-100);
text-align: center;
cursor: pointer;
}
}
</style>
\ No newline at end of file
<template>
<div class="line-chart-wrapper" id="line-chart"></div>
</template>
<script setup>
import { ref, onMounted, nextTick } from 'vue'
import setChart from '@/utils/setChart';
import getLineChart from './lineChart';
const props = defineProps({
lineChartData: {
type: Object,
default: {
dataX: [],
dataY: []
}
}
})
onMounted(() => {
const lineChart = getLineChart(props.lineChartData.dataX, props.lineChartData.dataY)
setChart(lineChart, 'line-chart', )
})
</script>
<style lang="scss">
.line-chart-wrapper {
width: 100%;
height: 100%;
// width: 1520px;
// height: 580px;
}
</style>
\ No newline at end of file
import * as echarts from 'echarts'
const getLineChart = (dataX, dataY) => {
return {
grid: {
left: 24,
top: 48,
right: 34,
bottom: 10,
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
splitLine: {
show: false
},
axisLine: {
show: false
},
data: dataX
},
yAxis: {
type: 'value',
splitLine: {
show: true,
lineStyle: {
color: ['#DEE2E7'], // 线条颜色,可以是数组,用于不同间隔交替颜色
width: 1, // 线宽
type: 'dashed', // 类型:'solid'(实线), 'dashed'(虚线), 'dotted'(点线)
// opacity: 0.6 // 透明度
}
},
axisLine: {
show: false
},
},
series: [
{
data: dataY,
type: 'line',
// showSymbol: false,
symbol: 'circle', // 圆形
symbolSize: 8, // 大小为8px
itemStyle: {
// color: 'rgba(5, 95, 194, 1)', // 填充为珊瑚红
color: '#fff',
borderColor: 'rgba(5, 95, 194, 1)',
borderWidth: 4,
// 不设置borderColor和borderWidth,即为纯实心
},
lineStyle: {
color: 'rgba(5, 95, 194, 1)'
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(5, 95, 194, 0.8)' // 起始颜色:深色
}, {
offset: 1,
color: 'rgba(5, 95, 194, 0)' // 结束颜色:浅色且透明度降低
}])
},
}
]
}
}
export default getLineChart;
\ No newline at end of file
<template>
<div class="pie-chart-wrapper" id="pie-chart"></div>
</template>
<script setup>
import { ref, onMounted, nextTick } from 'vue'
import setChart from '@/utils/setChart';
import getPieChart from './piechart';
const props = defineProps({
pieChartData: {
type: Array,
default: [
// {
// name: 'aaa',
// value: 12
// },
// {
// name: 'bbb',
// value: 8
// },
// {
// name: 'ccc',
// value: 15
// },
]
}
})
onMounted(() => {
const pieChart = getPieChart(props.pieChartData)
setChart(pieChart, 'pie-chart', )
})
</script>
<style lang="scss">
.pie-chart-wrapper {
width: 100%;
height: 100%;
// width: 1520px;
// height: 580px;
}
</style>
\ No newline at end of file
import { MUTICHARTCOLORS } from "@/common/constant";
const getPieChart = (data) => {
const colorList = MUTICHARTCOLORS
let option = {
color: colorList,
series: [
{
type: 'pie',
radius: [160, 190],
height: '100%',
left: 'center',
width: '98%',
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
label: {
alignTo: 'edge',
formatter: '{name|{b}}\n{time|{c} 条 {d}%}',
minMargin: 5,
edgeDistance: 10,
lineHeight: 25,
rich: {
name: {
color: 'rgba(59, 65, 75, 1)',
fontFamily: 'Microsoft YaHei',
fontSize: 16,
fontWeight: 'bold',
},
time: {
fontSize: 16,
fontFamily: 'Microsoft YaHei',
color: '#rgba(95, 101, 108, 1)'
}
}
},
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
<template>
<div class="radar-chart-wrapper" id="radar-chart"></div>
</template>
<script setup>
import { ref, onMounted, nextTick } from 'vue'
import setChart from '@/utils/setChart';
import getRadarChart from './radarChart';
const props = defineProps({
radarChartData: {
type: Object,
default: {
title: [],
data: []
}
}
})
onMounted(() => {
const radarChart = getRadarChart(props.radarChartData)
setChart(radarChart, 'radar-chart',)
})
</script>
<style lang="scss">
.radar-chart-wrapper {
width: 100%;
height: 100%;
// width: 1520px;
// height: 580px;
}
</style>
\ No newline at end of file
const getRadarChart = (data) => {
// const indicators = [
// { name: "集成电路", max: 10 },
// { name: "能源领域", max: 10 },
// { name: "量子科技", max: 10 },
// { name: "通信网络", max: 10 },
// { name: "人工智能", max: 10 },
// { name: "生物科技", max: 10 }
// ];
// const data = [
// {
// name: "337调查",
// value: [
// {
// name: '航空航天',
// value: 10,
// },
// {
// name: '先进制造',
// value: 2,
// },
// {
// name: '量子科技',
// value: 0,
// },
// {
// name: '人工智能',
// value: 6,
// },
// {
// name: '新材料',
// value: 7,
// },
// {
// name: '集成电路',
// value: 4,
// }
// ]
// },
// {
// name: "232调查",
// value: [ {
// name: '航空航天',
// value: 7,
// },
// {
// name: '先进制造',
// value: 3,
// },
// {
// name: '量子科技',
// value: 5,
// },
// {
// name: '人工智能',
// value: 9,
// },
// {
// name: '新材料',
// value: 10,
// },
// {
// name: '集成电路',
// value: 5,
// }]
// },
// {
// name: "301调查",
// value: [ {
// name: '航空航天',
// value: 8,
// },
// {
// name: '先进制造',
// value: 10,
// },
// {
// name: '量子科技',
// value: 2,
// },
// {
// name: '人工智能',
// value: 8,
// },
// {
// name: '新材料',
// value: 1,
// },
// {
// name: '集成电路',
// value: 3,
// }]
// }
// ]
const indicators = data.title.map(item => {
return {
name: item.name, max: data.maxNum
}
})
const data337 = [9, 6, 6, 6, 9, 7];
const data301 = [5, 3, 7, 8, 7, 9];
const data232 = [4, 10, 3, 4, 2, 5];
const option = {
color: ["rgba(5, 95, 194, 1)", "rgba(250, 140, 22, 1)", "rgba(146, 84, 222, 1)"],
legend: {
top: 24,
left: 'center',
icon: "circle",
itemWidth: 12,
itemHeight: 12,
itemGap: 24,
textStyle: {
color: "rgb(95, 101, 108)",
fontSize: 16,
fontFamily: "Microsoft YaHei",
fontWeight: 400,
lineHeight: 24
},
data: ["337调查", "301调查", "232调查"]
},
radar: {
shape: "polygon",
splitNumber: 5,
indicator: indicators,
center: ["50%", "56%"],
radius: "72%",
startAngle: 90,
clockwise: false,
axisName: {
color: "rgba(59, 65, 75, 1)",
fontSize: 16,
fontFamily: "Microsoft YaHei",
fontWeight: 700,
lineHeight: 24,
padding: [0, 5]
},
splitLine: {
lineStyle: {
color: "#d0d0d0",
width: 1
}
},
axisLine: {
lineStyle: {
color: "#d0d0d0",
width: 1
}
},
splitArea: {
show: true,
areaStyle: {
color: ["#fff", "rgb(247, 248, 249)", "#fff", "rgb(247, 248, 249)", "#fff"]
}
}
},
series: [
{
// name: "337调查",
name: data.data[0].name,
type: "radar",
data: [{ value: data.data[0].value }],
lineStyle: {
width: 2,
color: "rgba(5, 95, 194,1)"
},
symbol: "none",
areaStyle: {
color: "rgba(5, 95, 194,0.15)"
}
},
{
name: data.data[1].name,
type: "radar",
data: [{ value: data.data[1].value }],
lineStyle: {
width: 2,
color: "rgba(250, 140, 22, 1)"
},
symbol: "none",
areaStyle: {
color: "rgba(250, 140, 22, 0.15)"
}
},
{
name: data.data[2].name,
type: "radar",
data: [{ value: data.data[2].value }],
lineStyle: {
width: 2,
color: "rgba(146, 84, 222, 1)"
},
symbol: "none",
areaStyle: {
color: "rgba(146, 84, 222, 0.15)"
}
},
]
};
return option
}
export default getRadarChart
\ No newline at end of file
<template>
<div class="select-wrapper" :class="{'select-wrapper-custom': selectValue === '自定义'}">
<div class="select-left text-tip-1">{{ selectTitle + ':' }}</div>
<div class="select-right" :class="{'select-right-custom': selectValue === '自定义'}">
<el-select v-model="selectValue" :placeholder="placeholderName" style="width: 240px">
<!-- <el-option label="全部领域" value="全部领域" /> -->
<el-option v-for="item in selectList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
<el-date-picker style="width: 300px" v-if="selectValue === '自定义'" v-model="customTimeValue" type="daterange"
range-separator="--" start-placeholder="开始日期" end-placeholder="结束日期" size="default" />
</div>
</div>
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps({
selectTitle: {
type: String,
default: ''
},
selectList: {
type: Array,
default: []
},
placeholderName: {
type: String,
default: ''
},
selectName: {
type: String,
default: ''
},
customTime: {
type: String,
default: ''
}
})
const emit = defineEmits(['update:selectText', 'update:customTime'])
const selectValue = computed({
get: () => props.selectName,
set: (value) => emit('update:selectText', value)
})
const customTimeValue = computed({
get: () => props.customTime,
set: (value) => emit('update:customTime', value)
})
</script>
<style lang="scss" scoped>
.select-wrapper {
width: 348px;
height: 28px;
display: flex;
justify-content: space-between;
align-items: center;
gap: 8px;
.select-left {
width: 100px;
height: 24px;
color: var(--text-primary-65-color);
}
.select-right {
width: 240px;
display: flex;
gap: 8px;
justify-content: space-between;
:deep(.el-input__wrapper) {
border-radius: 4px;
}
}
.select-right-custom{
width: 630px;
}
}
.select-wrapper-custom{
width: 738px;
}
</style>
\ No newline at end of file
<template>
<div class="countrybill-wrapper">
<div class="header-box">我是国会法案</div>
<div class="main-box">
<div class="info-box">
<div class="switch-box" @click="handleSwitchChartData">
<img v-if="!isShowChart" src="@/views/dataLibrary/assets/icons/chart-active.svg" alt="">
<img v-else src="@/views/dataLibrary/assets/icons/data-active.svg" alt="">
</div>
<div class="num-box text-title-3-bold">
{{ `共 ${totalNum} 条数据` }}
</div>
</div>
<div class="content-box">
<ChartBox chartTitle="美国会法案提出数量随时间变化趋势" />
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import ChartBox from '../../chartBox/index.vue'
// 图表/数据
const isShowChart = ref(true)
const handleSwitchChartData = () => {
isShowChart.value = !isShowChart.value
}
// 总计数据
const totalNum = ref(12)
</script>
<style lang="scss" scoped>
.countrybill-wrapper {
width: 1600px;
height: 968px;
.headere-box {
width: 1568px;
height: 112px;
border-radius: 10px;
background: rgb(255, 255, 255);
border: 1px solid var(--bg-black-5);
margin: 16px auto;
}
.header-box {
width: 1568px;
height: 112px;
border-radius: 10px;
background: rgb(255, 255, 255);
border: 1px solid var(--bg-black-5);
margin: 16px auto;
}
.main-box {
.info-box {
margin: 0 auto;
width: 1568px;
height: 30px;
display: flex;
justify-content: space-between;
.switch-box {
width: 160px;
border-radius: 20px;
border: 1px solid var(--color-primary-100);
height: 30px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.num-box {
color: var(--color-red-100);
}
}
.content-box {
margin: 0 auto;
margin-top: 16px;
width: 1568px;
height: 766px;
border-radius: 10px;
background: rgba(255, 255, 255);
border: 1px solid var(--bg-black-5);
}
}
}
</style>
\ No newline at end of file
......@@ -72,7 +72,7 @@
</template>
<script setup>
import { computed, ref } from 'vue'
import { computed, onMounted, ref } from 'vue'
import Icon1 from './assets/icons/sider-icon1.svg'
import Icon2 from './assets/icons/sider-icon2.svg'
import Icon3 from './assets/icons/sider-icon3.svg'
......@@ -95,7 +95,6 @@ const tagsViewStore = useTagsViewStore()
// 在路由全局守卫中处理
router.beforeEach((to, from, next) => {
const tagsViewStore = useTagsViewStore()
// 路由允许添加标签(排除掉隐藏的布局页如 /404, /login 等)
if (to.meta?.title && !to.meta?.hiddenTag) {
tagsViewStore.addView({
......@@ -117,19 +116,19 @@ const siderList = ref([
children: [
{
name: '国会法案',
path: '/countryBill',
path: '/dataLibrary/countryBill',
active: true,
},
{
name: '州法案',
path: '/stateBill',
path: '/dataLibrary/stateBill',
active: false,
},
]
},
{
name: '科技政令',
path: '/dataDecree',
path: '/dataLibrary/dataDecree',
icon: Icon2,
active: false,
isExpanded: false,
......@@ -139,7 +138,7 @@ const siderList = ref([
},
{
name: '美国科技智库',
path: '/dataThinkTank',
path: '/dataLibrary/dataThinkTank',
icon: Icon3,
active: false,
isExpanded: false,
......@@ -155,22 +154,22 @@ const siderList = ref([
children: [
{
name: '实体清单',
path: '/dataEntityList',
path: '/dataLibrary/dataEntityList',
active: false,
},
{
name: '商业管制清单',
path: '/dataCommerceControlList',
path: '/dataLibrary/dataCommerceControlList',
active: false,
},
{
name: '实体清单事件',
path: '/dataEntityListEvent',
path: '/dataLibrary/dataEntityListEvent',
active: false,
},
{
name: '商业管制清单事件',
path: '/dataCommerceControlListEvent',
path: '/dataLibrary/dataCommerceControlListEvent',
active: false,
},
]
......@@ -191,22 +190,22 @@ const siderList = ref([
children: [
{
name: 'SDN清单',
path: '/sDNList',
path: '/dataLibrary/sDNList',
active: false,
},
{
name: '涉军企业清单',
path: '/mREList',
path: '/dataLibrary/mREList',
active: false,
},
{
name: 'SDN清单事件',
path: '/sDNListEvent',
path: '/dataLibrary/sDNListEvent',
active: false,
},
{
name: '涉军企业清单事件',
path: '/mREListEvent',
path: '/dataLibrary/mREListEvent',
active: false,
},
]
......@@ -219,17 +218,17 @@ const siderList = ref([
children: [
{
name: '337调查',
path: '/case337',
path: '/dataLibrary/case337',
active: false,
},
{
name: '232调查',
path: '/case232',
path: '/dataLibrary/case232',
active: false,
},
{
name: '301调查',
path: '/case301',
path: '/dataLibrary/case301',
active: false,
},
]
......@@ -251,22 +250,22 @@ const siderList = ref([
children: [
{
name: '国会议员',
path: '/congressMan',
path: '/dataLibrary/congressMan',
active: false,
},
{
name: '科技企业领袖',
path: '/technologyLeader',
path: '/dataLibrary/technologyLeader',
active: false,
},
{
name: '机构主官',
path: '/minister',
path: '/dataLibrary/minister',
active: false,
},
{
name: '智库研究人员',
path: '/thinkTankResearcher',
path: '/dataLibrary/thinkTankResearcher',
active: false,
},
]
......@@ -279,17 +278,17 @@ const siderList = ref([
children: [
{
name: '科技企业',
path: '/technologyCompany',
path: '/dataLibrary/technologyCompany',
active: false,
},
{
name: '研究型大学',
path: '/researchUniversity',
path: '/dataLibrary/researchUniversity',
active: false,
},
{
name: '重点实验室',
path: '/keyLab',
path: '/dataLibrary/keyLab',
active: false,
},
]
......@@ -316,13 +315,25 @@ const siderList = ref([
const handleSiderItem = (item) => {
siderList.value.forEach(val => {
val.active = false
val.isExpanded = false
if (val.children && val.children.length) {
val.children.forEach(vall => {
vall.active = false
})
}
})
item.isExpanded = true
item.active = true
item.isExpanded = !item.isExpanded
if (item.path) {
router.push({
path: item.path
})
} else {
item.children[0].active = true
router.push({
path: item.children[0].path
})
}
}
......@@ -342,13 +353,11 @@ const handleSiderSecondItem = (item) => {
}
const openedTabList = computed(() => {
const tagsViewStore = useTagsViewStore()
const arr = tagsViewStore.visitedViews
return arr
})
const handleClickTab = (tab) => {
const tagsViewStore = useTagsViewStore()
tagsViewStore.visitedViews.forEach(val => {
val.active = false
})
......@@ -360,6 +369,7 @@ const handleClickTab = (tab) => {
)
siderList.value.forEach(val => {
val.active = false
val.isExpanded = false
if (val.children && val.children.length) {
val.children.forEach(vall => {
vall.active = false
......@@ -374,10 +384,12 @@ const handleClickTab = (tab) => {
return
}
} else {
val.children.forEach(vall => {
if (vall.name === tab.meta.title) {
vall.active = true
val.active = true
val.isExpanded = true
return
}
})
......@@ -392,7 +404,6 @@ const handleCloseCurTab = (tab, index) => {
let activeTab
if (!tab.active) {
const tagsViewStore = useTagsViewStore()
tagsViewStore.delView(tab)
} else {
siderList.value.forEach(val => {
......@@ -404,7 +415,6 @@ const handleCloseCurTab = (tab, index) => {
}
})
if (index === openedTabList.value.length - 1) {
const tagsViewStore = useTagsViewStore()
tagsViewStore.delView(tab)
setTimeout(() => {
tagsViewStore.visitedViews[tagsViewStore.visitedViews.length - 1].active = true
......@@ -432,7 +442,6 @@ const handleCloseCurTab = (tab, index) => {
})
} else {
const tagsViewStore = useTagsViewStore()
tagsViewStore.delView(tab)
tagsViewStore.visitedViews[index].active = true
......@@ -459,10 +468,6 @@ const handleCloseCurTab = (tab, index) => {
})
}
}
}
......@@ -471,6 +476,10 @@ const handleClickToolBox = () => {
ElMessage.warning("当前功能正在开发中,敬请期待!");
};
onMounted(() => {
})
</script>
......@@ -480,6 +489,7 @@ const handleClickToolBox = () => {
.data-library-wrapper {
width: 1920px;
height: 1080px;
overflow: hidden;
// background: orange;
.data-library-header {
......@@ -615,29 +625,57 @@ const handleClickToolBox = () => {
.tab-box {
width: 1600px;
height: 48px;
background: rgba(255, 255, 255);
border-bottom: 2px solid var(--bg-black-5);
display: flex;
overflow: hidden;
.tab-item {
height: 48px;
// height: 46px;
white-space: nowrap;
/* 强制文字不换行 */
overflow: hidden;
/* 隐藏溢出的文字 */
text-overflow: ellipsis;
/* 显示省略号 */
display: flex;
flex-wrap: nowrap;
gap: 8px;
align-items: center;
padding: 0 12px 0 16px;
border-bottom: 2px solid var(--bg-black-5);
border-bottom: 2px solid var(--bg-white-100);
cursor: pointer;
// animation: all ease 0.5s;
&:hover {
flex: 0 0 auto;
/* 不再压缩 */
/* 或者设定一个固定宽度 */
/* width: 150px; */
z-index: 10;
/* 提高层级 */
// box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
// border-bottom: 2px solid var(--color-primary-100);
.text {
// width: 150px;
color: var(--color-primary-100);
}
}
.text {
/* 关键属性2: 处理内部文字溢出 */
white-space: nowrap;
/* 强制文字不换行 */
overflow: hidden;
/* 隐藏溢出的文字 */
text-overflow: ellipsis;
/* 显示省略号 */
}
.text-active {
color: var(--color-primary-100);
}
......@@ -645,6 +683,10 @@ const handleClickToolBox = () => {
.icon {
width: 16px;
height: 16px;
&:hover{
border-radius: 8px;
background: var(--color-primary-10);
}
img {
width: 100%;
......@@ -654,7 +696,7 @@ const handleClickToolBox = () => {
}
.tab-item-active {
border-bottom: 2px solid var(--color-primary-100);
border-bottom: 2px solid var(--color-primary-100) !important;
}
}
......
......@@ -7,12 +7,19 @@
<div class="sub-title">{{ subtitle }}</div>
</div>
<div class="description">{{ description }}</div>
<div v-if="quantity > 0" class="quantity" :style="{ color: color }">{{ quantity }}{{ unit || "个" }}</div>
<div v-if="quantity > 0" class="quantity" :style="{ color: color }">
{{ quantity }}{{ unit || "个" }}
<div class="quantity-title-des" v-if="desMap[title]">
<img class="info-icon" :src="infoIcon" alt="" />
{{ desMap[title] }}
</div>
</div>
</div>
</div>
</template>
<script setup>
import infoIcon from "../assets/icons/info-icon.png";
defineProps({
title: {
type: String,
......@@ -39,6 +46,11 @@ defineProps({
default: "#409EFF"
}
});
const desMap = {
实体清单: "中国实体数量",
商业管制清单: "受管制物项数量",
关键与新兴技术清单: "关键与新兴技术数量"
};
</script>
<style scoped lang="scss">
......@@ -53,9 +65,7 @@ defineProps({
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
transition:
transform 0.3s ease,
box-shadow 0.3s ease;
transition: transform 0.3s ease, box-shadow 0.3s ease;
cursor: pointer;
}
......@@ -117,9 +127,27 @@ defineProps({
.quantity {
position: absolute;
top: 20px;
top: 15px;
right: 20px;
font-size: 32px;
font-weight: 700;
width: 150px;
display: flex;
flex-direction: column;
align-items: flex-end;
.quantity-title-des {
display: flex;
align-items: center;
font-family: Source Han Sans CN;
font-size: 14px;
font-weight: 400;
color: rgba(95, 101, 108, 1);
line-height: 1.4;
.info-icon {
width: 16px;
height: 16px;
margin-right: 4px;
}
}
}
</style>
......@@ -50,12 +50,25 @@
<div class="home-main" ref="homeMainRef">
<div class="home-top-bg"></div>
<div class="home-main-header">
<SearchContainer style="margin-bottom: 0; margin-top: 48px; height: fit-content" v-if="homeMainRef"
placeholder="搜索出口管制" :containerRef="homeMainRef" areaName="实体清单" />
<SearchContainer
style="margin-bottom: 0; margin-top: 48px; height: fit-content"
v-if="homeMainRef"
placeholder="搜索出口管制"
:containerRef="homeMainRef"
areaName="实体清单"
/>
<div class="home-main-header-footer-info">
<InfoCard v-for="(item, index) in infoList" :key="item.id" :title="item.nameZh" :subtitle="item.nameAbbr"
:description="item.description" :quantity="item.postCount" unit="次" :color="infoListColor[index]"
@click="handleToEntityListNoId(item)" />
<InfoCard
v-for="(item, index) in infoList"
:key="item.id"
:title="item.nameZh"
:subtitle="item.nameAbbr"
:description="item.description"
:quantity="item.postCount"
unit="次"
:color="infoListColor[index]"
@click="handleToEntityListNoId(item)"
/>
</div>
</div>
......@@ -81,8 +94,15 @@
<img src="./assets/images/box1-right.png" alt="" />
</div>
</div>
<el-carousel ref="carouselRef" height="370px" :autoplay="true" :interval="3000" arrow="never"
indicator-position="none" @change="handleCarouselChange">
<el-carousel
ref="carouselRef"
height="370px"
:autoplay="true"
:interval="3000"
arrow="never"
indicator-position="none"
@change="handleCarouselChange"
>
<el-carousel-item v-for="(item, index) in entitiesDataInfoList" :key="item.id + index">
<div>
<div class="box1-top">
......@@ -100,8 +120,11 @@
</div>
<div class="box1-top-content-item">
<span class="box1-top-content-item-title">· 涉及领域:</span>
<div class="box1-top-content-item-tags" v-for="(domainItem, index) in item.domains"
:key="index">
<div
class="box1-top-content-item-tags"
v-for="(domainItem, index) in item.domains"
:key="index"
>
<el-tag :type="getTagType(domainItem)">{{ domainItem }}</el-tag>
</div>
</div>
......@@ -110,10 +133,18 @@
<div class="box1-bottom">
<div class="box1-bottom-title">· 涉及主要实体:</div>
<div class="box1-bottom-content">
<div class="box1-bottom-content-item" v-for="(ett, index) in item.sanEntities" :key="index"
@click="handleEntityClick(ett)">
<el-image v-if="ett.img" class="box1-bottom-content-item-img" :src="ett.img"
alt=""></el-image>
<div
class="box1-bottom-content-item"
v-for="(ett, index) in item.sanEntities"
:key="index"
@click="handleEntityClick(ett)"
>
<el-image
v-if="ett.img"
class="box1-bottom-content-item-img"
:src="ett.img"
alt=""
></el-image>
<div v-else class="box1-bottom-content-item-imgUndefined">
{{
(ett.entityNameZh || ett.enName)?.match(
......@@ -186,8 +217,14 @@
</div>
</template>
</custom-container> -->
<RiskSignal :list="warningList" @item-click="handleToRiskSignalDetail" @more-click="handleToMoreRiskSignal"
riskLevel="signalLevel" postDate="signalTime" name="signalTitle" />
<RiskSignal
:list="warningList"
@item-click="handleToRiskSignalDetail"
@more-click="handleToMoreRiskSignal"
riskLevel="signalLevel"
postDate="signalTime"
name="signalTitle"
/>
</el-col>
</el-row>
......@@ -210,11 +247,19 @@
</custom-container>
</el-col> -->
<div class="center-center">
<NewsList :newsList="newsList" @item-click="handleNewsInfoClick" @more-click="handleToMoreNews"
content="newsContent" />
<MessageBubble :messageList="socialMediaList" @person-click="handlePerClick" imageUrl="avatar"
@more-click="handleToSocialDetail" />
<NewsList
:newsList="newsList"
@item-click="handleNewsInfoClick"
@more-click="handleToMoreNews"
content="newsContent"
/>
<MessageBubble
:messageList="socialMediaList"
@person-click="handlePerClick"
imageUrl="avatar"
@more-click="handleToSocialDetail"
/>
<!-- <custom-container title="社交媒体" :titleIcon="dialogIcon" height="450px">
<template #default>
<div class="dialog-list">
......@@ -240,14 +285,19 @@
<template #default="scope">
<div style="display: flex; align-items: center">
<span style="margin-right: 10px; width: 40px">{{ scope.row.num }}</span>
<el-progress :percentage="scope.row.percent * 100" :show-text="false"
:status="getStatus(scope.row.percent)" />
<el-progress
:percentage="scope.row.percent * 100"
:show-text="false"
:status="getStatus(scope.row.percent)"
/>
</div>
</template>
</el-table-column>
<el-table-column label="重点领域" width="220" align="center">
<template #default="scope">
<div style="display: flex; justify-content: center; align-items: center; gap: 5px">
<div
style="display: flex; justify-content: center; align-items: center; gap: 5px"
>
<el-tag v-for="tag in scope.row.tags" :key="tag" :type="getTagType(tag)">{{
tag
}}</el-tag>
......@@ -264,14 +314,19 @@
<template #default="scope">
<div style="display: flex; align-items: center">
<span style="margin-right: 10px; width: 40px">{{ scope.row.num }}</span>
<el-progress :percentage="scope.row.percent * 100" :show-text="false"
:status="getStatus(scope.row.percent)" />
<el-progress
:percentage="scope.row.percent * 100"
:show-text="false"
:status="getStatus(scope.row.percent)"
/>
</div>
</template>
</el-table-column>
<el-table-column label="重点领域" width="220" align="center">
<template #default="scope">
<div style="display: flex; justify-content: center; align-items: center; gap: 5px">
<div
style="display: flex; justify-content: center; align-items: center; gap: 5px"
>
<el-tag v-for="tag in scope.row.tags" :key="tag" :type="getTagType(tag)">{{
tag
}}</el-tag>
......@@ -288,8 +343,11 @@
<template #default="scope">
<div style="display: flex; align-items: center">
<span style="margin-right: 10px; width: 40px">{{ scope.row.num }}</span>
<el-progress :percentage="scope.row.percent * 100" :show-text="false"
:status="getStatus(scope.row.percent)" />
<el-progress
:percentage="scope.row.percent * 100"
:show-text="false"
:status="getStatus(scope.row.percent)"
/>
</div>
</template>
</el-table-column>
......@@ -341,9 +399,13 @@
<el-row :gutter="20" style="width: 1600px; margin: 0 auto; margin-top: 39px">
<CustomTitle id="position4" title="资源库" style="margin-top: 0px" />
<div class="resource-tabs">
<div v-for="tab in resourceTabs" :key="tab.value" class="resource-tab-item"
:class="{ active: activeResourceTab === tab.value, disabled: tab.disabled }"
@click="handleResourceTabClick(tab)">
<div
v-for="tab in resourceTabs"
:key="tab.value"
class="resource-tab-item"
:class="{ active: activeResourceTab == tab.value, disabled: tab.disabled }"
@click="handleResourceTabClick(tab)"
>
{{ tab.label }}
</div>
</div>
......@@ -356,15 +418,25 @@
<div class="box4-item" v-for="(item, idx) in sanctionProcessList" :key="item.title">
<div class="box4-item-left">
<el-image :src="dotIcon" alt="图片" class="box4-item-left-icon" />
<div class="box4-item-left-line" v-if="idx + 1 != sanctionProcessList.length"></div>
<div
class="box4-item-left-line"
v-if="idx + 1 != sanctionProcessList.length"
></div>
</div>
<div class="box4-item-right">
<div class="box4-item-right-header" @click="handleSanc(item)">
<span class="box4-item-right-header-title">{{ item.postDate }}{{ item.title }}</span>
<span class="box4-item-right-header-title"
>{{ item.postDate }}{{ item.title }}</span
>
<span class="box4-item-right-header-desc">{{ item.desc }}</span>
</div>
<el-tooltip effect="dark" :content="item.content" popper-class="common-prompt-popper"
placement="top" :show-after="500">
<el-tooltip
effect="dark"
:content="item.content"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="box4-item-right-content">
{{ item.content }}
</div>
......@@ -372,8 +444,12 @@
</div>
</div>
</div>
<div class="box4-footer" :style="{ marginTop: sanctionProcessList.length > 0 ? '0px' : 'auto' }">
<el-button type="primary" link @click="handleGetMore">查看更多
<div
class="box4-footer"
:style="{ marginTop: sanctionProcessList.length > 0 ? '0px' : 'auto' }"
>
<el-button type="primary" link @click="handleGetMore"
>查看更多
<el-icon>
<DArrowRight />
</el-icon>
......@@ -390,8 +466,15 @@
</template>
<template #default>
<div class="box5">
<el-table :data="entitiesList" class="sanction-table" stripe empty-text="暂无数据" height="700px"
header-row-class-name="table-header" row-class-name="table-row">
<el-table
:data="entitiesList"
class="sanction-table"
stripe
empty-text="暂无数据"
height="700px"
header-row-class-name="table-header"
row-class-name="table-row"
>
<!-- <el-table-column prop="index" label="序号" width="80" align="center">
<template #default="scope">
{{ scope.$index + 1 + (currentPage - 1) * pageSize }}
......@@ -401,8 +484,12 @@
<el-table-column prop="name" label="实体名称" min-width="200">
<template #default="scope">
<div class="tableName" @click="handleCompClick(scope.row)">
<el-image v-if="scope.row.img" class="box1-bottom-content-item-img" :src="scope.row.img"
alt=""></el-image>
<el-image
v-if="scope.row.img"
class="box1-bottom-content-item-img"
:src="scope.row.img"
alt=""
></el-image>
<div v-else class="box1-bottom-content-item-imgUndefined">
{{
(scope.row.name || scope.row.enName)?.match(
......@@ -453,13 +540,19 @@
<el-table-column prop="revenue" label="50%规则子企业" width="280" align="right">
<template #default="scope">
<div class="num-item" v-if="scope.row.ruleOrgCount > 0">
<div class="name-item" :class="[
'revenue-cell',
scope.row.revenue === '无营收数据' ? 'no-revenue' : ''
]">
<div
class="name-item"
:class="[
'revenue-cell',
scope.row.revenue === '无营收数据' ? 'no-revenue' : ''
]"
>
{{ scope.row.ruleOrgList[0].orgName }}...等
</div>
<div style="width: 50px; color: #409eff; cursor: pointer" @click="handleOrgClick(scope.row)">
<div
style="width: 50px; color: #409eff; cursor: pointer"
@click="handleOrgClick(scope.row)"
>
{{ scope.row.ruleOrgCount }}家>
</div>
</div>
......@@ -471,8 +564,15 @@
<!-- <div class="pagination-info">
第{{ currentPage }}页,共{{ totalPages }}页
</div> -->
<el-pagination v-model:current-page="currentPage" :page-size="pageSize" :total="total"
:pager-count="5" layout="prev, pager, next" background @current-change="handlePageChange" />
<el-pagination
v-model:current-page="currentPage"
:page-size="pageSize"
:total="total"
:pager-count="5"
layout="prev, pager, next"
background
@current-change="handlePageChange"
/>
</div>
</div>
</template>
......@@ -538,8 +638,14 @@
</div>
<div class="right-footer">
<div class="total-count">{{ totalAll }}</div>
<el-pagination v-model:current-page="currentPageAll" :page-size="pageSizeAll" :total="totalAll"
layout="prev, pager, next" background @current-change="handlePageChangeAll" />
<el-pagination
v-model:current-page="currentPageAll"
:page-size="pageSizeAll"
:total="totalAll"
layout="prev, pager, next"
background
@current-change="handlePageChangeAll"
/>
</div>
</div>
</div>
......@@ -574,8 +680,12 @@
</div>
</template>
</el-dialog> -->
<RuleSubsidiaryDialog v-model="dialogVisible" :company-name="currentRuleCompany" :total-count="currentRuleCount"
:data-list="currentOrgList" />
<RuleSubsidiaryDialog
v-model="dialogVisible"
:company-name="currentRuleCompany"
:total-count="currentRuleCount"
:data-list="currentOrgList"
/>
</div>
<el-dialog v-model="mediaVisible" title="社交媒体信息" width="500" :before-close="handleMediaClose">
<div class="dialog-content">
......@@ -746,7 +856,8 @@ const handleTitleClick = item => {
const route = router.resolve({
path: "/exportControl/singleSanction",
query: {
id: item.id
id: item.id,
sanTypeId: item.sanTypeId
}
});
window.open(route.href, "_blank");
......@@ -759,7 +870,8 @@ const handleCompClick = item => {
const route = router.resolve({
name: "companyPages",
params: {
id: item.id
id: item.id,
sanTypeId: item.sanTypeId
}
});
window.open(route.href, "_blank");
......@@ -828,7 +940,15 @@ onMounted(async () => {
// 交换第二个和第三个元素
[dataCount[1], dataCount[2]] = [dataCount[2], dataCount[1]];
infoList.value = dataCount.slice(0, 2);
allSanTypeIds.value = infoList.value.map(item => item.id);
resourceTabs.value = infoList.value.map(item => ({
label: item.nameZh,
value: tabMap[item.id],
id: [item.id],
disabled: item.id == "13" // 商业管制清单不展示
}));
resourceTabs.value.unshift({ label: "全部制裁", value: "all", id: "", disabled: false });
console.log("返回的数据结构 infoList =》", infoList.value);
const entityList = _.map(entitiesDataInfo?.sanEntities ?? [], ({ entityNameZh, entityName }) => {
return { name: entityNameZh, enName: entityName };
});
......@@ -1013,15 +1133,22 @@ const handleToEntityList = item => {
// 跳转到V2.0实体清单无ID
const handleToEntityListNoId = item => {
console.log("这是什么数据 =>", item);
if (item.nameZh == "实体清单") {
const routeData = router.resolve({
path: "/exportControl/entityList"
path: "/exportControl/entityList",
query: {
sanTypeId: item.id
}
});
// 打开一个新页面
window.open(routeData.href, "_blank");
} else if (item.nameZh == "商业管制清单") {
const routeData = router.resolve({
path: "/exportControl/commercialControlList"
path: "/exportControl/commercialControlList",
query: {
sanTypeId: item.id
}
});
// 打开一个新页面
window.open(routeData.href, "_blank");
......@@ -1036,6 +1163,7 @@ const curBillListIndex = ref(0);
const searchExportControlText = ref("");
const infoListColor = ref(["rgba(206, 79, 81, 1)", "rgba(114, 46, 209, 1)", "rgba(132, 136, 142, 1)", "rgba(132, 136, 142, 1)"]);
const infoList = ref([]);
const allSanTypeIds = ref(["1", "13"]);
// 雷达图
const domainChecked = ref(false);
......@@ -1214,7 +1342,8 @@ const fetchSanctionList = async () => {
techDomainIds: techDomains,
years: years,
isCn: false,
typeName: "实体清单"
// typeName: "实体清单"
sanTypeIds: allSanTypeIds.value
};
const res = await getExportControlList(params);
......@@ -1223,8 +1352,8 @@ const fetchSanctionList = async () => {
const tags = Array.isArray(item.techDomains)
? item.techDomains
: item.techDomain
? [item.techDomain]
: item.techDomainList || [];
? [item.techDomain]
: item.techDomainList || [];
const fullTime = item.startTime
? formatAnyDateToChinese(item.startTime)
......@@ -1254,13 +1383,13 @@ const fetchSanctionList = async () => {
countTag: item.cnEntityCount
? `${item.cnEntityCount}家中国实体`
: item.ruleOrgCount
? `${item.ruleOrgCount}家关联实体`
: item.countTag || ""
? `${item.ruleOrgCount}家关联实体`
: item.countTag || ""
};
});
totalAll.value = res.totalElements;
}
} catch (error) { }
} catch (error) {}
};
const handlePageChangeAll = val => {
......@@ -1344,7 +1473,8 @@ const fetchEntitiesList = async (page = 1, size = 10) => {
const handleGetMore = async () => {
sanctionPage.value++;
try {
const res = await getSanctionProcess("实体清单", sanctionPage.value, 10);
const sanTypeid = activeResourceTabItem.value.id ? activeResourceTabItem.value.id : allSanTypeIds.value;
const res = await getSanctionProcess(sanTypeid, sanctionPage.value, 10);
if (res && res.content) {
// 将新数据合并到现有列表中
const newData = res.content.map(item => ({
......@@ -1369,7 +1499,7 @@ const handleGetMore = async () => {
// 获取历次制裁过程数据
const fetchSanctionProcess = async (page = 1, size = 10) => {
try {
const res = await getSanctionProcess("实体清单", page, size);
const res = await getSanctionProcess(allSanTypeIds.value, page, size);
if (res) {
sanctionProcessList.value = res.content.map(item => ({
...item,
......@@ -1394,18 +1524,25 @@ const handlePageChange = page => {
const searchKeyword = ref("");
// 资源库 Tab 数据
const resourceTabs = [
{ label: "全部制裁", value: "all", disabled: false },
{ label: "实体清单", value: "entity", disabled: false },
{ label: "商业管制清单", value: "commerce", disabled: true }
const resourceTabs = ref([
// { label: "全部制裁", value: "all", disabled: false },
// { label: "实体清单", value: "entity", disabled: false },
// { label: "商业管制清单", value: "commerce", disabled: true }
// { label: "关键与新兴技术清单", value: "tech", disabled: true },
// { label: "军事最终用户清单", value: "military", disabled: true }
];
]);
const activeResourceTab = ref("all");
const activeResourceTabItem = ref({});
// 数据对应,便宜行事
const tabMap = {
1: "entity",
13: "commerce"
};
const handleResourceTabClick = tab => {
if (tab.disabled) return;
activeResourceTab.value = tab.value;
activeResourceTabItem.value = tab;
};
const strengthLabels = {
......@@ -1532,7 +1669,7 @@ const handleGetHylyList = async () => {
hylymc: "全部分类"
};
categoryList.value = [obj, ...categoryList.value];
} catch (error) { }
} catch (error) {}
};
const chart1Data = ref({
......@@ -2032,7 +2169,6 @@ const handleMediaClick = item => {
}
.box3-content {
// flex: 1;
.el-progress--line {
width: 82px;
......@@ -2176,8 +2312,7 @@ const handleMediaClick = item => {
overflow-y: auto;
.home-top-bg {
background:
url("./assets/images/background.png"),
background: url("./assets/images/background.png"),
linear-gradient(180deg, rgba(229, 241, 254, 1) 0%, rgba(246, 251, 255, 0) 30%);
background-size: 100% 100%;
position: absolute;
......
......@@ -25,8 +25,12 @@
<div class="left-center">
<AnalysisBox title="出口管制分类编码(ECCN)" :showAllBtn="false">
<div class="button-list">
<div :class="['button', { 'click': item.isClick }]" @click="changeECCN(item)" v-for="(item, i) in ECCNList"
:key="i">
<div
:class="['button', { click: item.isClick }]"
@click="changeECCN(item)"
v-for="(item, i) in ECCNList"
:key="i"
>
<span>{{ item.ranking }}{{ item.name }}</span>
</div>
</div>
......@@ -44,9 +48,17 @@
<AnalysisBox title="商业管制清单更新历史" :showAllBtn="false">
<template #header-btn>
<div class="filters">
<el-select v-model="selectedDomain" placeholder="Select"
style="width: 150px; height: 32px; margin-right: 16px">
<el-option v-for="item in domainOptions" :key="item.value" :label="item.label" :value="item.value" />
<el-select
v-model="selectedDomain"
placeholder="Select"
style="width: 150px; height: 32px; margin-right: 16px"
>
<el-option
v-for="item in domainOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<!-- <el-checkbox v-model="onlyChina">只看涉华动态</el-checkbox> -->
</div>
......@@ -59,30 +71,43 @@
</div>
<div class="img-zone">
<img :src="item.icon || title" alt />
<div v-if="i < sanctionList.length - 1"
:class="['img-line', { 'img-line-last': i === sanctionList.length - 1 }]">
</div>
<div
v-if="i < sanctionList.length - 1"
:class="['img-line', { 'img-line-last': i === sanctionList.length - 1 }]"
></div>
</div>
<div class="main">
<div class="main-title">{{ item.name }}</div>
<!-- <div class="main-title" @click="handleClick(item)">{{ item.name }}</div> -->
<el-tooltip effect="dark" :content="item.summary" popper-class="common-prompt-popper" placement="top"
:show-after="500">
<el-tooltip
effect="dark"
:content="item.summary"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="main-desc">{{ item.summary }}</div>
</el-tooltip>
<div class="tag-box">
<div v-for="tag in item.techDomainList" :key="tag" class="tag-item">{{ tag }}</div>
</div>
<div :class="{ 'count-tag': item.cnEntityCount }">{{ item.cnEntityCount ? `${item.cnEntityCount}家中国实体` :
"" }}</div>
<div :class="{ 'count-tag': item.cnEntityCount }">
{{ item.cnEntityCount ? `${item.cnEntityCount}家中国实体` : "" }}
</div>
</div>
</div>
</div>
<div class="left-footer">
<div class="total-count">共 {{ totalAll }} 项</div>
<el-pagination v-model:current-page="currentPageAll" :page-size="pageSizeAll" :total="totalAll"
layout="prev, pager, next" background @current-change="handlePageChangeAll" />
<el-pagination
v-model:current-page="currentPageAll"
:page-size="pageSizeAll"
:total="totalAll"
layout="prev, pager, next"
background
@current-change="handlePageChangeAll"
/>
</div>
</AnalysisBox>
</div>
......@@ -110,17 +135,31 @@
<span>关键人物</span>
</div>
<div class="key-person-list">
<div class="person-item" v-for="(item, index) in publishInfo.personList" :key="index"
@click="handlePerClick(item)">
<div
class="person-item"
v-for="(item, index) in publishInfo.personList"
:key="index"
@click="handlePerClick(item)"
>
<img :src="item.imageUrl" alt />
<div class="person-info">
<el-tooltip effect="dark" :content="item.name" popper-class="common-prompt-popper" placement="top"
:show-after="500">
<el-tooltip
effect="dark"
:content="item.name"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="name">{{ item.name }}</div>
</el-tooltip>
<el-tooltip effect="dark" :content="item.position" popper-class="common-prompt-popper" placement="top"
:show-after="500">
<el-tooltip
effect="dark"
:content="item.position"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="title1">{{ item.position }}</div>
</el-tooltip>
</div>
......@@ -166,9 +205,18 @@ import defaultIcon from "../../../../../assets/icons/default-avatar.png";
import icon01 from "../../assets/icon01.png";
import icon02 from "../../assets/icon02.png";
import { ArrowDown } from "@element-plus/icons-vue";
import { ElTable, ElTableColumn, ElButton, ElSelect, ElOption, ElInput } from 'element-plus'
import { getCCLInfo, getECCN, getECCNList, getPublishInfo, getPublishOrgInfo, getEntityUpdateInfo } from "@/api/exportControlV2.0.js";
import { ElTable, ElTableColumn, ElButton, ElSelect, ElOption, ElInput } from "element-plus";
import {
getCCLInfo,
getECCN,
getECCNList,
getPublishInfo,
getPublishOrgInfo,
getEntityUpdateInfo
} from "@/api/exportControlV2.0.js";
import { useRoute } from "vue-router";
const route = useRoute();
// 处理点击发布机构的方法
const handleClickOrg = item => {
// console.log("点击了发布机构:", item);
......@@ -238,13 +286,14 @@ const getSanctionUpdate = async () => {
isCn: onlyChina.value,
techDomainIds: selectedDomain.value ? [selectedDomain.value] : [],
// typeName: "实体清单",
typeName: "商业管制清单",
// typeName: "商业管制清单",
pageNum: currentPageAll.value,
pageSize: pageSizeAll.value
pageSize: pageSizeAll.value,
sanTypeIds: [Number(sanTypeId.value)] || 13 // 商业管制清单固定13
};
try {
const res = await getEntityUpdateInfo(data);
console.log('-----getSanctionUpdate', res)
console.log("-----getSanctionUpdate", res);
if (res && res.code === 200) {
console.log(res.data.content);
sanctionList.value = (res.data.content || []).map(item => ({
......@@ -288,13 +337,13 @@ const handlePageChangeAll = val => {
const publishInfo = ref({});
const getPublishInfoFn = async () => {
const params = {
sanTypeId: 13 // 商业管制清单固定13
sanTypeId: sanTypeId.value || 13 // 商业管制清单固定13
};
try {
const res = await getPublishInfo(params);
if (res && res.code === 200) {
publishInfo.value = res.data;
console.log('------getPublishInfoFn', res.data)
console.log("------getPublishInfoFn", res.data);
// 获取发布机构动态
getPublishOrgInfoFn();
}
......@@ -348,12 +397,12 @@ const CCLInfo = ref({
description: "xxxxx",
legalBasis: "法律依据",
controlledObject: "管制对象",
name: '',
orgId: '',
orgLogoUrl: '',
orgName: '',
originalName: '',
shortName: '',
name: "",
orgId: "",
orgLogoUrl: "",
orgName: "",
originalName: "",
shortName: "",
restrictiveMeasure: "核心限制措施"
});
const getCCLInfoFn = async () => {
......@@ -361,7 +410,7 @@ const getCCLInfoFn = async () => {
const res = await getCCLInfo();
if (res && res.code === 200) {
CCLInfo.value = res.data;
console.log('getCCLInfoFn', CCLInfo.value)
console.log("getCCLInfoFn", CCLInfo.value);
}
} catch (error) {
console.error("获取商业管制清单基本信息失败:", error);
......@@ -371,27 +420,28 @@ const getCCLInfoFn = async () => {
// 定义ECCN列表
const ECCNList = ref([
{
name: '第1位: 物项类别',
name: "第1位: 物项类别",
isClick: true,
description: 'ECCN的第一位是一个数字,它指明了受控物项所属的技术或行业类别,对于快速定位物项在《商业管制清单》中的位置至关重要',
key: 'wxlb' // 用于和后端对接的
description:
"ECCN的第一位是一个数字,它指明了受控物项所属的技术或行业类别,对于快速定位物项在《商业管制清单》中的位置至关重要",
key: "wxlb" // 用于和后端对接的
}
])
]);
const getCCL_ECCN_Type = async () => {
try {
const res = await getECCN();
if (res && res.code === 200) {
ECCNList.value = res.data;
console.log('getCCL_ECCN_Type', ECCNList.value)
console.log("getCCL_ECCN_Type", ECCNList.value);
// 为每个对象增加是否点击对象
ECCNList.value.forEach((item) => {
item.isClick = false
})
ECCNList.value.forEach(item => {
item.isClick = false;
});
// 默认点击第一个
ECCNList.value[0].isClick = true
ECCNList.value[0].isClick = true;
// 默认将第一个赋值给currentECCN
currentECCN.value = ECCNList.value[0]
currentECCN.value = ECCNList.value[0];
}
} catch (error) {
console.error("获取商业管制清单出口管制分类编码失败:", error);
......@@ -401,46 +451,47 @@ const getCCL_ECCN_Type = async () => {
// 表格数据
const tableData = ref([
{
categoryCode: '0',
categoryCode: "0",
categoryId: 1,
code: null,
description: null,
descriptionZh: null,
id: 1,
name: 'Nuclear Materials, Facilities and Equipment and Miscellaneous',
name: "Nuclear Materials, Facilities and Equipment and Miscellaneous",
nameZh: "核材料、设备设施及其他类似物项"
}
])
]);
const currentECCN = ref({
name: '第1位: 物项类别',
name: "第1位: 物项类别",
isClick: true,
description: 'ECCN的第一位是一个数字,它指明了受控物项所属的技术或行业类别,对于快速定位物项在《商业管制清单》中的位置至关重要',
description:
"ECCN的第一位是一个数字,它指明了受控物项所属的技术或行业类别,对于快速定位物项在《商业管制清单》中的位置至关重要",
id: 1,
ranking: 1
})
});
/**
* 修改ECCN
*/
function changeECCN(item) {
ECCNList.value.forEach((i) => i.isClick = false)
item.isClick = true
currentECCN.value = item
ECCNList.value.forEach(i => (i.isClick = false));
item.isClick = true;
currentECCN.value = item;
}
// 监听当前的ECCN,更新获取列表数据
watch(
() => currentECCN.value,
async (newValue) => {
async newValue => {
// 调用接口更新table数据
const params = {
id: currentECCN.value.id
}
};
try {
const res = await getECCNList(params);
if (res && res.code === 200) {
tableData.value = res.data;
console.log('getECCNList', tableData.value)
console.log("getECCNList", tableData.value);
}
} catch (error) {
console.error("获取商业管制清单出口管制分类编码信息列表列表数据:", error);
......@@ -448,18 +499,19 @@ watch(
},
{ deep: true }
);
const sanTypeId = ref("");
onMounted(() => {
// 获取路由参数sanTypeId
sanTypeId.value = route.query.sanTypeId || "13";
console.log("商业管制清单介绍页面接收到的 sanTypeId:", sanTypeId.value);
// 获取商业管制清单基本信息
getCCLInfoFn();
// 获取商业管制清单的分类编码
getCCL_ECCN_Type()
getCCL_ECCN_Type();
// 获取商业管制清单发布机构
getPublishInfoFn();
// 获取商业管制清单更新历史
getSanctionUpdate();
});
</script>
......
......@@ -10,9 +10,7 @@
</div>
<div class="department">{{ headerTitle.department }}</div>
</div>
<div class="btn">
<img :src="icon01" alt />切换
</div>
<div class="btn"><img :src="icon01" alt />切换</div>
</div>
<div class="header-nav">
<div
......@@ -38,15 +36,16 @@
</template>
<script setup>
import { ref } from 'vue'
import { ref, onMounted } from "vue";
import { useRoute } from "vue-router";
import sanctionsOverview from "./components/sanctionsOverview/index.vue"
import sanctionsOverview from "./components/sanctionsOverview/index.vue";
// import dataStatistics from "./components/dataStatistics/index.vue"
// import deepMining from "./components/deepMining/index.vue"
// import impactAnalysis from "./components/impactAnalysis/index.vue"
import title from "./assets/title.png"
import icon01 from "./assets/icon01.png"
import title from "./assets/title.png";
import icon01 from "./assets/icon01.png";
import icon1 from "../assets/icons/icon1.png";
import icon1Active from "../assets/icons/icon1_active.png";
import icon5 from "../assets/icons/icon5.png";
......@@ -56,41 +55,45 @@ import icon2Active from "../assets/icons/icon2_active.png";
import icon3 from "../assets/icons/icon3.png";
import icon3Active from "../assets/icons/icon3_active.png";
const route = useRoute();
const sanTypeId = ref("");
onMounted(() => {
// 获取路由参数sanTypeId
sanTypeId.value = route.query.sanTypeId;
console.log("CommercialControlList 页面接收到的 sanTypeId:", sanTypeId.value);
});
const headerTitle = ref({
img: title,
title: "商业管制清单(CCL)",
titleEn: "Commercial Control List",
department: "美国商务部工业与安全局"
})
img: title,
title: "商业管制清单(CCL)",
titleEn: "Commercial Control List",
department: "美国商务部工业与安全局"
});
const activeIndex = ref(0)
const activeIndex = ref(0);
const headerNavList = ref([
{
img: icon1,
imgActive: icon1Active,
title: "制裁概况"
},
{
img: icon5,
imgActive: icon5Active,
title: "数据统计"
},
{
img: icon2,
imgActive: icon2Active,
title: "深度挖掘"
},
{
img: icon3,
imgActive: icon3Active,
title: "影响分析"
}
])
{
img: icon1,
imgActive: icon1Active,
title: "制裁概况"
},
{
img: icon5,
imgActive: icon5Active,
title: "数据统计"
},
{
img: icon2,
imgActive: icon2Active,
title: "深度挖掘"
},
{
img: icon3,
imgActive: icon3Active,
title: "影响分析"
}
]);
</script>
<style scoped lang="scss">
......
......@@ -178,8 +178,13 @@
<div class="rank-index" :class="'rank-' + (index + 1)">{{ index + 1 }}</div>
<div class="rank-name">{{ item.name }}</div>
<div class="rank-bar-bg">
<div class="rank-bar-fill"
:style="{ width: (item.value / maxRankValue) * 100 + '%', background: getBarColor(index) }"></div>
<div
class="rank-bar-fill"
:style="{
width: (item.value / maxRankValue) * 100 + '%',
background: getBarColor(index)
}"
></div>
</div>
<div class="rank-value">{{ item.value }}家</div>
</div>
......@@ -302,13 +307,22 @@ import * as echarts from "echarts";
import chinaJson from "../../../utils/China.json";
import ai from "./assets/ai.png";
import right from "./assets/right.png";
import { getTotalCount, getSanctionCountChange, getRegionCount, getTechDomainCount, getEntityTypeCount } from "@/api/exportControlV2.0";
import {
getTotalCount,
getSanctionCountChange,
getRegionCount,
getTechDomainCount,
getEntityTypeCount
} from "@/api/exportControlV2.0";
import { useRoute } from "vue-router";
const route = useRoute();
// 实体清单-数据统计-制裁实体类型分布情况
const typeData = ref([]);
const getTypeCountData = async () => {
// 参数
const param = {};
param.sanTypeId = sanTypeId.value;
if (typeTime.value !== "all") {
param.startDate = `${typeTime.value}-01-01`;
......@@ -330,14 +344,12 @@ const getTypeCountData = async () => {
}
};
// 实体清单-数据统计-制裁实体领域分布情况
const domainData = ref([]);
const getDomainCountData = async () => {
// 参数
const param = {};
param.sanTypeId = sanTypeId.value;
if (domainTime.value !== "all") {
param.startDate = `${domainTime.value}-01-01`;
......@@ -371,7 +383,7 @@ const maxRankValue = computed(() => {
const getRegionCountData = async () => {
// 参数
const param = {};
param.sanTypeId = sanTypeId.value;
if (regionTime.value !== "all") {
param.startDate = `${regionTime.value}-01-01`;
param.endDate = `${regionTime.value}-12-31`;
......@@ -396,14 +408,14 @@ const getRegionCountData = async () => {
}
};
// 实体清单-数据统计-制裁实体数量变化情况
const sanctionCountChange = ref([]);
// 获取实体清单-数据统计-制裁实体数量变化情况
const getSanctionCountChangeData = async () => {
// 参数
const param = {
countType: activeTab.value === "year" ? "year" : "record"
countType: activeTab.value === "year" ? "year" : "record",
sanTypeId: sanTypeId.value
};
try {
const res = await getSanctionCountChange(param);
......@@ -419,7 +431,7 @@ const totalCount = ref(0);
// 获取实体清单-数据统计-总量统计
const getTotalCountData = async () => {
try {
const res = await getTotalCount();
const res = await getTotalCount(sanTypeId.value);
totalCount.value = res.data || 0;
} catch (error) {
console.error("获取实体清单-数据统计-总量统计失败:", error);
......@@ -438,9 +450,7 @@ const typeTime = ref("all");
const currentYear = new Date().getFullYear();
const timeOptions = [
{ label: "全部时间", value: "all" },
];
const timeOptions = [{ label: "全部时间", value: "all" }];
for (let i = 0; i <= 10; i++) {
const year = currentYear - i;
......@@ -749,11 +759,13 @@ const updateTypeChart = () => {
chart = echarts.init(typeChartRef.value);
}
let data = typeData.value.length ? [...typeData.value] : [
{ value: 50, name: "企业" },
{ value: 32, name: "高校" },
{ value: 32, name: "科研院所" }
];
let data = typeData.value.length
? [...typeData.value]
: [
{ value: 50, name: "企业" },
{ value: 32, name: "高校" },
{ value: 32, name: "科研院所" }
];
// 2. 聚合逻辑:保留前5项,其余合并为“其他”
data.sort((a, b) => b.value - a.value);
......@@ -873,7 +885,10 @@ const initTypeChart = () => {
updateTypeChart();
};
const sanTypeId = ref("");
onMounted(() => {
sanTypeId.value = route.query.sanTypeId || "";
console.log("数据统计页面接收到的 sanTypeId:", sanTypeId.value);
// initSanctionCountChart();
initMapChart();
initDomainChart();
......
<template>
<div class="deep-mining">
<div class="side-nav">
<div v-for="(item, index) in activeTab" :key="index" class="tab-item" :class="{ active: index === activeIndex }"
@click="activeIndex = index">
<div
v-for="(item, index) in activeTab"
:key="index"
class="tab-item"
:class="{ active: index === activeIndex }"
@click="activeIndex = index"
>
{{ item }}
<span v-if="index === activeIndex" class="arrow"></span>
</div>
......@@ -12,9 +17,17 @@
<AnalysisBox title="选择制裁">
<div class="left-main">
<div class="date-picker-box">
<el-date-picker v-model="dateRange" type="daterange" range-separator="--" start-placeholder="开始日期"
end-placeholder="结束日期" value-format="YYYY-MM-DD" style="width: 100%" :clearable="false"
@change="handleDateChange" />
<el-date-picker
v-model="dateRange"
type="daterange"
range-separator="--"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
style="width: 100%"
:clearable="false"
@change="handleDateChange"
/>
</div>
<div class="list-header">
<div class="count">{{ sanctionList.length }}次制裁</div>
......@@ -29,8 +42,13 @@
</div> -->
</div>
<div class="list-content" v-loading="loading">
<div class="list-item" v-for="item in sanctionList" :key="item.id"
:class="{ active: currentSanctionId === item.id }" @click="handleSanctionSelect(item.id)">
<div
class="list-item"
v-for="item in sanctionList"
:key="item.id"
:class="{ active: currentSanctionId === item.id }"
@click="handleSanctionSelect(item.id)"
>
<div class="item-left">{{ item.date }}-{{ item.title }}</div>
<div class="item-right">{{ item.count }}{{ item.unit }}</div>
</div>
......@@ -41,8 +59,17 @@
<div class="right">
<AnalysisBox title="制裁产业链时序图">
<template #header-btn>
<el-select v-model="selectedIndustryId" placeholder="请选择" class="industry-select"
@change="() => { getFishboneData(); getCnEntityOnChainData(); }">
<el-select
v-model="selectedIndustryId"
placeholder="请选择"
class="industry-select"
@change="
() => {
getFishboneData();
getCnEntityOnChainData();
}
"
>
<el-option v-for="item in industryList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</template>
......@@ -63,29 +90,44 @@
<div class="fishbone" ref="fishboneRef" v-if="fishboneDataList.length > 0">
<div class="main-line" :style="{ width: fishboneDataList.length * 200 + 300 + 'px' }">
<!-- 主轴上的标签 -->
<div class="main-line-text" v-for="(item, index) in mainLineLabels" :key="'label-' + index"
<div
class="main-line-text"
v-for="(item, index) in mainLineLabels"
:key="'label-' + index"
:class="{
'blue-theme': index < 2,
'green-theme': index >= 2 && index < 4,
'purple-theme': index >= 4
}" :style="{ left: index * 200 + 220 + 'px' }">
}"
:style="{ left: index * 200 + 220 + 'px' }"
>
{{ item }}
</div>
</div>
<!-- 奇数索引的数据组放在上方 -->
<div v-for="(causeGroup, groupIndex) in getOddGroups(fishboneDataList)" :key="'top-' + groupIndex"
:class="getTopBoneClass(groupIndex)" :style="{ left: groupIndex * 400 + 420 + 'px' }">
<div
v-for="(causeGroup, groupIndex) in getOddGroups(fishboneDataList)"
:key="'top-' + groupIndex"
:class="getTopBoneClass(groupIndex)"
:style="{ left: groupIndex * 400 + 420 + 'px' }"
>
<div class="left-bone">
<div class="left-bone-item" v-for="(item, index) in getLeftItems(causeGroup.causes)"
:key="'left-' + index">
<div
class="left-bone-item"
v-for="(item, index) in getLeftItems(causeGroup.causes)"
:key="'left-' + index"
>
<img :src="defaultTitle || item.picture" alt="" class="company-icon" />
<div class="text" :title="item.name">{{ item.name }}</div>
<div class="line"></div>
</div>
</div>
<div class="right-bone">
<div class="right-bone-item" v-for="(item, index) in getRightItems(causeGroup.causes)"
:key="'right-' + index">
<div
class="right-bone-item"
v-for="(item, index) in getRightItems(causeGroup.causes)"
:key="'right-' + index"
>
<div class="line"></div>
<img :src="defaultTitle || item.picture" alt="" class="company-icon" />
<div class="text" :title="item.name">{{ item.name }}</div>
......@@ -94,20 +136,29 @@
</div>
<!-- 偶数索引的数据组放在下方 -->
<div v-for="(causeGroup, groupIndex) in getEvenGroups(fishboneDataList)"
:key="'bottom-' + groupIndex" :class="getBottomBoneClass(groupIndex)"
:style="{ left: groupIndex * 400 + 220 + 'px' }">
<div
v-for="(causeGroup, groupIndex) in getEvenGroups(fishboneDataList)"
:key="'bottom-' + groupIndex"
:class="getBottomBoneClass(groupIndex)"
:style="{ left: groupIndex * 400 + 220 + 'px' }"
>
<div class="left-bone">
<div class="left-bone-item" v-for="(item, index) in getLeftItems(causeGroup.causes)"
:key="'left-bottom-' + index">
<div
class="left-bone-item"
v-for="(item, index) in getLeftItems(causeGroup.causes)"
:key="'left-bottom-' + index"
>
<img :src="defaultTitle || item.picture" alt="" class="company-icon" />
<div class="text" :title="item.name">{{ item.name }}</div>
<div class="line"></div>
</div>
</div>
<div class="right-bone">
<div class="right-bone-item" v-for="(item, index) in getRightItems(causeGroup.causes)"
:key="'right-bottom-' + index">
<div
class="right-bone-item"
v-for="(item, index) in getRightItems(causeGroup.causes)"
:key="'right-bottom-' + index"
>
<div class="line"></div>
<img :src="defaultTitle || item.picture" alt="" class="company-icon" />
<div class="text" :title="item.name">{{ item.name }}</div>
......@@ -115,8 +166,16 @@
</div>
</div>
</div>
<div v-else
style="display: flex; justify-content: center; align-items: center; height: 200px; width: 100%">
<div
v-else
style="
display: flex;
justify-content: center;
align-items: center;
height: 200px;
width: 100%;
"
>
<el-empty description="暂无相关数据" />
</div>
</div>
......@@ -130,9 +189,11 @@
</div>
<div class="text">
{{
`中国企业${cnEntityOnChainData.upstreamInternalCount ||
0}家(${formatRate(cnEntityOnChainData.upstreamInternalRate)}%),受制裁${cnEntityOnChainData.upstreamEntityCount
|| 0}家(${formatRate(cnEntityOnChainData.upstreamEntityRate)}%)`
`中国企业${cnEntityOnChainData.upstreamInternalCount || 0}家(${formatRate(
cnEntityOnChainData.upstreamInternalRate
)}%),受制裁${cnEntityOnChainData.upstreamEntityCount || 0}家(${formatRate(
cnEntityOnChainData.upstreamEntityRate
)}%)`
}}
</div>
</div>
......@@ -145,9 +206,11 @@
</div>
<div class="text">
{{
`中国企业${cnEntityOnChainData.midstreamInternalCount ||
0}家(${formatRate(cnEntityOnChainData.midstreamInternalRate)}%),受制裁${cnEntityOnChainData.midstreamEntityCount
|| 0}家(${formatRate(cnEntityOnChainData.midstreamEntityRate)}%)`
`中国企业${cnEntityOnChainData.midstreamInternalCount || 0}家(${formatRate(
cnEntityOnChainData.midstreamInternalRate
)}%),受制裁${cnEntityOnChainData.midstreamEntityCount || 0}家(${formatRate(
cnEntityOnChainData.midstreamEntityRate
)}%)`
}}
</div>
</div>
......@@ -160,9 +223,11 @@
</div>
<div class="text">
{{
`中国企业${cnEntityOnChainData.downstreamInternalCount ||
0}家(${formatRate(cnEntityOnChainData.downstreamInternalRate)}%),受制裁${cnEntityOnChainData.downstreamEntityCount
|| 0}家(${formatRate(cnEntityOnChainData.downstreamEntityRate)}%)`
`中国企业${cnEntityOnChainData.downstreamInternalCount || 0}家(${formatRate(
cnEntityOnChainData.downstreamInternalRate
)}%),受制裁${cnEntityOnChainData.downstreamEntityCount || 0}家(${formatRate(
cnEntityOnChainData.downstreamEntityRate
)}%)`
}}
</div>
</div>
......@@ -181,14 +246,22 @@
import { ref, onMounted, nextTick } from "vue";
import { ArrowLeft, ArrowRight } from "@element-plus/icons-vue";
import defaultTitle from "../../assets/default-icon2.png";
import { getDeepMiningSelect, getDeepMiningIndustry, getDeepMiningIndustryFishbone, getDeepMiningIndustryEntity } from "@/api/exportControlV2.0";
import {
getDeepMiningSelect,
getDeepMiningIndustry,
getDeepMiningIndustryFishbone,
getDeepMiningIndustryEntity
} from "@/api/exportControlV2.0";
import { useRoute } from "vue-router";
const route = useRoute();
// 实体清单-深度挖掘-产业链中国企业实体信息查询
const getCnEntityOnChainData = async () => {
const currentSanction = sanctionList.value.find(item => item.id === currentSanctionId.value);
const date = currentSanction ? currentSanction.date : '';
const date = currentSanction ? currentSanction.date : "";
// 确保 date 格式正确
const formattedDate = date && date.includes('年') ? date.replace('年', '-').replace('月', '-').replace('日', '') : date;
const formattedDate = date && date.includes("年") ? date.replace("年", "-").replace("月", "-").replace("日", "") : date;
const params = {
date: formattedDate
......@@ -207,17 +280,15 @@ const getCnEntityOnChainData = async () => {
console.error("获取产业链中国企业实体信息失败:", error);
cnEntityOnChainData.value = {};
}
}
};
// 实体清单-深度挖掘-产业链鱼骨图信息
const fishboneDataList = ref([]);
const getFishboneData = async () => {
const currentSanction = sanctionList.value.find(item => item.id === currentSanctionId.value);
const date = currentSanction ? currentSanction.date : '';
const date = currentSanction ? currentSanction.date : "";
// 确保 date 格式正确
const formattedDate = date && date.includes('年') ? date.replace('年', '-').replace('月', '-').replace('日', '') : date;
const formattedDate = date && date.includes("年") ? date.replace("年", "-").replace("月", "-").replace("日", "") : date;
const params = {
date: formattedDate
......@@ -230,14 +301,13 @@ const getFishboneData = async () => {
if (res.code === 200 && res.data && res.data.causes && res.data.causes.length > 0) {
const rootCauses = res.data.causes;
if (rootCauses.length > 0 && rootCauses[0].causes) {
fishboneDataList.value = rootCauses.map(group => {
return {
causes: group.causes || []
};
});
mainLineLabels.value = rootCauses.map(group => group.text || '');
mainLineLabels.value = rootCauses.map(group => group.text || "");
} else {
fishboneDataList.value = [];
mainLineLabels.value = [];
......@@ -250,9 +320,7 @@ const getFishboneData = async () => {
console.error("获取产业链鱼骨图数据失败:", error);
fishboneDataList.value = [];
}
}
};
// 实体清单-深度挖掘-产业链列表信息
const industryList = ref([]);
......@@ -274,30 +342,25 @@ const getIndustryList = async () => {
industryList.value = [];
selectedIndustryId.value = null;
}
}
};
// 获取选择制裁
const loading = ref(false);
const currentPage = ref(1);
const pageSize = ref(10000);
const pageSize = ref(100);
const total = ref(0);
const totalPage = ref(0);
const getDeepMiningSelectData = async () => {
loading.value = true;
const params = {
startDate: dateRange.value && dateRange.value[0] ? dateRange.value[0] : '',
endDate: dateRange.value && dateRange.value[1] ? dateRange.value[1] : '',
typeName: "实体清单",
startDate: dateRange.value && dateRange.value[0] ? dateRange.value[0] : "",
endDate: dateRange.value && dateRange.value[1] ? dateRange.value[1] : "",
// typeName: "实体清单",
isCn: false,
pageNum: currentPage.value,
pageSize: pageSize.value
pageSize: pageSize.value,
sanTypeIds: [Number(sanTypeId.value)] || 1 // 实体清单固定1
};
try {
const res = await getDeepMiningSelect(params);
......@@ -307,7 +370,7 @@ const getDeepMiningSelectData = async () => {
date: item.postDate,
title: item.name,
count: item.cnEntityCount,
unit: '家中国实体', // 接口未返回单位,暂时固定
unit: "家中国实体", // 接口未返回单位,暂时固定
summary: item.summary, // 保留额外信息备用
techDomainList: item.techDomainList // 保留额外信息备用
}));
......@@ -326,7 +389,7 @@ const getDeepMiningSelectData = async () => {
} finally {
loading.value = false;
}
}
};
// 日期选择变化
const handleDateChange = () => {
......@@ -335,14 +398,14 @@ const handleDateChange = () => {
};
// 翻页
const handlePageChange = (page) => {
const handlePageChange = page => {
if (page < 1 || page > totalPage.value) return;
currentPage.value = page;
getDeepMiningSelectData();
};
// 列表项点击事件
const handleSanctionSelect = (id) => {
const handleSanctionSelect = id => {
currentSanctionId.value = id;
getFishboneData();
getCnEntityOnChainData();
......@@ -366,13 +429,7 @@ const currentSanctionId = ref(5);
const cnEntityOnChainData = ref({});
const mainLineLabels = ref([
"关键原材料", "电池材料", "电子元器件", "动力电池", "电子控制系统", "动力电池"
]);
const mainLineLabels = ref(["关键原材料", "电池材料", "电子元器件", "动力电池", "电子控制系统", "动力电池"]);
// 获取奇数索引的数据组(放在上方)
const getOddGroups = data => {
......@@ -409,12 +466,15 @@ const getRightItems = items => {
};
// 格式化比率
const formatRate = (rate) => {
if (rate === undefined || rate === null) return '0.00';
const formatRate = rate => {
if (rate === undefined || rate === null) return "0.00";
return (rate * 100).toFixed(2);
};
const sanTypeId = ref("");
onMounted(() => {
// 获取路由参数中的sanTypeId
sanTypeId.value = route.query.sanTypeId || "";
// 获取选择制裁
getDeepMiningSelectData();
// 获取产业链信息
......@@ -730,7 +790,7 @@ onMounted(() => {
// 虚线
&::after {
content: '';
content: "";
position: absolute;
top: 0;
left: 0;
......@@ -744,7 +804,7 @@ onMounted(() => {
position: absolute;
// top: -14px;
font-size: 16px;
color: #055FC2;
color: #055fc2;
font-weight: bold;
background-color: #f7f8f9;
padding: 0 10px;
......@@ -1235,7 +1295,6 @@ onMounted(() => {
}
}
.industry-select {
width: 160px;
height: 28px;
......
......@@ -75,9 +75,17 @@
<AnalysisBox title="实体清单更新历史" :showAllBtn="false">
<template #header-btn>
<div class="filters">
<el-select v-model="selectedDomain" placeholder="Select"
style="width: 150px; height: 32px; margin-right: 16px">
<el-option v-for="item in domainOptions" :key="item.value" :label="item.label" :value="item.value" />
<el-select
v-model="selectedDomain"
placeholder="Select"
style="width: 150px; height: 32px; margin-right: 16px"
>
<el-option
v-for="item in domainOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-checkbox v-model="onlyChina">只看涉华动态</el-checkbox>
</div>
......@@ -91,8 +99,13 @@
<img :src="item.icon || title" alt="" />
<div class="main">
<div class="main-title" @click="handleClick(item)">{{ item.name }}</div>
<el-tooltip effect="dark" :content="item.summary" popper-class="common-prompt-popper" placement="top"
:show-after="500">
<el-tooltip
effect="dark"
:content="item.summary"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="main-desc">{{ item.summary }}</div>
</el-tooltip>
<div class="tag-box">
......@@ -107,8 +120,14 @@
</div>
<div class="left-footer">
<div class="total-count"> {{ totalAll }} </div>
<el-pagination v-model:current-page="currentPageAll" :page-size="pageSizeAll" :total="totalAll"
layout="prev, pager, next" background @current-change="handlePageChangeAll" />
<el-pagination
v-model:current-page="currentPageAll"
:page-size="pageSizeAll"
:total="totalAll"
layout="prev, pager, next"
background
@current-change="handlePageChangeAll"
/>
</div>
</AnalysisBox>
</div>
......@@ -130,8 +149,12 @@
<span>关键人物</span>
</div>
<div class="key-person-list">
<div class="person-item" v-for="(item, index) in publishInfo.personList" :key="index"
@click="handlePerClick(item)">
<div
class="person-item"
v-for="(item, index) in publishInfo.personList"
:key="index"
@click="handlePerClick(item)"
>
<img :src="item.imageUrl" alt="" />
<div class="person-info">
<CommonPrompt :content="item.name">
......@@ -183,7 +206,9 @@ import icon02 from "../../assets/icon02.png";
import { ArrowDown } from "@element-plus/icons-vue";
import CommonPrompt from "../../../../../commonPrompt/index.vue";
import { getEntityInfo, getPublishInfo, getPublishOrgInfo, getEntityUpdateInfo } from "@/api/exportControlV2.0.js";
import { useRoute } from "vue-router";
const route = useRoute();
// 处理点击发布机构的方法
const handleClickOrg = item => {
// console.log("点击了发布机构:", item);
......@@ -275,9 +300,10 @@ const getSanctionUpdate = async () => {
const data = {
isCn: onlyChina.value,
techDomainIds: selectedDomain.value ? [selectedDomain.value] : [],
typeName: "实体清单",
// typeName: "实体清单",
pageNum: currentPageAll.value,
pageSize: pageSizeAll.value
pageSize: pageSizeAll.value,
sanTypeIds: [sanTypeId.value] || ["1"] // 实体清单固定1
};
try {
const res = await getEntityUpdateInfo(data);
......@@ -324,7 +350,7 @@ const handlePageChangeAll = val => {
const publishInfo = ref({});
const getPublishInfoFn = async () => {
const params = {
sanTypeId: 1 // 实体清单固定1
sanTypeId: sanTypeId.value || 1 // 实体清单固定1
};
try {
const res = await getPublishInfo(params);
......@@ -379,22 +405,25 @@ const handleLoadMoreDynamic = () => {
// 获取实体清单基本信息
const entityInfo = ref({});
const emit = defineEmits(['update-entity-info']);
const getEntityInfoFn = async () => {
const emit = defineEmits(["update-entity-info"]);
const getEntityInfoFn = async id => {
try {
const res = await getEntityInfo("el");
const res = await getEntityInfo(id);
if (res && res.code === 200) {
entityInfo.value = res.data;
emit('update-entity-info', res.data);
console.log("获取实体清单基本信息成功:", res.data);
emit("update-entity-info", res.data);
}
} catch (error) {
console.error("获取实体清单基本信息失败:", error);
}
};
const sanTypeId = ref("");
onMounted(() => {
sanTypeId.value = route.query.sanTypeId;
// 获取实体清单基本信息
getEntityInfoFn();
getEntityInfoFn(sanTypeId.value);
// 获取实体清单发布机构
getPublishInfoFn();
// 获取实体清单更新历史
......
......@@ -13,27 +13,47 @@
<div class="text">科技领域</div>
</div>
<div class="checkbox-group">
<el-checkbox v-for="(item, index) in techFields" :key="index" v-model="item.checked" :label="item.label"
@change="handleFilterChange(item, techFields, 'tech')" />
<el-checkbox
v-for="(item, index) in techFields"
:key="index"
v-model="item.checked"
:label="item.label"
@change="handleFilterChange(item, techFields, 'tech')"
/>
</div>
<div class="title">
<div class="box"></div>
<div class="text">实体类型</div>
</div>
<div class="checkbox-group">
<el-checkbox v-for="(item, index) in entityTypes" :key="index" v-model="item.checked" :label="item.label"
@change="handleFilterChange(item, entityTypes, 'type')" />
<el-checkbox
v-for="(item, index) in entityTypes"
:key="index"
v-model="item.checked"
:label="item.label"
@change="handleFilterChange(item, entityTypes, 'type')"
/>
</div>
<div class="title">
<div class="box"></div>
<div class="text">制裁时间</div>
</div>
<div class="checkbox-group">
<el-checkbox v-for="(item, index) in sanctionTimes" :key="index" v-model="item.checked" :label="item.label"
@change="handleFilterChange(item, sanctionTimes, 'time')" />
<el-checkbox
v-for="(item, index) in sanctionTimes"
:key="index"
v-model="item.checked"
:label="item.label"
@change="handleFilterChange(item, sanctionTimes, 'time')"
/>
<div v-if="sanctionTimes.find(i => i.value === 'custom' && i.checked)" class="custom-date-picker">
<el-date-picker v-model="customDateRange" type="daterange" range-separator="-" start-placeholder="开始日期"
end-placeholder="结束日期" />
<el-date-picker
v-model="customDateRange"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
</div>
</div>
</div>
......@@ -106,33 +126,47 @@
<template #header-btn>
<div class="stats">
<div class="dot"></div>
<div class="count-text"><span class="highlight">{{ ruleCount.totalCount }}</span></div>
<div class="rule-text">(50%规则涉及<span class="highlight">{{ ruleCount.ruleCount }}</span>家)</div>
<div class="count-text">
<span class="highlight">{{ ruleCount.totalCount }}</span>
</div>
<div class="rule-text">
(50%规则涉及<span class="highlight">{{ ruleCount.ruleCount }}</span
>家)
</div>
</div>
</template>
<div class="right-table">
<el-table :data="entityRows" table-layout="fixed" :row-class-name="tableRowClassName"
:header-cell-style="{ background: '#fff' }">
<el-table
:data="entityRows"
table-layout="fixed"
:row-class-name="tableRowClassName"
:header-cell-style="{ background: '#fff' }"
>
<el-table-column label="实体名称" min-width="200">
<template #default="{ row }">
<div class="entity-name-cell" @click="handleCompClick(row)">
<el-image v-if="row.img" class="avatar" :src="row.img" alt=""></el-image>
<div v-else class="avatar-undefined">
{{
(row.entityNameZh || row.entityName)?.match(
/[\u4e00-\u9fa5a-zA-Z0-9]/
)?.[0]
}}
{{ (row.entityNameZh || row.entityName)?.match(/[\u4e00-\u9fa5a-zA-Z0-9]/)?.[0] }}
</div>
<CommonPrompt :content="row.entityNameZh || row.entityName" style="flex: 1; overflow: hidden" />
<CommonPrompt
:content="row.entityNameZh || row.entityName"
style="flex: 1; overflow: hidden"
/>
</div>
</template>
</el-table-column>
<el-table-column label="涉及领域" min-width="150">
<template #default="{ row }">
<div class="domain-cell">
<el-tag v-for="tag in row.techDomains" :key="tag" class="domain-tag" effect="plain"
:disable-transitions="true" :style="getTagStyle(tag)">
<el-tag
v-for="tag in row.techDomains"
:key="tag"
class="domain-tag"
effect="plain"
:disable-transitions="true"
:style="getTagStyle(tag)"
>
{{ tag }}
</el-tag>
</div>
......@@ -143,10 +177,11 @@
<template #default="{ row }">
<div class="rule-cell" v-if="row.ruleOrgCount > 0">
<div class="rule-text" :title="row.ruleOrgList?.[0]?.orgName || ''">
{{ row.ruleOrgList?.[0]?.orgName || '' }}...等
{{ row.ruleOrgList?.[0]?.orgName || "" }}...等
</div>
<el-link class="rule-link" type="primary" :underline="false" @click="handleRuleClick(row)">{{
row.ruleOrgCount }}家 ></el-link>
<el-link class="rule-link" type="primary" :underline="false" @click="handleRuleClick(row)"
>{{ row.ruleOrgCount }}家 ></el-link
>
</div>
</template>
</el-table-column>
......@@ -154,15 +189,26 @@
</div>
<div class="tight-footer">
<div class="total-text">共 {{ total }} 项</div>
<el-pagination :current-page="currentPage" v-model:page-size="pageSize" :total="total"
layout="prev, pager, next" prev-text="<" next-text=">" @current-change="handleCurrentChange" />
<el-pagination
:current-page="currentPage"
v-model:page-size="pageSize"
:total="total"
layout="prev, pager, next"
prev-text="<"
next-text=">"
@current-change="handleCurrentChange"
/>
</div>
</AnalysisBox>
</div>
</div>
</div>
<RuleSubsidiaryDialog v-model="ruleDialogVisible" :company-name="currentRuleCompany" :total-count="currentRuleCount"
:data-list="currentRuleList" />
<RuleSubsidiaryDialog
v-model="ruleDialogVisible"
:company-name="currentRuleCompany"
:total-count="currentRuleCount"
:data-list="currentRuleList"
/>
</template>
<script setup>
......@@ -171,15 +217,15 @@ import { useRouter } from "vue-router";
import { Search } from "@element-plus/icons-vue";
import defaultIcon from "../../../../../assets/icons/default-avatar.png";
import RuleSubsidiaryDialog from "./RuleSubsidiaryDialog.vue";
import { getExportControlList, get50PercentEntityCount } from "@/api/exportControlV2.0.js"
import CommonPrompt from '@/views/exportControl/commonPrompt/index.vue'
import { getExportControlList, get50PercentEntityCount } from "@/api/exportControlV2.0.js";
import CommonPrompt from "@/views/exportControl/commonPrompt/index.vue";
const router = useRouter();
// 跳转公司详情页
const handleCompClick = item => {
console.log("item", item);
window.sessionStorage.setItem('curTabName', item.entityNameZh || item.entityName)
window.sessionStorage.setItem("curTabName", item.entityNameZh || item.entityName);
const route = router.resolve({
name: "companyPages",
params: {
......@@ -199,7 +245,7 @@ const total = ref(0);
const entityRows = computed(() => mainList.value);
const handleCurrentChange = (val) => {
const handleCurrentChange = val => {
if (val === currentPage.value) return;
currentPage.value = val;
getExportControlListApi();
......@@ -275,7 +321,7 @@ const currentRuleCompany = ref("");
const currentRuleCount = ref(0);
const currentRuleList = ref([]);
const handleRuleClick = (row) => {
const handleRuleClick = row => {
currentRuleCompany.value = row.entityNameZh || row.entityName;
currentRuleCount.value = row.ruleOrgCount;
currentRuleList.value = row.ruleOrgList || [];
......@@ -285,11 +331,11 @@ const handleRuleClick = (row) => {
// 筛选逻辑处理
const handleFilterChange = (item, list, type) => {
// 如果点击的是"全部"
if (item.value === 'all') {
if (item.value === "all") {
if (item.checked) {
// 选中全部,取消其他所有
list.forEach(i => {
if (i.value !== 'all') i.checked = false;
if (i.value !== "all") i.checked = false;
});
} else {
// 取消全部(通常不允许全部取消,至少得选一个,这里如果取消全部,就默认为全部选中)
......@@ -299,17 +345,17 @@ const handleFilterChange = (item, list, type) => {
// 点击的是具体项
if (item.checked) {
// 选中具体项,取消"全部"
const allItem = list.find(i => i.value === 'all');
const allItem = list.find(i => i.value === "all");
if (allItem) allItem.checked = false;
// 特殊处理制裁时间的自定义和其他年份互斥
if (type === 'time') {
if (item.value === 'custom') {
if (type === "time") {
if (item.value === "custom") {
list.forEach(i => {
if (i.value !== 'custom' && i.value !== 'all') i.checked = false;
if (i.value !== "custom" && i.value !== "all") i.checked = false;
});
} else {
const customItem = list.find(i => i.value === 'custom');
const customItem = list.find(i => i.value === "custom");
if (customItem) customItem.checked = false;
}
}
......@@ -317,7 +363,7 @@ const handleFilterChange = (item, list, type) => {
// 取消具体项,检查是否还有选中的
const anyChecked = list.some(i => i.checked);
if (!anyChecked) {
const allItem = list.find(i => i.value === 'all');
const allItem = list.find(i => i.value === "all");
if (allItem) allItem.checked = true;
}
}
......@@ -337,50 +383,54 @@ let abortController = null;
const getExportControlListApi = async () => {
// 取消上一轮未完成的请求
if (abortController) {
try { abortController.abort(); } catch { }
try {
abortController.abort();
} catch {}
}
abortController = new AbortController();
isFetching.value = true;
// 处理科技领域筛选
let techDomains = [];
const allTech = techFields.value.find(item => item.value === 'all');
const allTech = techFields.value.find(item => item.value === "all");
if (!allTech || !allTech.checked) {
techDomains = techFields.value
.filter(item => item.checked && item.value !== 'all')
.map(item => item.value);
techDomains = techFields.value.filter(item => item.checked && item.value !== "all").map(item => item.value);
}
// 处理实体类型筛选
let typeIds = [];
const allType = entityTypes.value.find(item => item.value === 'all');
const allType = entityTypes.value.find(item => item.value === "all");
if (!allType || !allType.checked) {
typeIds = entityTypes.value
.filter(item => item.checked && item.value !== 'all')
.map(item => Number(item.value));
typeIds = entityTypes.value.filter(item => item.checked && item.value !== "all").map(item => Number(item.value));
}
// 处理制裁时间筛选
let years = [];
let startDate = undefined;
let endDate = undefined;
const allTime = sanctionTimes.value.find(item => item.value === 'all');
const allTime = sanctionTimes.value.find(item => item.value === "all");
if (!allTime || !allTime.checked) {
years = sanctionTimes.value
.filter(item => item.checked && item.value !== 'all' && item.value !== 'custom')
.filter(item => item.checked && item.value !== "all" && item.value !== "custom")
.map(item => Number(item.value));
const customTime = sanctionTimes.value.find(item => item.value === 'custom');
const customTime = sanctionTimes.value.find(item => item.value === "custom");
if (customTime && customTime.checked && customDateRange.value && customDateRange.value.length === 2) {
const start = new Date(customDateRange.value[0]);
const end = new Date(customDateRange.value[1]);
startDate = `${start.getFullYear()}-${String(start.getMonth() + 1).padStart(2, '0')}-${String(start.getDate()).padStart(2, '0')}`;
endDate = `${end.getFullYear()}-${String(end.getMonth() + 1).padStart(2, '0')}-${String(end.getDate()).padStart(2, '0')}`;
startDate = `${start.getFullYear()}-${String(start.getMonth() + 1).padStart(2, "0")}-${String(
start.getDate()
).padStart(2, "0")}`;
endDate = `${end.getFullYear()}-${String(end.getMonth() + 1).padStart(2, "0")}-${String(end.getDate()).padStart(
2,
"0"
)}`;
}
}
const data = {
typeName: "实体清单",
// typeName: "实体清单",
sanTypeId: sanTypeId.value || 1,
isCn: onlyChina.value,
techDomains: techDomains.length > 0 ? techDomains : undefined,
entityTypes: typeIds.length > 0 ? typeIds : undefined,
......@@ -404,14 +454,14 @@ const getExportControlListApi = async () => {
total.value = res.data.totalElements;
}
} catch (error) {
if (!error || (error.code !== 'ERR_CANCELED' && error.name !== 'CanceledError' && error.name !== 'AbortError')) {
if (!error || (error.code !== "ERR_CANCELED" && error.name !== "CanceledError" && error.name !== "AbortError")) {
console.error(error);
}
} finally {
isFetching.value = false;
abortController = null;
}
}
};
watch(onlyChina, () => {
currentPage.value = 1;
......@@ -428,13 +478,14 @@ watch(searchKeyword, () => {
getExportControlListApi();
}, 300);
});
const sanTypeId = ref("");
onMounted(() => {
sanTypeId.value = router.currentRoute.value.query.sanTypeId || "1";
getExportControlListApi();
});
watch(customDateRange, () => {
if (sanctionTimes.value.find(item => item.value === 'custom' && item.checked)) {
if (sanctionTimes.value.find(item => item.value === "custom" && item.checked)) {
currentPage.value = 1;
getExportControlListApi();
}
......@@ -795,40 +846,40 @@ watch(customDateRange, () => {
.total-text {
font-size: 14px;
font-weight: 400;
color: #5F656C;
color: #5f656c;
font-family: "Microsoft YaHei";
}
:deep(.el-pagination) {
--el-pagination-button-bg-color: #fff;
--el-pagination-hover-color: #0E78F1;
--el-pagination-hover-color: #0e78f1;
--el-pagination-font-size: 14px;
.el-pager li {
border: 1px solid #DCDFE6;
border: 1px solid #dcdfe6;
border-radius: 4px;
margin: 0 4px;
font-weight: 400;
color: #5F656C;
color: #5f656c;
min-width: 32px;
height: 32px;
line-height: 30px;
&.is-active {
background-color: #0E78F1;
background-color: #0e78f1;
color: #fff;
border-color: #0E78F1;
border-color: #0e78f1;
}
&:hover:not(.is-active) {
color: #0E78F1;
border-color: #0E78F1;
color: #0e78f1;
border-color: #0e78f1;
}
}
.btn-prev,
.btn-next {
border: 1px solid #DCDFE6;
border: 1px solid #dcdfe6;
border-radius: 4px;
padding: 0;
margin: 0 4px;
......@@ -838,13 +889,13 @@ watch(customDateRange, () => {
text-align: center;
&:hover {
color: #0E78F1;
border-color: #0E78F1;
color: #0e78f1;
border-color: #0e78f1;
}
&[disabled] {
border-color: #E4E7ED;
color: #C0C4CC;
border-color: #e4e7ed;
color: #c0c4cc;
}
}
}
......
<template>
<div class="sanctions-overview">
<div class="side-nav">
<div v-for="(item, index) in activeTab" :key="index" class="tab-item" :class="{'active': index === activeIndex}" @click="activeIndex = index">
{{item}}
<span v-if="index === activeIndex" class="arrow"></span>
</div>
</div>
<div class="content-box">
<introductionPage v-if="activeIndex === 0" @update-entity-info="(data) => $emit('update-entity-info', data)"></introductionPage>
<listPage v-if="activeIndex === 1"></listPage>
</div>
</div>
<div class="sanctions-overview">
<div class="side-nav">
<div
v-for="(item, index) in activeTab"
:key="index"
class="tab-item"
:class="{ active: index === activeIndex }"
@click="activeIndex = index"
>
{{ item }}
<span v-if="index === activeIndex" class="arrow"></span>
</div>
</div>
<div class="content-box">
<introductionPage
v-show="activeIndex === 1"
@update-entity-info="data => $emit('update-entity-info', data)"
></introductionPage>
<listPage v-show="activeIndex === 0"></listPage>
</div>
</div>
</template>
<script setup>
import { ref, defineEmits } from 'vue'
import introductionPage from "./components/introductionPage/index.vue"
import listPage from "./components/listPage/index.vue"
const emit = defineEmits(['update-entity-info'])
const activeTab = ref(["实体清单简介", "实体清单列表"])
const activeIndex = ref(0)
import { ref, defineEmits } from "vue";
import introductionPage from "./components/introductionPage/index.vue";
import listPage from "./components/listPage/index.vue";
const emit = defineEmits(["update-entity-info"]);
const activeTab = ref(["实体清单列表", "实体清单简介"]);
const activeIndex = ref(0);
</script>
<style scoped lang="scss">
*{
margin: 0;
padding: 0;
* {
margin: 0;
padding: 0;
}
.sanctions-overview{
width: 1601px;
margin: 0 auto;
position: relative;
// min-height: 800px;
.side-nav {
position: absolute;
top: 27px;
right: 100%;
margin-right: 12px;
display: flex;
flex-direction: column;
gap: 16px;
.tab-item {
cursor: pointer;
padding: 4px 20px;
border-radius: 22px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(95, 101, 108);
white-space: nowrap;
display: flex;
align-items: center;
&.active {
background-color: rgb(5, 95, 194);
color: #fff;
.arrow {
display: inline-block;
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 6px solid #fff;
margin-left: 8px;
}
}
}
}
.content-box {
width: 100%;
}
.sanctions-overview {
width: 1601px;
margin: 0 auto;
position: relative;
// min-height: 800px;
.side-nav {
position: absolute;
top: 27px;
right: 100%;
margin-right: 12px;
display: flex;
flex-direction: column;
gap: 16px;
.tab-item {
cursor: pointer;
padding: 4px 20px;
border-radius: 22px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(95, 101, 108);
white-space: nowrap;
display: flex;
align-items: center;
&.active {
background-color: rgb(5, 95, 194);
color: #fff;
.arrow {
display: inline-block;
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 6px solid #fff;
margin-left: 8px;
}
}
}
}
.content-box {
width: 100%;
}
}
</style>
<template>
<div class="entity-list">
<div class="header">
<div class="header-title">
<img :src="headerTitle.img" alt="">
<div>
<div class="title">
{{ headerTitle.title }}
<span>{{ headerTitle.titleEn }}</span>
</div>
<div class="department">
{{ headerTitle.department }}
</div>
</div>
<div class="btn">
<img :src="icon01" alt="">切换
</div>
</div>
<div class="header-nav">
<div
class="nav-item"
v-for="(item, index) in headerNavList"
:key="index"
:class="{ active: activeIndex === index }"
@click="activeIndex = index"
>
<img :src="activeIndex === index ? item.imgActive : item.img" alt="">
<span>{{ item.title }}</span>
<div class="active-line" v-if="activeIndex === index"></div>
</div>
</div>
</div>
<div class="main">
<sanctions-overview v-if="activeIndex === 0" @update-entity-info="handleUpdateEntityInfo"></sanctions-overview>
<data-statistics v-if="activeIndex === 1"></data-statistics>
<deep-mining v-if="activeIndex === 2"></deep-mining>
<impact-analysis v-if="activeIndex === 3"></impact-analysis>
</div>
</div>
<div class="entity-list">
<div class="header">
<div class="header-title">
<img :src="headerTitle.img" alt="" />
<div>
<div class="title">
{{ headerTitle.title }}
<span>{{ headerTitle.titleEn }}</span>
</div>
<div class="department">
{{ headerTitle.department }}
</div>
</div>
<div class="btn"><img :src="icon01" alt="" />切换</div>
</div>
<div class="header-nav">
<div
class="nav-item"
v-for="(item, index) in headerNavList"
:key="index"
:class="{ active: activeIndex === index }"
@click="activeIndex = index"
>
<img :src="activeIndex === index ? item.imgActive : item.img" alt="" />
<span>{{ item.title }}</span>
<div class="active-line" v-if="activeIndex === index"></div>
</div>
</div>
</div>
<div class="main">
<sanctions-overview v-if="activeIndex === 0" @update-entity-info="handleUpdateEntityInfo"></sanctions-overview>
<data-statistics v-if="activeIndex === 1"></data-statistics>
<deep-mining v-if="activeIndex === 2"></deep-mining>
<impact-analysis v-if="activeIndex === 3"></impact-analysis>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { ref, onMounted } from "vue";
import { useRoute } from "vue-router";
import sanctionsOverview from "./components/sanctionsOverview/index.vue";
import dataStatistics from "./components/dataStatistics/index.vue";
......@@ -58,27 +57,34 @@ import icon2Active from "../assets/icons/icon2_active.png";
import icon3 from "../assets/icons/icon3.png";
import icon3Active from "../assets/icons/icon3_active.png";
const route = useRoute();
const headerTitle = ref({
// img: title,
// title: "实体清单",
// titleEn: "Entity List",
// department: "美国商务部工业与安全局"
})
// img: title,
// title: "实体清单",
// titleEn: "Entity List",
// department: "美国商务部工业与安全局"
});
const handleUpdateEntityInfo = (data) => {
if (data) {
headerTitle.value = {
...headerTitle.value,
title: data.name,
titleEn: data.originalName,
department: data.orgName,
departId: data.orgId,
img: data.orgLogoUrl || title
}
}
}
onMounted(() => {
// 获取路由参数id
const id = route.query.id;
console.log("EntityList 页面接收到的 id:", id);
});
const handleUpdateEntityInfo = data => {
console.log("更新实体清单基本信息:", data);
if (data) {
headerTitle.value = {
...headerTitle.value,
title: data.name,
titleEn: data.originalName,
department: data.orgName,
departId: data.orgId,
img: data.orgLogoUrl || title
};
}
};
const activeIndex = ref(0)
const activeIndex = ref(0);
const headerNavList = ref([
{
......
......@@ -137,15 +137,18 @@
<AnalysisBox title="制裁实体国家分布情况">
<div class="country-list">
<div class="list-item" v-for="(item, index) in countryDistribution" :key="index">
<img :src="flag" alt="" class="flag">
<img :src="flag" alt="" class="flag" />
<div class="country-name">{{ item.name }}</div>
<div class="progress-bar-container">
<div class="progress-bar" :style="{
width: item.width,
background: item.gradient
}"></div>
<div
class="progress-bar"
:style="{
width: item.width,
background: item.gradient
}"
></div>
</div>
<div class="count" :class="{ 'highlight': index === 0 }">{{ item.count }}</div>
<div class="count" :class="{ highlight: index === 0 }">{{ item.count }}</div>
</div>
</div>
<div class="bottom">
......@@ -170,9 +173,13 @@
<div class="rank-index" :class="'rank-' + (index + 1)">{{ index + 1 }}</div>
<div class="rank-name">{{ item.name }}</div>
<div class="rank-bar-bg">
<div class="rank-bar-fill"
:style="{ width: (maxRegionCount > 0 ? (item.count / maxRegionCount) * 100 : 0) + '%', background: getBarColor(index) }">
</div>
<div
class="rank-bar-fill"
:style="{
width: (maxRegionCount > 0 ? (item.count / maxRegionCount) * 100 : 0) + '%',
background: getBarColor(index)
}"
></div>
</div>
<div class="rank-value">{{ item.count }}</div>
</div>
......@@ -201,10 +208,18 @@ import * as echarts from "echarts";
import chinaJson from "../../../utils/China.json";
import ai from "./assets/ai.png";
import right from "./assets/right.png";
import flag from "../../assets/default-icon2.png"
import flag from "../../assets/default-icon2.png";
import { useRouter } from "vue-router";
import { getSingleSanctionTotalCount, getSingleSanctionDomainCount, getSingleSanctionEntityTypeCount, getSingleSanctionEntityCountryCount, getSingleSanctionEntityRegionCount } from "@/api/exportControlV2.0";
import {
getSingleSanctionTotalCount,
getSingleSanctionDomainCount,
getSingleSanctionEntityTypeCount,
getSingleSanctionEntityCountryCount,
getSingleSanctionEntityRegionCount
} from "@/api/exportControlV2.0";
import { useRoute } from "vue-router";
const route = useRoute();
// 单次制裁-数据统计-制裁实体地域分布情况
const regionDistribution = ref([]);
const maxRegionCount = ref(0);
......@@ -212,8 +227,8 @@ const maxRegionCount = ref(0);
const getRegionData = async () => {
if (!sanRecordId.value) return;
try {
const params = { sanRecordId: sanRecordId.value };
if (regionTime.value && regionTime.value !== 'all') {
const params = { sanRecordId: sanRecordId.value, sanTypeId: route.query.sanTypeId || "1" };
if (regionTime.value && regionTime.value !== "all") {
params.startDate = `${regionTime.value}-01-01`;
params.endDate = `${regionTime.value}-12-31`;
}
......@@ -226,9 +241,7 @@ const getRegionData = async () => {
} catch (error) {
console.log(error);
}
}
};
// 单次制裁-数据统计-制裁实体国家分布情况
const countryDistribution = ref([]);
......@@ -236,7 +249,7 @@ const countryDistribution = ref([]);
const getCountryCount = async () => {
if (!sanRecordId.value) return;
try {
const params = { sanRecordId: sanRecordId.value };
const params = { sanRecordId: sanRecordId.value, sanTypeId: sanTypeId.value };
const res = await getSingleSanctionEntityCountryCount(params);
if (res.code === 200) {
const rawData = res.data || [];
......@@ -245,7 +258,7 @@ const getCountryCount = async () => {
countryDistribution.value = rawData.map((item, index) => {
// 计算宽度,最大值对应 80%
const width = maxCount > 0 ? (item.count / maxCount) * 80 + '%' : '0%';
const width = maxCount > 0 ? (item.count / maxCount) * 80 + "%" : "0%";
// 根据索引分配渐变色
let gradient = "";
......@@ -267,9 +280,7 @@ const getCountryCount = async () => {
} catch (error) {
console.log(error);
}
}
};
// 单次制裁-数据统计-制裁实体类型分布情况
const entityTypeCount = ref([]);
......@@ -277,8 +288,8 @@ const entityTypeCount = ref([]);
const getEntityTypeCount = async () => {
if (!sanRecordId.value) return;
try {
const params = { sanRecordId: sanRecordId.value };
if (typeTime.value && typeTime.value !== 'all') {
const params = { sanRecordId: sanRecordId.value, sanTypeId: sanTypeId.value };
if (typeTime.value && typeTime.value !== "all") {
params.startDate = `${typeTime.value}-01-01`;
params.endDate = `${typeTime.value}-12-31`;
}
......@@ -290,10 +301,7 @@ const getEntityTypeCount = async () => {
} catch (error) {
console.log(error);
}
}
};
// 单次制裁-数据统计-制裁实体领域分布情况
const domainCount = ref([]);
......@@ -301,8 +309,8 @@ const domainCount = ref([]);
const getDomainCount = async () => {
if (!sanRecordId.value) return;
try {
const params = { sanRecordId: sanRecordId.value };
if (domainTime.value && domainTime.value !== 'all') {
const params = { sanRecordId: sanRecordId.value, sanTypeId: sanTypeId.value };
if (domainTime.value && domainTime.value !== "all") {
params.startDate = `${domainTime.value}-01-01`;
params.endDate = `${domainTime.value}-12-31`;
}
......@@ -314,8 +322,7 @@ const getDomainCount = async () => {
} catch (error) {
console.log(error);
}
}
};
// 单次制裁-数据统计-总量统计
const totalCount = ref({});
......@@ -323,22 +330,21 @@ const totalCount = ref({});
const getTotalCount = async () => {
if (!sanRecordId.value) return;
try {
const res = await getSingleSanctionTotalCount({ sanRecordId: sanRecordId.value });
const res = await getSingleSanctionTotalCount(route.query.sanTypeId);
if (res.code === 200) {
totalCount.value = res.data || {};
}
} catch (error) {
console.log(error);
}
}
};
const router = useRouter();
const sanRecordId = ref("")
const sanRecordId = ref("");
const getUrlParams = () => {
const urlParams = new URLSearchParams(window.location.search);
sanRecordId.value = urlParams.get("id") || ""
}
sanRecordId.value = urlParams.get("id") || "";
};
const regionTime = ref("all");
const domainTime = ref("all");
......@@ -355,11 +361,7 @@ watch(regionTime, () => {
getRegionData();
});
const timeOptions = [
{ label: "全部时间", value: "all" }
];
const timeOptions = [{ label: "全部时间", value: "all" }];
// 生成2000-2025年的选项
for (let i = 2025; i >= 2000; i--) {
timeOptions.push({ label: `${i}年`, value: `${i}` });
......@@ -640,8 +642,11 @@ const initTypeChart = () => {
chart.resize();
});
};
const sanTypeId = ref("");
onMounted(() => {
// 获取路由参数id
sanTypeId.value = route.query.sanTypeId;
console.log("页面接收到的 sanTypeId:", sanTypeId.value);
// 获取url参数
getUrlParams();
// 单次制裁-数据统计-总量统计-请求
......
<template>
<div class="sanctions-overview">
<div class="main">
<div class="left">
<div class="left-top">
<AnalysisBox title="基本信息" :showAllBtn="false">
<div class="left-top-title">
<div class="info-row">
<div class="label">发布机构:</div>
<div class="value link">
<img :src="title" alt="" class="icon">
<span @click="handleClickDp">{{ formattedData.postOrgName }} ></span>
</div>
</div>
<div class="info-row">
<div class="label">发布时间:</div>
<div class="value">{{ formattedData.postDate }}</div>
</div>
<div class="info-row">
<div class="label">生效时间:</div>
<div class="value">{{ formattedData.effectiveDate }}</div>
</div>
<div class="info-row">
<div class="label">发布文件:</div>
<div class="value">{{ formattedData.fileCode }}</div>
</div>
<div class="info-row">
<div class="label">案卷号:</div>
<div class="value">{{ formattedData.administrativeOrderId }}</div>
</div>
<div class="info-row">
<div class="label">发布人:</div>
<div class="value link">
<img :src="defaultTitle" alt="" class="icon avatar">
<span @click="handleClick">{{ formattedData.postPersonName }} ></span>
</div>
</div>
<div class="info-row">
<div class="label">制裁领域:</div>
<div class="value tags">
<span class="tag" v-for="(domain, index) in formattedData.domains" :key="index">{{ domain }}</span>
</div>
</div>
</div>
<div class="left-top-content">
<div class="content-title">制裁实体分布:</div>
<div class="distribution-list">
<div class="list-item" v-for="(item, index) in entityDistribution" :key="index">
<img :src="flag" alt="" class="flag">
<div class="country-name">{{ item.name }}</div>
<div class="progress-bar-container">
<div class="progress-bar" :style="{
width: item.width,
background: item.gradient
}"></div>
</div>
<div class="count" :class="{ 'highlight': index === 0 }">{{ item.count }}</div>
</div>
</div>
</div>
</AnalysisBox>
</div>
<div class="left-bottom">
<AnalysisBox title="制裁背景" :showAllBtn="false">
<div class="left-bottom-content">
<div class="timeline-list">
<div class="timeline-item" v-for="(item, index) in timelineData" :key="index">
<div class="date-row">
<div class="dot"></div>
<div class="date">{{ item.date }}</div>
</div>
<div class="content">{{ item.content }}</div>
</div>
</div>
<div class="view-more" v-if="hasMore" @click="loadMore">
查看更多 <el-icon class="icon-more">
<DArrowRight />
</el-icon>
</div>
</div>
</AnalysisBox>
</div>
</div>
<div class="right" v-loading="isLoading">
<AnalysisBox title="制裁清单" :showAllBtn="false">
<div class="right-title">
<div class="stats-row">
<div class="tabs">
<div class="tab-btn" :class="{ active: activeTab === 'add' }" @click="activeTab = 'add'">新增实体</div>
<div class="tab-btn" :class="{ active: activeTab === 'remove' }" @click="activeTab = 'remove'">移除实体
</div>
</div>
<div class="stats-info">
<div class="stat-item">
<span class="dot red"></span>
<span class="text">新增 <span class="num red">{{ addCount }}</span> 家 (50%规则涉及<span class="num red">{{
addRuleCount }}</span>家)</span>
</div>
<div class="stat-item">
<span class="dot green"></span>
<span class="text">移除 <span class="num green">{{ removeCount }}</span> 家 (50%规则涉及<span
class="num green">{{ removeRuleCount }}</span>家)</span>
</div>
</div>
</div>
<div class="filter-row">
<div class="filter-left">
<!-- <el-select v-model="filterEntity" placeholder="受制裁实体" style="width: 184px">
<div class="sanctions-overview">
<div class="main">
<div class="left">
<div class="left-top">
<AnalysisBox title="基本信息" :showAllBtn="false">
<div class="left-top-title">
<div class="info-row">
<div class="label">发布机构:</div>
<div class="value link">
<img :src="title" alt="" class="icon" />
<span @click="handleClickDp">{{ formattedData.postOrgName }} ></span>
</div>
</div>
<div class="info-row">
<div class="label">发布时间:</div>
<div class="value">{{ formattedData.postDate }}</div>
</div>
<div class="info-row">
<div class="label">生效时间:</div>
<div class="value">{{ formattedData.effectiveDate }}</div>
</div>
<div class="info-row">
<div class="label">发布文件:</div>
<div class="value">{{ formattedData.fileCode }}</div>
</div>
<div class="info-row">
<div class="label">案卷号:</div>
<div class="value">{{ formattedData.administrativeOrderId }}</div>
</div>
<div class="info-row">
<div class="label">发布人:</div>
<div class="value link">
<img :src="defaultTitle" alt="" class="icon avatar" />
<span @click="handleClick">{{ formattedData.postPersonName }} ></span>
</div>
</div>
<div class="info-row">
<div class="label">制裁领域:</div>
<div class="value tags">
<span class="tag" v-for="(domain, index) in formattedData.domains" :key="index">{{
domain
}}</span>
</div>
</div>
</div>
<div class="left-top-content">
<div class="content-title">制裁实体分布:</div>
<div class="distribution-list">
<div class="list-item" v-for="(item, index) in entityDistribution" :key="index">
<img :src="flag" alt="" class="flag" />
<div class="country-name">{{ item.name }}</div>
<div class="progress-bar-container">
<div
class="progress-bar"
:style="{
width: item.width,
background: item.gradient
}"
></div>
</div>
<div class="count" :class="{ highlight: index === 0 }">{{ item.count }}</div>
</div>
</div>
</div>
</AnalysisBox>
</div>
<div class="left-bottom">
<AnalysisBox title="制裁背景" :showAllBtn="false">
<div class="left-bottom-content">
<div class="timeline-list">
<div class="timeline-item" v-for="(item, index) in timelineData" :key="index">
<div class="date-row">
<div class="dot"></div>
<div class="date">{{ item.date }}</div>
</div>
<div class="content">{{ item.content }}</div>
</div>
</div>
<div class="view-more" v-if="hasMore" @click="loadMore">
查看更多
<el-icon class="icon-more">
<DArrowRight />
</el-icon>
</div>
</div>
</AnalysisBox>
</div>
</div>
<div class="right" v-loading="isLoading">
<AnalysisBox title="制裁清单" :showAllBtn="false">
<div class="right-title">
<div class="stats-row">
<div class="tabs">
<div class="tab-btn" :class="{ active: activeTab === 'add' }" @click="activeTab = 'add'">
新增实体
</div>
<div class="tab-btn" :class="{ active: activeTab === 'remove' }" @click="activeTab = 'remove'">
移除实体
</div>
</div>
<div class="stats-info">
<div class="stat-item">
<span class="dot red"></span>
<span class="text"
>新增 <span class="num red">{{ addCount }}</span> 家 (50%规则涉及<span class="num red">{{
addRuleCount
}}</span
>家)</span
>
</div>
<div class="stat-item">
<span class="dot green"></span>
<span class="text"
>移除 <span class="num green">{{ removeCount }}</span> 家 (50%规则涉及<span
class="num green"
>{{ removeRuleCount }}</span
>家)</span
>
</div>
</div>
</div>
<div class="filter-row">
<div class="filter-left">
<!-- <el-select v-model="filterEntity" placeholder="受制裁实体" style="width: 184px">
<el-option label="受制裁实体" value="1" />
</el-select> -->
</div>
<div class="filter-right">
<el-checkbox v-model="onlyChina" label="只看中国实体" />
<el-select v-model="filterField" placeholder="全部领域" style="width: 150px; margin: 0 12px 0 16px">
<el-option label="全部领域" value="" />
<el-option v-for="item in domainOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-input v-model="searchKeyword" placeholder="搜索实体" style="width: 150px" :suffix-icon="Search" />
</div>
</div>
</div>
<div class="right-content">
<div class="sanction-group-list">
<div class="sanction-group" v-for="(group, index) in sanctionList" :key="index">
<el-table :data="group.entities" style="width: 100%">
<el-table-column label="实体名称" min-width="280">
<template #default="scope">
<div class="name-cell">
<div class="dot"></div>
<img :src="defaultTitle" class="company-icon" />
<span class="company-name" @click="handleCompClick(scope.row)">{{ scope.row.name }}</span>
</div>
</template>
</el-table-column>
<el-table-column label="涉及领域" width="180" align="center">
<template #default="scope">
<span v-for="(item, index) in scope.row.fields" :key="index" class="tag"
:style="getTagStyle(item)" style="margin: 0 2px;">{{ item }}</span>
</template>
</el-table-column>
<el-table-column prop="location" label="上市地点" width="90" align="center" />
<el-table-column prop="date" label="制裁时间" width="150" align="center" />
<el-table-column prop="revenue" label="营收(亿元)" width="110" align="center" />
<el-table-column label="50%规则子企业" width="180" align="center">
<template #default="scope">
<span v-if="scope.row.subsidiaryCount" class="subsidiary-link"
@click="handleSubsidiaryClick(scope.row)">
{{ scope.row.subsidiaryText }} <span class="blue-text">{{ scope.row.subsidiaryCount }}家 ></span>
</span>
<span v-else>--</span>
</template>
</el-table-column>
</el-table>
<div class="reason-box">
{{ group.reason }}
</div>
</div>
</div>
</div>
</AnalysisBox>
</div>
</div>
<!-- 50%规则子企业弹框 -->
<RuleSubsidiaryDialog v-model="subsidiaryDialogVisible" :company-name="currentSubsidiaryCompanyName"
:total-count="currentSubsidiaryCount" :data-list="currentSubsidiaryList" />
</div>
</div>
<div class="filter-right">
<el-checkbox v-model="onlyChina" label="只看中国实体" />
<el-select
v-model="filterField"
placeholder="全部领域"
style="width: 150px; margin: 0 12px 0 16px"
>
<el-option label="全部领域" value="" />
<el-option
v-for="item in domainOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-input
v-model="searchKeyword"
placeholder="搜索实体"
style="width: 150px"
:suffix-icon="Search"
/>
</div>
</div>
</div>
<div class="right-content">
<div class="sanction-group-list">
<div class="sanction-group" v-for="(group, index) in sanctionList" :key="index">
<el-table :data="group.entities" style="width: 100%">
<el-table-column label="实体名称" min-width="280">
<template #default="scope">
<div class="name-cell">
<div class="dot"></div>
<img :src="defaultTitle" class="company-icon" />
<span class="company-name" @click="handleCompClick(scope.row)">{{
scope.row.name
}}</span>
</div>
</template>
</el-table-column>
<el-table-column label="涉及领域" width="180" align="center">
<template #default="scope">
<span
v-for="(item, index) in scope.row.fields"
:key="index"
class="tag"
:style="getTagStyle(item)"
style="margin: 0 2px"
>{{ item }}</span
>
</template>
</el-table-column>
<el-table-column prop="location" label="上市地点" width="90" align="center" />
<el-table-column prop="date" label="制裁时间" width="150" align="center" />
<el-table-column prop="revenue" label="营收(亿元)" width="110" align="center" />
<el-table-column label="50%规则子企业" width="180" align="center">
<template #default="scope">
<span
v-if="scope.row.subsidiaryCount"
class="subsidiary-link"
@click="handleSubsidiaryClick(scope.row)"
>
{{ scope.row.subsidiaryText }}
<span class="blue-text">{{ scope.row.subsidiaryCount }}家 ></span>
</span>
<span v-else>--</span>
</template>
</el-table-column>
</el-table>
<div class="reason-box">
{{ group.reason }}
</div>
</div>
</div>
</div>
</AnalysisBox>
</div>
</div>
<!-- 50%规则子企业弹框 -->
<RuleSubsidiaryDialog
v-model="subsidiaryDialogVisible"
:company-name="currentSubsidiaryCompanyName"
:total-count="currentSubsidiaryCount"
:data-list="currentSubsidiaryList"
/>
</div>
</template>
<script setup>
......@@ -172,34 +219,40 @@ import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { DArrowRight, Search } from "@element-plus/icons-vue";
import { debounce } from "lodash";
import title from "../../assets/title.png"
import defaultTitle from "../../assets/default-icon1.png"
import flag from "../../assets/default-icon2.png"
import { getSingleSanctionEntityCountry, getSingleSanctionBackground, getSingleSanctionOverviewList } from "@/api/exportControlV2.0";
import title from "../../assets/title.png";
import defaultTitle from "../../assets/default-icon1.png";
import flag from "../../assets/default-icon2.png";
import {
getSingleSanctionEntityCountry,
getSingleSanctionBackground,
getSingleSanctionOverviewList
} from "@/api/exportControlV2.0";
import RuleSubsidiaryDialog from "../../../v2.0EntityList/components/sanctionsOverview/components/listPage/RuleSubsidiaryDialog.vue";
import { useRoute } from "vue-router";
const route = useRoute();
// 跳转公司详情页
const handleCompClick = item => {
if (!item.entityId) {
ElMessage.warning("暂无数据");
return;
}
window.sessionStorage.setItem('curTabName', item.name)
const curRoute = router.resolve({ name: "companyPages", params: { id: item.entityId } });
window.open(curRoute.href, "_blank");
if (!item.entityId) {
ElMessage.warning("暂无数据");
return;
}
window.sessionStorage.setItem("curTabName", item.name);
const curRoute = router.resolve({ name: "companyPages", params: { id: item.entityId } });
window.open(curRoute.href, "_blank");
};
// 跳转发布机构详情页
const handleClickDp = () => {
// console.log("点击了发布机构:", props.data);
window.sessionStorage.setItem('curTabName', props.data.postOrgName)
const route = router.resolve({
path: "/institution",
query: {
id: props.data.postOrgId
}
});
window.open(route.href, "_blank");
// console.log("点击了发布机构:", props.data);
window.sessionStorage.setItem("curTabName", props.data.postOrgName);
const route = router.resolve({
path: "/institution",
query: {
id: props.data.postOrgId
}
});
window.open(route.href, "_blank");
};
// 50%规则子企业弹框逻辑
......@@ -208,63 +261,65 @@ const currentSubsidiaryCompanyName = ref("");
const currentSubsidiaryCount = ref(0);
const currentSubsidiaryList = ref([]);
const handleSubsidiaryClick = (row) => {
currentSubsidiaryCompanyName.value = row.name;
currentSubsidiaryCount.value = row.subsidiaryCount;
currentSubsidiaryList.value = row.ruleOrgList || [];
subsidiaryDialogVisible.value = true;
const handleSubsidiaryClick = row => {
currentSubsidiaryCompanyName.value = row.name;
currentSubsidiaryCount.value = row.subsidiaryCount;
currentSubsidiaryList.value = row.ruleOrgList || [];
subsidiaryDialogVisible.value = true;
};
// 单次制裁-制裁概况-制裁清单
const sanctionList = ref([])
const addCount = ref(0)
const addRuleCount = ref(0)
const removeCount = ref(0)
const removeRuleCount = ref(0)
const sanctionList = ref([]);
const addCount = ref(0);
const addRuleCount = ref(0);
const removeCount = ref(0);
const removeRuleCount = ref(0);
const isLoading = ref(false)
const isLoading = ref(false);
// 调用单次制裁-制裁概况-制裁清单接口
const getSanctionOverviewList = async () => {
isLoading.value = true
try {
const res = await getSingleSanctionOverviewList({
sanRecordId: sanRecordId.value,
isOnlyCn: onlyChina.value,
domainId: filterField.value || undefined,
searchText: searchKeyword.value || undefined,
searchType: searchType.value
})
isLoading.value = false
if (res.code === 200) {
const data = res.data || {}
addCount.value = data.addCount || 0
addRuleCount.value = data.addRuleCount || 0
removeCount.value = data.removeCount || 0
removeRuleCount.value = data.removeRuleCount || 0
const list = data.sanList || []
sanctionList.value = list.map(item => ({
reason: item.sanReason,
entities: (item.orgList || []).map(org => ({
...org,
name: org.entityNameZh || org.entityName,
fields: org.techDomains || [],
location: "--", // 接口暂无数据
date: org.startTime ? org.startTime.replace(/^(\d{4})-(\d{2})-(\d{2}).*$/, '$1年$2月$3日') : '--', // 格式化日期
revenue: "--", // 接口暂无数据
subsidiaryCount: org.ruleOrgCount || 0,
subsidiaryText: org.ruleOrgList && org.ruleOrgList.length > 0
? (org.ruleOrgList[0].orgName.length > 10 ? org.ruleOrgList[0].orgName.slice(0, 10) + '...' : org.ruleOrgList[0].orgName) + '...等'
: ''
}))
}))
}
} catch (error) {
console.log(error)
}
}
isLoading.value = true;
try {
const res = await getSingleSanctionOverviewList({
sanRecordId: sanRecordId.value,
isOnlyCn: onlyChina.value,
domainId: filterField.value || undefined,
searchText: searchKeyword.value || undefined,
searchType: searchType.value
});
isLoading.value = false;
if (res.code === 200) {
const data = res.data || {};
addCount.value = data.addCount || 0;
addRuleCount.value = data.addRuleCount || 0;
removeCount.value = data.removeCount || 0;
removeRuleCount.value = data.removeRuleCount || 0;
const list = data.sanList || [];
sanctionList.value = list.map(item => ({
reason: item.sanReason,
entities: (item.orgList || []).map(org => ({
...org,
name: org.entityNameZh || org.entityName,
fields: org.techDomains || [],
location: "--", // 接口暂无数据
date: org.startTime ? org.startTime.replace(/^(\d{4})-(\d{2})-(\d{2}).*$/, "$1年$2月$3日") : "--", // 格式化日期
revenue: "--", // 接口暂无数据
subsidiaryCount: org.ruleOrgCount || 0,
subsidiaryText:
org.ruleOrgList && org.ruleOrgList.length > 0
? (org.ruleOrgList[0].orgName.length > 10
? org.ruleOrgList[0].orgName.slice(0, 10) + "..."
: org.ruleOrgList[0].orgName) + "...等"
: ""
}))
}));
}
} catch (error) {
console.log(error);
}
};
// 单次制裁-制裁概况-制裁背景
const timelinePage = ref(1);
......@@ -272,811 +327,814 @@ const timelinePageSize = ref(3);
const hasMore = ref(true);
const getSanctionBackground = async (isLoadMore = false) => {
try {
const res = await getSingleSanctionBackground({
sanRecordId: sanRecordId.value,
pageNum: timelinePage.value,
pageSize: timelinePageSize.value,
})
if (res.code === 200) {
const list = res.data.content || [];
const formattedList = list.map(item => ({
...item,
date: item.createTime ? item.createTime.split(' ')[0] : '', // 提取日期部分
content: item.summaryZh
}));
if (isLoadMore) {
timelineData.value = [...timelineData.value, ...formattedList];
} else {
timelineData.value = formattedList;
}
// 判断是否还有更多数据
const totalElements = res.data.totalElements || 0;
hasMore.value = timelineData.value.length < totalElements;
}
} catch (error) {
console.log(error)
}
}
try {
const res = await getSingleSanctionBackground({
sanRecordId: sanRecordId.value,
pageNum: timelinePage.value,
pageSize: timelinePageSize.value
});
if (res.code === 200) {
const list = res.data.content || [];
const formattedList = list.map(item => ({
...item,
date: item.createTime ? item.createTime.split(" ")[0] : "", // 提取日期部分
content: item.summaryZh
}));
if (isLoadMore) {
timelineData.value = [...timelineData.value, ...formattedList];
} else {
timelineData.value = formattedList;
}
// 判断是否还有更多数据
const totalElements = res.data.totalElements || 0;
hasMore.value = timelineData.value.length < totalElements;
}
} catch (error) {
console.log(error);
}
};
const loadMore = () => {
timelinePage.value++;
getSanctionBackground(true);
timelinePage.value++;
getSanctionBackground(true);
};
const router = useRouter();
const sanRecordId = ref("")
const sanRecordId = ref("");
const getUrlParams = () => {
const urlParams = new URLSearchParams(window.location.search);
sanRecordId.value = urlParams.get("id") || ""
}
const urlParams = new URLSearchParams(window.location.search);
sanRecordId.value = urlParams.get("id") || "";
};
// 单次制裁-制裁概况-制裁实体国家分布
const getEntityCountry = async () => {
try {
const res = await getSingleSanctionEntityCountry({
sanRecordId: sanRecordId.value
})
if (res.code === 200) {
const rawData = res.data || [];
const maxCount = Math.max(...rawData.map(item => item.count || 0), 1);
// 颜色池 - 用于循环分配
const gradientPool = [
"linear-gradient(270deg, rgba(255,170,0,1) 0%, rgba(255,255,255,0) 100%)", // 橙
"linear-gradient(270deg, rgba(5,95,194,1) 0%, rgba(255,255,255,0) 100%)", // 蓝
"linear-gradient(270deg, rgba(114,46,209,1) 0%, rgba(255,255,255,0) 100%)", // 紫
"linear-gradient(270deg, rgba(16,178,166,1) 0%, rgba(255,255,255,0) 100%)" // 青
];
// 固定颜色映射 - 特定国家使用固定颜色
const fixedColorMap = {
"中国": "linear-gradient(270deg, rgba(206,79,81,1) 0%, rgba(255,255,255,0) 100%)" // 红
};
entityDistribution.value = rawData.map((item, index) => ({
...item,
width: `${((item.count || 0) / maxCount) * 100}%`,
// 优先使用固定颜色,否则循环使用颜色池中的颜色
gradient: fixedColorMap[item.name] || gradientPool[index % gradientPool.length]
}));
}
} catch (error) {
console.log(error)
}
}
try {
const res = await getSingleSanctionEntityCountry({
sanRecordId: sanRecordId.value,
sanTypeId: sanTypeId.value || 1 // 实体清单固定1
});
if (res.code === 200) {
const rawData = res.data || [];
const maxCount = Math.max(...rawData.map(item => item.count || 0), 1);
// 颜色池 - 用于循环分配
const gradientPool = [
"linear-gradient(270deg, rgba(255,170,0,1) 0%, rgba(255,255,255,0) 100%)", // 橙
"linear-gradient(270deg, rgba(5,95,194,1) 0%, rgba(255,255,255,0) 100%)", // 蓝
"linear-gradient(270deg, rgba(114,46,209,1) 0%, rgba(255,255,255,0) 100%)", // 紫
"linear-gradient(270deg, rgba(16,178,166,1) 0%, rgba(255,255,255,0) 100%)" // 青
];
// 固定颜色映射 - 特定国家使用固定颜色
const fixedColorMap = {
中国: "linear-gradient(270deg, rgba(206,79,81,1) 0%, rgba(255,255,255,0) 100%)" // 红
};
entityDistribution.value = rawData.map((item, index) => ({
...item,
width: `${((item.count || 0) / maxCount) * 100}%`,
// 优先使用固定颜色,否则循环使用颜色池中的颜色
gradient: fixedColorMap[item.name] || gradientPool[index % gradientPool.length]
}));
}
} catch (error) {
console.log(error);
}
};
const props = defineProps({
data: {
type: Object,
default: () => ({})
}
data: {
type: Object,
default: () => ({})
}
});
// 跳转到人物页
const handleClick = () => {
window.sessionStorage.setItem("curTabName", props.data.postPersonName)
const route = router.resolve({
path: "/characterPage",
query: {
// type: props.data.type,
personId: props.data.postPersonId
}
});
window.open(route.href, "_blank");
window.sessionStorage.setItem("curTabName", props.data.postPersonName);
const route = router.resolve({
path: "/characterPage",
query: {
// type: props.data.type,
personId: props.data.postPersonId
}
});
window.open(route.href, "_blank");
};
// 计算属性处理数据
const formattedData = computed(() => {
const info = props.data || {};
// 日期格式化
const formatDate = (dateStr) => {
if (!dateStr) return '';
const date = new Date(dateStr);
if (isNaN(date.getTime())) return dateStr;
return `${date.getFullYear()}${date.getMonth() + 1}${date.getDate()}日`;
};
return {
postOrgName: info.postOrgName,
postDate: formatDate(info.postDate),
effectiveDate: formatDate(info.effectiveDate),
fileCode: info.fileCode ? `${info.fileCode} ` : '',
administrativeOrderId: info.administrativeOrderId ? `No. ${info.administrativeOrderId}` : '',
postPersonName: info.postPersonName,
domains: info.domainNames
};
const info = props.data || {};
// 日期格式化
const formatDate = dateStr => {
if (!dateStr) return "";
const date = new Date(dateStr);
if (isNaN(date.getTime())) return dateStr;
return `${date.getFullYear()}${date.getMonth() + 1}${date.getDate()}日`;
};
return {
postOrgName: info.postOrgName,
postDate: formatDate(info.postDate),
effectiveDate: formatDate(info.effectiveDate),
fileCode: info.fileCode ? `${info.fileCode} ` : "",
administrativeOrderId: info.administrativeOrderId ? `No. ${info.administrativeOrderId}` : "",
postPersonName: info.postPersonName,
domains: info.domainNames
};
});
const filterEntity = ref('')
const onlyChina = ref(false)
const filterField = ref('')
const searchKeyword = ref('')
const activeTab = ref('add')
const searchType = computed(() => activeTab.value)
const filterEntity = ref("");
const onlyChina = ref(false);
const filterField = ref("");
const searchKeyword = ref("");
const activeTab = ref("add");
const searchType = computed(() => activeTab.value);
// 监听筛选条件变化
watch([onlyChina, filterField, activeTab], () => {
getSanctionOverviewList()
})
getSanctionOverviewList();
});
// 搜索框防抖
const debouncedSearch = debounce(() => {
getSanctionOverviewList()
}, 500)
getSanctionOverviewList();
}, 500);
watch(searchKeyword, () => {
debouncedSearch()
})
debouncedSearch();
});
const domainOptions = ref([
{ label: "人工智能", value: "1" },
{ label: "生物科技", value: "2" },
{ label: "新一代信息技术", value: "3" },
{ label: "量子科技", value: "4" },
{ label: "新能源", value: "5" },
{ label: "集成电路", value: "6" },
{ label: "海洋", value: "7" },
{ label: "先进制造", value: "8" },
{ label: "新材料", value: "9" },
{ label: "航空航天", value: "10" },
{ label: "深海", value: "11" },
{ label: "极地", value: "12" },
{ label: "太空", value: "13" },
{ label: "核", value: "14" }
{ label: "人工智能", value: "1" },
{ label: "生物科技", value: "2" },
{ label: "新一代信息技术", value: "3" },
{ label: "量子科技", value: "4" },
{ label: "新能源", value: "5" },
{ label: "集成电路", value: "6" },
{ label: "海洋", value: "7" },
{ label: "先进制造", value: "8" },
{ label: "新材料", value: "9" },
{ label: "航空航天", value: "10" },
{ label: "深海", value: "11" },
{ label: "极地", value: "12" },
{ label: "太空", value: "13" },
{ label: "核", value: "14" }
]);
const tagColors = [
{ bg: 'rgb(242, 235, 255)', border: 'rgb(211, 190, 255)', text: 'rgb(114, 46, 209)' }, // Purple
{ bg: 'rgb(225, 250, 248)', border: 'rgb(178, 242, 238)', text: 'rgb(16, 178, 166)' }, // Cyan
{ bg: 'rgb(231, 243, 255)', border: 'rgb(186, 224, 255)', text: 'rgb(5, 95, 194)' }, // Blue
{ bg: 'rgb(255, 247, 230)', border: 'rgb(255, 213, 145)', text: 'rgb(250, 140, 22)' }, // Orange
{ bg: 'rgb(255, 241, 240)', border: 'rgb(255, 204, 199)', text: 'rgb(245, 34, 45)' }, // Red
{ bg: 'rgb(246, 255, 237)', border: 'rgb(183, 235, 143)', text: 'rgb(82, 196, 26)' }, // Green
{ bg: "rgb(242, 235, 255)", border: "rgb(211, 190, 255)", text: "rgb(114, 46, 209)" }, // Purple
{ bg: "rgb(225, 250, 248)", border: "rgb(178, 242, 238)", text: "rgb(16, 178, 166)" }, // Cyan
{ bg: "rgb(231, 243, 255)", border: "rgb(186, 224, 255)", text: "rgb(5, 95, 194)" }, // Blue
{ bg: "rgb(255, 247, 230)", border: "rgb(255, 213, 145)", text: "rgb(250, 140, 22)" }, // Orange
{ bg: "rgb(255, 241, 240)", border: "rgb(255, 204, 199)", text: "rgb(245, 34, 45)" }, // Red
{ bg: "rgb(246, 255, 237)", border: "rgb(183, 235, 143)", text: "rgb(82, 196, 26)" } // Green
];
const getTagStyle = (tagName) => {
if (!tagName) return {};
let hash = 0;
for (let i = 0; i < tagName.length; i++) {
hash = tagName.charCodeAt(i) + ((hash << 5) - hash);
}
const index = Math.abs(hash) % tagColors.length;
const color = tagColors[index];
return {
backgroundColor: color.bg,
borderColor: color.border,
color: color.text
};
}
const getTagStyle = tagName => {
if (!tagName) return {};
let hash = 0;
for (let i = 0; i < tagName.length; i++) {
hash = tagName.charCodeAt(i) + ((hash << 5) - hash);
}
const index = Math.abs(hash) % tagColors.length;
const color = tagColors[index];
return {
backgroundColor: color.bg,
borderColor: color.border,
color: color.text
};
};
const timelineData = ref([]);
const entityDistribution = ref([
{
name: "中国",
count: 24,
width: "100%",
gradient: "linear-gradient(270deg, rgba(206,79,81,1) 0%, rgba(255,255,255,0) 100%)"
},
{
name: "沙特阿拉伯",
count: 2,
width: "60%",
gradient: "linear-gradient(270deg, rgba(255,170,0,1) 0%, rgba(255,255,255,0) 100%)"
},
{
name: "俄罗斯",
count: 2,
width: "60%",
gradient: "linear-gradient(270deg, rgba(255,170,0,1) 0%, rgba(255,255,255,0) 100%)"
},
{
name: "中国香港",
count: 1,
width: "50%",
gradient: "linear-gradient(270deg, rgba(5,95,194,1) 0%, rgba(255,255,255,0) 100%)"
}
])
{
name: "中国",
count: 24,
width: "100%",
gradient: "linear-gradient(270deg, rgba(206,79,81,1) 0%, rgba(255,255,255,0) 100%)"
},
{
name: "沙特阿拉伯",
count: 2,
width: "60%",
gradient: "linear-gradient(270deg, rgba(255,170,0,1) 0%, rgba(255,255,255,0) 100%)"
},
{
name: "俄罗斯",
count: 2,
width: "60%",
gradient: "linear-gradient(270deg, rgba(255,170,0,1) 0%, rgba(255,255,255,0) 100%)"
},
{
name: "中国香港",
count: 1,
width: "50%",
gradient: "linear-gradient(270deg, rgba(5,95,194,1) 0%, rgba(255,255,255,0) 100%)"
}
]);
const sanTypeId = ref("");
onMounted(() => {
// 获取URL参数
getUrlParams()
// 单次制裁-制裁概况-制裁实体国家分布
getEntityCountry()
// 单次制裁-制裁概况-制裁背景
getSanctionBackground()
// 单次制裁-制裁概况-制裁清单
getSanctionOverviewList()
})
// 获取路由参数中的sanTypeId
sanTypeId.value = route.query.sanTypeId || "1";
// 获取URL参数
getUrlParams();
// 单次制裁-制裁概况-制裁实体国家分布
getEntityCountry();
// 单次制裁-制裁概况-制裁背景
getSanctionBackground();
// 单次制裁-制裁概况-制裁清单
getSanctionOverviewList();
});
</script>
<style scoped lang="scss">
* {
margin: 0;
padding: 0;
margin: 0;
padding: 0;
}
.sanctions-overview {
width: 1601px;
margin: 0 auto;
padding-top: 16px;
padding-bottom: 16px;
.main {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
.left {
width: 520px;
// height: 1119px;
.left-top {
width: 100%;
height: auto;
// padding-bottom: 20px;
// border-radius: 10px;
// box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
// background-color: #fff;
margin-bottom: 16px;
.left-top-title {
padding: 22px 20px 22px 27px;
width: 100%;
height: auto;
border-bottom: 1px solid rgb(234, 236, 238);
display: flex;
flex-direction: column;
// justify-content: space-between;
gap: 12px;
.info-row {
display: flex;
align-items: center;
font-size: 16px;
font-family: "Microsoft YaHei";
line-height: 24px;
.label {
min-width: 92px;
color: rgb(59, 65, 75);
font-weight: 700;
font-size: 16px;
font-family: "Microsoft YaHei";
line-height: 24px;
text-align: left;
}
.value {
display: flex;
align-items: center;
color: rgb(59, 65, 75);
font-weight: 400;
font-size: 16px;
font-family: "Microsoft YaHei";
line-height: 24px;
overflow: hidden;
&.link {
color: rgb(5, 95, 194);
cursor: pointer;
}
.icon {
width: 20px;
height: 20px;
margin-right: 8px;
object-fit: contain;
&.avatar {
border-radius: 50%;
width: 24px;
height: 24px;
}
}
&.tags {
gap: 8px;
flex-wrap: wrap;
overflow: visible;
.tag {
padding: 1px 8px;
background: rgba(246, 250, 255, 1);
border-radius: 4px;
border: 1px solid rgba(231, 243, 255, 1);
color: rgb(5, 95, 194);
font-size: 14px;
line-height: 20px;
}
}
}
}
}
.left-top-content {
width: 100%;
height: 234px;
padding: 19px 29px 22px 27px;
overflow: auto;
.content-title {
font-size: 16px;
font-weight: 700;
color: rgb(59, 65, 75);
font-family: "Microsoft YaHei";
line-height: 24px;
margin-bottom: 12px;
text-align: left;
}
.distribution-list {
display: flex;
flex-direction: column;
gap: 16px;
overflow: auto;
.list-item {
display: flex;
align-items: center;
height: 24px;
.flag {
width: 24px;
height: 24px;
margin-right: 16px;
border-radius: 50%;
object-fit: cover;
}
.country-name {
width: 96px;
font-size: 16px;
font-weight: 400;
color: rgb(59, 65, 75);
font-family: "Microsoft YaHei";
line-height: 24px;
margin-right: 12px;
text-align: left;
}
.progress-bar-container {
flex: 1;
height: 8px;
// background: #f0f2f5;
// border-radius: 4px;
// overflow: hidden;
margin-right: 24px;
display: flex;
align-items: center;
.progress-bar {
height: 100%;
border-radius: 4px;
}
}
.count {
// width: 40px;
text-align: right;
font-size: 16px;
font-weight: 400;
color: rgb(59, 65, 75);
font-family: "Microsoft YaHei";
line-height: 24px;
&.highlight {
color: rgb(206, 79, 81);
font-weight: 700;
}
}
}
}
}
}
.left-bottom {
width: 100%;
height: 521px;
.left-bottom-content {
padding: 20px 25px 0 25px;
height: calc(100% - 45px); // 减去标题高度
display: flex;
flex-direction: column;
.timeline-list {
display: flex;
flex-direction: column;
gap: 24px;
margin-bottom: 24px;
overflow-y: auto; // 允许垂直滚动
flex: 1; // 占据剩余空间
padding-right: 10px; // 防止滚动条遮挡内容
/* Custom Scrollbar */
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: 3px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
}
.timeline-item {
display: flex;
flex-direction: column;
// margin-left: 12px;
position: relative;
&::before {
content: "";
position: absolute;
left: 6px;
top: 12px;
height: calc(100% + 24px);
width: 1px;
background-color: rgb(234, 236, 238);
transform: translateX(-50%);
}
&:last-child::before {
display: none;
}
}
.date-row {
display: flex;
align-items: center;
margin-bottom: 3px;
}
.dot {
width: 12px;
height: 12px;
border-radius: 50%;
background-color: #fff;
border: 3px solid rgb(5, 95, 194);
box-sizing: border-box;
margin-right: 13px;
position: relative;
z-index: 1;
}
.date {
font-size: 16px;
font-weight: 700;
color: rgb(5, 95, 194);
font-family: "Microsoft YaHei";
line-height: 24px;
// margin-bottom: 3px;
}
.content {
font-size: 16px;
font-weight: 400;
color: rgb(59, 65, 75);
line-height: 24px;
margin-left: 25px;
text-align: left;
font-family: "Microsoft YaHei";
}
.view-more {
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 400;
color: rgb(5, 95, 194);
cursor: pointer;
margin-top: 24px;
font-family: "Microsoft YaHei";
.icon-more {
transform: rotate(90deg);
margin-left: 8px;
}
}
}
}
}
.right {
width: 1064px;
// height: auto;
// border-radius: 10px;
// box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
// background-color: #fff;
.right-title {
width: 100%;
// height: 107px;
padding: 4px 20px 20px 20px;
box-sizing: border-box;
.filter-row {
display: flex;
justify-content: right;
align-items: center;
// margin-bottom: 20px;
:deep(.el-input__inner) {
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(95, 101, 108);
&::placeholder {
color: rgb(95, 101, 108);
}
}
:deep(.el-checkbox__label) {
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(95, 101, 108);
}
.filter-right {
display: flex;
align-items: center;
}
}
.stats-row {
display: flex;
margin-bottom: 20px;
justify-content: space-between;
align-items: center;
.tabs {
display: flex;
gap: 8px;
.tab-btn {
padding: 4px 8px;
border: 1px solid rgb(230, 231, 232);
border-radius: 4px;
cursor: pointer;
font-size: 18px;
color: rgb(59, 65, 75);
font-weight: 400;
line-height: 24px;
font-family: "Microsoft YaHei";
&.active {
color: rgb(5, 95, 194);
border-color: rgb(5, 95, 194);
font-weight: 700;
}
}
}
.stats-info {
display: flex;
gap: 24px;
align-items: center;
.stat-item {
display: flex;
align-items: center;
font-size: 18px;
color: rgb(59, 65, 75);
font-family: "Microsoft YaHei";
line-height: 24px;
margin-right: 34px;
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 8px;
&.red {
background-color: rgb(206, 79, 81);
}
&.green {
background-color: rgb(33, 129, 57);
}
}
.text {
font-size: 18px;
font-weight: 700;
line-height: 24px;
font-family: "Microsoft YaHei";
color: rgb(59, 65, 75);
.num {
font-weight: 700;
&.red {
color: rgb(206, 79, 81);
}
&.green {
color: rgb(33, 129, 57);
}
}
}
}
}
}
}
.right-content {
padding: 0 20px 17px 20px;
.sanction-group-list {
display: flex;
flex-direction: column;
gap: 16px;
.sanction-group {
border: 1px solid rgb(234, 236, 238);
border-radius: 8px;
overflow: hidden;
:deep(.el-table__header-wrapper) {
th {
background-color: var(--color-primary-100) !important;
height: 48px;
padding: 0;
color: #fff;
font-weight: 700;
font-size: 16px;
font-family: "Microsoft YaHei";
border-bottom: none;
}
th:first-child {
border-top-left-radius: 8px;
}
th:last-child {
border-top-right-radius: 8px;
}
}
:deep(.el-table__body-wrapper) {
tr:nth-child(odd) td {
background-color: rgba(248, 249, 250, 1);
}
tr:nth-child(even) td {
background-color: #fff;
}
td {
height: 48px;
padding: 0;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
color: rgb(95, 101, 108);
line-height: 24px;
}
}
.name-cell {
display: flex;
align-items: center;
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: rgb(206, 79, 81);
margin-right: 16px;
flex-shrink: 0;
}
.company-icon {
width: 24px;
height: 24px;
margin-right: 12px;
border-radius: 50%;
flex-shrink: 0;
}
.company-name {
font-size: 16px;
font-weight: 700;
line-height: 24px;
font-family: "Microsoft YaHei";
color: rgba(59, 65, 75, 1);
cursor: pointer;
}
}
.tag {
padding: 1px 8px;
border-radius: 4px;
font-size: 14px;
display: inline-block;
border: 1px solid transparent;
}
.subsidiary-link {
cursor: pointer;
font-size: 14px;
color: rgb(59, 65, 75);
.blue-text {
color: rgb(5, 95, 194);
}
}
.reason-box {
padding: 12px 19px 14px 39px;
background-color: #fff;
border-top: 1px solid rgb(234, 236, 238);
font-size: 16px;
color: rgb(59, 65, 75);
line-height: 28px;
font-family: "Microsoft YaHei";
text-align: left;
}
}
}
}
}
}
width: 1601px;
margin: 0 auto;
padding-top: 16px;
padding-bottom: 16px;
.main {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
.left {
width: 520px;
// height: 1119px;
.left-top {
width: 100%;
height: auto;
// padding-bottom: 20px;
// border-radius: 10px;
// box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
// background-color: #fff;
margin-bottom: 16px;
.left-top-title {
padding: 22px 20px 22px 27px;
width: 100%;
height: auto;
border-bottom: 1px solid rgb(234, 236, 238);
display: flex;
flex-direction: column;
// justify-content: space-between;
gap: 12px;
.info-row {
display: flex;
align-items: center;
font-size: 16px;
font-family: "Microsoft YaHei";
line-height: 24px;
.label {
min-width: 92px;
color: rgb(59, 65, 75);
font-weight: 700;
font-size: 16px;
font-family: "Microsoft YaHei";
line-height: 24px;
text-align: left;
}
.value {
display: flex;
align-items: center;
color: rgb(59, 65, 75);
font-weight: 400;
font-size: 16px;
font-family: "Microsoft YaHei";
line-height: 24px;
overflow: hidden;
&.link {
color: rgb(5, 95, 194);
cursor: pointer;
}
.icon {
width: 20px;
height: 20px;
margin-right: 8px;
object-fit: contain;
&.avatar {
border-radius: 50%;
width: 24px;
height: 24px;
}
}
&.tags {
gap: 8px;
flex-wrap: wrap;
overflow: visible;
.tag {
padding: 1px 8px;
background: rgba(246, 250, 255, 1);
border-radius: 4px;
border: 1px solid rgba(231, 243, 255, 1);
color: rgb(5, 95, 194);
font-size: 14px;
line-height: 20px;
}
}
}
}
}
.left-top-content {
width: 100%;
height: 234px;
padding: 19px 29px 22px 27px;
overflow: auto;
.content-title {
font-size: 16px;
font-weight: 700;
color: rgb(59, 65, 75);
font-family: "Microsoft YaHei";
line-height: 24px;
margin-bottom: 12px;
text-align: left;
}
.distribution-list {
display: flex;
flex-direction: column;
gap: 16px;
overflow: auto;
.list-item {
display: flex;
align-items: center;
height: 24px;
.flag {
width: 24px;
height: 24px;
margin-right: 16px;
border-radius: 50%;
object-fit: cover;
}
.country-name {
width: 96px;
font-size: 16px;
font-weight: 400;
color: rgb(59, 65, 75);
font-family: "Microsoft YaHei";
line-height: 24px;
margin-right: 12px;
text-align: left;
}
.progress-bar-container {
flex: 1;
height: 8px;
// background: #f0f2f5;
// border-radius: 4px;
// overflow: hidden;
margin-right: 24px;
display: flex;
align-items: center;
.progress-bar {
height: 100%;
border-radius: 4px;
}
}
.count {
// width: 40px;
text-align: right;
font-size: 16px;
font-weight: 400;
color: rgb(59, 65, 75);
font-family: "Microsoft YaHei";
line-height: 24px;
&.highlight {
color: rgb(206, 79, 81);
font-weight: 700;
}
}
}
}
}
}
.left-bottom {
width: 100%;
height: 521px;
.left-bottom-content {
padding: 20px 25px 0 25px;
height: calc(100% - 45px); // 减去标题高度
display: flex;
flex-direction: column;
.timeline-list {
display: flex;
flex-direction: column;
gap: 24px;
margin-bottom: 24px;
overflow-y: auto; // 允许垂直滚动
flex: 1; // 占据剩余空间
padding-right: 10px; // 防止滚动条遮挡内容
/* Custom Scrollbar */
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: 3px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
}
.timeline-item {
display: flex;
flex-direction: column;
// margin-left: 12px;
position: relative;
&::before {
content: "";
position: absolute;
left: 6px;
top: 12px;
height: calc(100% + 24px);
width: 1px;
background-color: rgb(234, 236, 238);
transform: translateX(-50%);
}
&:last-child::before {
display: none;
}
}
.date-row {
display: flex;
align-items: center;
margin-bottom: 3px;
}
.dot {
width: 12px;
height: 12px;
border-radius: 50%;
background-color: #fff;
border: 3px solid rgb(5, 95, 194);
box-sizing: border-box;
margin-right: 13px;
position: relative;
z-index: 1;
}
.date {
font-size: 16px;
font-weight: 700;
color: rgb(5, 95, 194);
font-family: "Microsoft YaHei";
line-height: 24px;
// margin-bottom: 3px;
}
.content {
font-size: 16px;
font-weight: 400;
color: rgb(59, 65, 75);
line-height: 24px;
margin-left: 25px;
text-align: left;
font-family: "Microsoft YaHei";
}
.view-more {
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 400;
color: rgb(5, 95, 194);
cursor: pointer;
margin-top: 24px;
font-family: "Microsoft YaHei";
.icon-more {
transform: rotate(90deg);
margin-left: 8px;
}
}
}
}
}
.right {
width: 1064px;
// height: auto;
// border-radius: 10px;
// box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
// background-color: #fff;
.right-title {
width: 100%;
// height: 107px;
padding: 4px 20px 20px 20px;
box-sizing: border-box;
.filter-row {
display: flex;
justify-content: right;
align-items: center;
// margin-bottom: 20px;
:deep(.el-input__inner) {
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(95, 101, 108);
&::placeholder {
color: rgb(95, 101, 108);
}
}
:deep(.el-checkbox__label) {
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(95, 101, 108);
}
.filter-right {
display: flex;
align-items: center;
}
}
.stats-row {
display: flex;
margin-bottom: 20px;
justify-content: space-between;
align-items: center;
.tabs {
display: flex;
gap: 8px;
.tab-btn {
padding: 4px 8px;
border: 1px solid rgb(230, 231, 232);
border-radius: 4px;
cursor: pointer;
font-size: 18px;
color: rgb(59, 65, 75);
font-weight: 400;
line-height: 24px;
font-family: "Microsoft YaHei";
&.active {
color: rgb(5, 95, 194);
border-color: rgb(5, 95, 194);
font-weight: 700;
}
}
}
.stats-info {
display: flex;
gap: 24px;
align-items: center;
.stat-item {
display: flex;
align-items: center;
font-size: 18px;
color: rgb(59, 65, 75);
font-family: "Microsoft YaHei";
line-height: 24px;
margin-right: 34px;
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 8px;
&.red {
background-color: rgb(206, 79, 81);
}
&.green {
background-color: rgb(33, 129, 57);
}
}
.text {
font-size: 18px;
font-weight: 700;
line-height: 24px;
font-family: "Microsoft YaHei";
color: rgb(59, 65, 75);
.num {
font-weight: 700;
&.red {
color: rgb(206, 79, 81);
}
&.green {
color: rgb(33, 129, 57);
}
}
}
}
}
}
}
.right-content {
padding: 0 20px 17px 20px;
.sanction-group-list {
display: flex;
flex-direction: column;
gap: 16px;
.sanction-group {
border: 1px solid rgb(234, 236, 238);
border-radius: 8px;
overflow: hidden;
:deep(.el-table__header-wrapper) {
th {
background-color: var(--color-primary-100) !important;
height: 48px;
padding: 0;
color: #fff;
font-weight: 700;
font-size: 16px;
font-family: "Microsoft YaHei";
border-bottom: none;
}
th:first-child {
border-top-left-radius: 8px;
}
th:last-child {
border-top-right-radius: 8px;
}
}
:deep(.el-table__body-wrapper) {
tr:nth-child(odd) td {
background-color: rgba(248, 249, 250, 1);
}
tr:nth-child(even) td {
background-color: #fff;
}
td {
height: 48px;
padding: 0;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
color: rgb(95, 101, 108);
line-height: 24px;
}
}
.name-cell {
display: flex;
align-items: center;
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: rgb(206, 79, 81);
margin-right: 16px;
flex-shrink: 0;
}
.company-icon {
width: 24px;
height: 24px;
margin-right: 12px;
border-radius: 50%;
flex-shrink: 0;
}
.company-name {
font-size: 16px;
font-weight: 700;
line-height: 24px;
font-family: "Microsoft YaHei";
color: rgba(59, 65, 75, 1);
cursor: pointer;
}
}
.tag {
padding: 1px 8px;
border-radius: 4px;
font-size: 14px;
display: inline-block;
border: 1px solid transparent;
}
.subsidiary-link {
cursor: pointer;
font-size: 14px;
color: rgb(59, 65, 75);
.blue-text {
color: rgb(5, 95, 194);
}
}
.reason-box {
padding: 12px 19px 14px 39px;
background-color: #fff;
border-top: 1px solid rgb(234, 236, 238);
font-size: 16px;
color: rgb(59, 65, 75);
line-height: 28px;
font-family: "Microsoft YaHei";
text-align: left;
}
}
}
}
}
}
}
.title-com {
width: 100%;
height: 56px;
display: flex;
align-items: center;
padding: 14px 12px 16px 0;
.box {
width: 8px;
height: 20px;
background-color: rgb(5, 95, 194);
border-bottom-right-radius: 4px;
border-top-right-radius: 4px;
margin-right: 14px;
}
.text {
font-size: 20px;
font-weight: 700;
font-family: "Microsoft YaHei";
line-height: 26px;
color: rgb(5, 95, 194);
}
.btn {
width: 60px;
height: 28px;
margin-left: auto;
img {
width: 28px;
height: 28px;
cursor: pointer;
}
img:first-child {
margin-right: 4px;
}
}
width: 100%;
height: 56px;
display: flex;
align-items: center;
padding: 14px 12px 16px 0;
.box {
width: 8px;
height: 20px;
background-color: rgb(5, 95, 194);
border-bottom-right-radius: 4px;
border-top-right-radius: 4px;
margin-right: 14px;
}
.text {
font-size: 20px;
font-weight: 700;
font-family: "Microsoft YaHei";
line-height: 26px;
color: rgb(5, 95, 194);
}
.btn {
width: 60px;
height: 28px;
margin-left: auto;
img {
width: 28px;
height: 28px;
cursor: pointer;
}
img:first-child {
margin-right: 4px;
}
}
}
</style>
\ No newline at end of file
</style>
......@@ -39,6 +39,9 @@ export default defineConfig({
}
}
},
publicDir: 'public', // 指定 public 目录的位置
// 服务器的根路径
base: '/',
server: {
host: '0.0.0.0', // 监听所有网络接口
port: 3000,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论