提交 6eb0131b authored 作者: 张烨's avatar 张烨

fix:政令模块细节优化

上级 6b9cc944
......@@ -20,6 +20,14 @@ export function getDecreehylyList() {
})
}
// 获取受影响实体列表
export function getDecreeEntities(params) {
return request({
method: 'GET',
url: `/api/administrativeOrderInfo/relatedEntities/${params.id}`,
})
}
// 根据政行业领域ID获取公司列表
/**
* @param {cRelated, id}
......
......@@ -324,8 +324,8 @@ watch(isTranslate, () => {
.report-main {
flex: auto;
box-sizing: border-box;
padding-top: 10px;
height: 20px;
padding: 10px 0;
.no-content {
height: 100%;
......
......@@ -179,17 +179,20 @@
<div class="box5-header-title">{{ "行政令发布频度" }}</div>
</div>
<div class="box5-selectbox">
<el-select @change="handleBox5YearChange" v-model="box5SelectedYear" placeholder="选择时间"
style="width: 120px">
<el-option v-for="item in box5YearList" :key="item.value" :label="item.label" :value="item.value" />
<el-select @change="handleBox5YearChange" v-model="box5SelectedYear" placeholder="选择时间" style="width: 120px">
<el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
<div class="box5-main">
<div class="box5-chart" id="chart1"></div>
</div>
<div class="ai-pane">
<AiButton />
<AiPane aiContent="假数据假数据假数据假数据假数据假数据假数据假数据假数据假数据假数据" />
</div>
</div>
<div class="box6">
<div class="box6-header">
<div class="header-icon">
......@@ -197,9 +200,8 @@
</div>
<div class="header-title">{{ "政令科技领域" }}</div>
<div class="box6-selectbox">
<el-select @change="handleBox6YearChange" v-model="box6SelectedYear" placeholder="选择时间"
style="width: 120px">
<el-option v-for="item in box6YearList" :key="item.value" :label="item.label" :value="item.value" />
<el-select @change="handleBox6YearChange" v-model="box6SelectedYear" placeholder="选择时间" style="width: 120px">
<el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
......@@ -222,10 +224,10 @@
</div>
<div class="info">
<div class="info-header">
<div class="title">{{ item.title }}</div>
<div class="title one-line-ellipsis">{{ item.title }}</div>
<div class="time">{{ item.time }}</div>
</div>
<div class="info-content">{{ item.content ? item.content : "暂无数据" }}</div>
<div class="info-content one-line-ellipsis">{{ item.content || "暂无数据" }}</div>
</div>
</div>
</div>
......@@ -370,7 +372,9 @@ import { onMounted, ref, watch, nextTick, reactive } from "vue";
import router from "@/router";
import WordCloudChart from "@/components/base/WordCloundChart/index.vue"
import SimplePagination from "@/components/SimplePagination.vue";
import TimeTabPane from '@/components/base/TimeTabPane/index.vue'
import TimeTabPane from '@/components/base/TimeTabPane/index.vue';
import AiButton from '@/components/base/Ai/AiButton/index.vue';
import AiPane from '@/components/base/Ai/AiPane/index.vue';
import {
getDepartmentList,
getLatestDecree,
......@@ -687,40 +691,24 @@ const handleClickPerson = async item => {
} catch (error) { }
};
// 获取最近年份列表
const currentYear = new Date().getFullYear();
const getYearList = (count = 6) => {
const yearOptions = [];
for (let i = 0; i < count; i++) {
const year = currentYear - i;
yearOptions.push({ label: year.toString(), value: year.toString() });
}
return yearOptions;
};
const yearList = getYearList();
// 行政令发布频度
const chart1Data = ref({
dataX: [],
dataY: []
});
const box5YearList = ref([
{
label: "2026",
value: "2026"
},
{
label: "2025",
value: "2025"
},
{
label: "2024",
value: "2024"
},
{
label: "2023",
value: "2023"
},
{
label: "2022",
value: "2022"
},
{
label: "2021",
value: "2021"
}
]);
const box5SelectedYear = ref("2026");
const box5SelectedYear = ref(yearList[0].value);
const handleGetDecreeYearOrder = async () => {
const params = {
year: box5SelectedYear.value
......@@ -764,33 +752,7 @@ const chart2Data = ref([
]);
// const colorList = ["#69B1FF", "#FFC069", "#87E8DE", "#85A5FF", "#FF7875", "#B37FEB", "#4096FF"];
const box6YearList = ref([
{
label: "2026",
value: "2026"
},
{
label: "2025",
value: "2025"
},
{
label: "2024",
value: "2024"
},
{
label: "2023",
value: "2023"
},
{
label: "2022",
value: "2022"
},
{
label: "2021",
value: "2021"
}
]);
const box6SelectedYear = ref("2026");
const box6SelectedYear = ref(yearList[0].value);
const handleGetDecreeArea = async () => {
const params = {
......@@ -826,7 +788,7 @@ const keyDecreeList = ref([]);
const keyDecreeInfo = reactive({
total: 0,
page: 1,
size: 3,
size: 5,
})
const handleGetKeyDecree = async () => {
......@@ -917,7 +879,7 @@ const handleChangeCheckedDecreeType = () => {
};
const pubTime = ref([
{ id: "all", name: "全时间" },
{ id: "all", name: "全时间" },
{ id: "2026", name: "2026年" },
{ id: "2025", name: "2025年" },
{ id: "2024", name: "2024年" },
......@@ -1119,127 +1081,6 @@ onMounted(async () => {
position: relative;
overflow-y: hidden;
.search-header {
width: 100%;
// height: 144px;
background: #fff;
overflow: hidden;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
.search-header-container {
width: 1600px;
margin: 0 auto;
padding: 16px 0px 16px 0px;
}
.home-main-header-center {
// margin-top: 20px;
// margin-left: 200px;
width: 800px;
height: 48px;
border-radius: 10px;
// box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
border: 1px solid var(--color-primary-35);
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
padding: 1px;
position: relative;
&:hover {
border: 1px solid var(--color-main-active);
}
.search {
position: absolute;
right: -1px;
top: 0px;
width: 120px;
height: 46px;
border-radius: 10px;
background: var(--color-main-active);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.search-icon {
width: 18px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
.search-text {
margin-left: 8px;
height: 22px;
color: #fff;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 22px;
}
}
}
.home-main-header-btn-box {
margin-top: 16px;
// margin-left: 200px;
display: flex;
gap: 16px;
.btn {
display: flex;
align-items: center;
gap: 9px;
width: 140px;
height: 36px;
border: 1px solid #aed6ff;
box-sizing: border-box;
border-radius: 24px;
background: #e7f3ff;
cursor: pointer;
position: relative;
&:hover {
background: #cae3fc;
}
.btn-text {
width: 80px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
line-height: 48px;
margin-left: 24px;
text-align: center;
}
.btn-icon {
position: absolute;
top: 10px;
right: 19px;
width: 6px;
height: 12px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
.scrollHomeMain {
width: 100%;
height: calc(100% - 144px);
overflow-y: auto;
}
.home-main {
position: relative;
width: 100%;
......@@ -2094,543 +1935,6 @@ onMounted(async () => {
padding-bottom: 8px;
padding-left: 24px;
padding-top: 5px;
// .box4-main-item {
// margin-top: 16px;
// display: flex;
// margin-left: 21px;
// .left {
// margin-top: 5px;
// width: 36px;
// height: 36px;
// border-radius: 18px;
// overflow: hidden;
// cursor: pointer;
// img {
// width: 100%;
// height: 100%;
// }
// }
// .right {
// margin-left: 10px;
// width: 690px;
// border-radius: 4px;
// box-sizing: border-box;
// border: 1px solid rgba(231, 243, 255, 1);
// background: rgba(246, 250, 255, 1);
// padding: 10px 15px;
// .right-top {
// display: flex;
// justify-content: space-between;
// .name {
// height: 24px;
// color: rgba(59, 65, 75, 1);
// font-family: Microsoft YaHei;
// font-size: 16px;
// font-weight: 700;
// line-height: 24px;
// }
// .time {
// height: 30px;
// color: rgba(95, 101, 108, 1);
// font-family: Microsoft YaHei;
// font-size: 16px;
// font-weight: 400;
// line-height: 30px;
// }
// }
// .content {
// color: rgba(59, 65, 75, 1);
// font-family: Microsoft YaHei;
// font-size: 16px;
// font-weight: 400;
// line-height: 24px;
// }
// }
// }
}
}
}
.center-center1 {
margin: 0 auto;
margin-top: 24px;
height: 100px;
width: 1600px;
border-radius: 50px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
display: flex;
justify-content: space-between;
box-sizing: border-box;
padding: 4px 5px;
.center1-item {
width: 351px;
height: 92px;
border-radius: 48px;
display: flex;
cursor: pointer;
&:hover {
background: rgba(231, 243, 255, 1);
}
.left {
margin-top: 15px;
margin-left: 39px;
width: 60px;
height: 60px;
img {
width: 100%;
height: 100%;
}
}
.right {
margin-left: 8px;
.name {
height: 31px;
margin-top: 16px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 24px;
font-weight: 700;
line-height: 31px;
}
.nameActive {
color: var(--color-main-active);
}
.time {
margin-top: 1px;
height: 30px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
}
.timeActive {
color: var(--color-main-active);
}
}
}
.center1ItemActive {
background: rgba(231, 243, 255, 1);
}
}
.center-center2 {
margin: 0 auto;
margin-top: 24px;
width: 1600px;
height: 960px;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
.center2-header {
display: flex;
justify-content: space-between;
.center2-header-left {
margin-left: 62px;
display: flex;
.left {
width: 140px;
height: 175px;
border-radius: 0px 0px 70px 70px;
background: rgba(231, 243, 255, 1);
overflow: hidden;
.icon {
width: 128px;
height: 128px;
border-radius: 75px;
margin-top: 41px;
margin-left: 6px;
img {
width: 100%;
height: 100%;
}
}
}
.right {
margin-left: 29px;
.right-item1 {
margin-top: 41px;
height: 31px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 24px;
font-weight: 700;
line-height: 32px;
}
.right-item2 {
display: flex;
margin-top: 7px;
.icon {
width: 24px;
height: 24px;
img {
width: 100%;
height: 100%;
}
}
.text {
margin-left: 8px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 400;
line-height: 24px;
}
}
.right-item3 {
margin-top: 10px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 400;
line-height: 24px;
}
.right-item4 {
margin-top: 8px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 400;
line-height: 24px;
}
}
}
.center2-header-right {
margin-right: 59px;
margin-top: 47px;
.top {
display: flex;
.top-box {
width: 180px;
height: 72px;
margin-left: 50px;
.item1 {
height: 26px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
text-align: right;
}
.item2 {
margin-top: 4px;
font-family: Microsoft YaHei;
font-weight: 700;
display: flex;
justify-content: flex-end;
.item2-3 {
height: 42px;
color: var(--color-main-active);
font-size: 32px;
line-height: 42px;
}
.item2-2 {
height: 24px;
margin-top: 9px;
margin-left: 5px;
margin-right: 5px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 700;
line-height: 24px;
}
.item2-1 {
height: 42px;
color: rgba(206, 79, 81, 1);
font-size: 32px;
line-height: 42px;
}
}
}
}
.bottom {
height: 22px;
margin-top: 29px;
display: flex;
justify-content: flex-end;
.icon {
margin-top: 4px;
width: 14px;
height: 14px;
margin-right: 8px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 22px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 24px;
}
}
}
}
.center2-mid {
width: 1479px;
height: 189px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px;
margin: 40px auto 0;
}
.center2-footer {
display: flex;
.center2-footer-left {
width: 732px;
margin-left: 58px;
margin-top: 21px;
.header {
display: flex;
height: 48px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
.icon {
margin-top: 15px;
margin-left: 20px;
width: 20px;
height: 20px;
img {
width: 100%;
height: 100%;
}
}
.text {
margin-left: 20px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 48px;
}
}
.main {
width: 732px;
height: 470px;
overflow-y: auto;
overflow-x: hidden;
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
padding-top: 9px;
.item {
width: 50%;
height: 80px;
display: flex;
margin-top: 8px;
.item-left {
width: 60px;
height: 60px;
margin-top: 10px;
margin-left: 16px;
img {
width: 100%;
height: 100%;
}
}
.item-right {
margin-left: 13px;
.item-right-box1 {
margin-top: 15px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 700;
line-height: 24px;
}
.item-right-box2 {
margin-top: 1px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
}
}
}
.center2-footer-right {
margin-left: 21px;
margin-top: 16px;
width: 730px;
.header {
height: 54px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
display: flex;
.icon {
width: 24px;
height: 24px;
margin-left: 16px;
margin-top: 16px;
img {
width: 100%;
height: 100%;
}
}
.tab-box {
margin-left: 20px;
width: 500px;
display: flex;
.tab {
height: 54px;
margin-right: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
line-height: 54px;
padding: 0 2px;
box-sizing: border-box;
}
.tabActive {
font-weight: 700;
color: var(--color-main-active);
border-bottom: 3px solid var(--color-main-active);
}
}
.right {
width: 80px;
margin-left: 90px;
display: flex;
justify-content: space-between;
.btn {
width: 28px;
height: 28px;
margin-top: 13px;
img {
width: 100%;
height: 100%;
}
}
}
}
.main {
height: 475px;
margin-top: 5px;
overflow-y: hidden;
.main-item {
display: flex;
margin-top: 20px;
.id {
margin-top: 3px;
margin-left: 2px;
width: 36px;
height: 36px;
border-radius: 18px;
background: #e7f3ff;
line-height: 36px;
text-align: center;
color: var(--color-main-active);
}
.info {
margin-left: 13px;
width: 672px;
.info-header {
display: flex;
justify-content: space-between;
height: 24px;
.title {
height: 24px;
margin-top: 1px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 700;
line-height: 24px;
}
.tag {
height: 24px;
line-height: 24px;
border-radius: 4px;
padding: 0 8px;
background: rgba(255, 251, 230, 1);
color: rgba(250, 173, 20, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
}
}
}
}
}
}
}
}
......@@ -2654,6 +1958,29 @@ onMounted(async () => {
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: rgba(255, 255, 255, 1);
border-radius: 10px;
position: relative;
.ai-pane {
position: absolute;
right: 0px;
bottom: 30px;
z-index: 2;
:deep(.ai-pane-wrapper) {
display: none;
}
:deep(.ai-button-wrapper) {
display: flex;
}
&:hover {
width: 100%;
bottom: 1px;
:deep(.ai-pane-wrapper) {
display: block;
}
:deep(.ai-button-wrapper) {
display: none;
}
}
}
.box5-header {
height: 48px;
......@@ -2758,13 +2085,13 @@ onMounted(async () => {
.center-footer1 {
margin-top: 21px;
height: 450px;
height: 452px;
display: flex;
justify-content: center;
.box7 {
width: 792px;
height: 450px;
height: 100%;
border-radius: 10px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
......@@ -2800,27 +2127,23 @@ onMounted(async () => {
}
.box7-main {
margin-top: 10px;
.box7-list {
height: 310px;
height: 354px;
padding: 4px 24px 0;
.box7-item {
width: 730px;
margin-top: 16px;
margin-left: 25px;
// border-bottom: 1px solid rgba(240, 242, 244, 1);
display: flex;
padding: 6px 0;
cursor: pointer;
&:hover {
background: var(--color-bg-hover);
}
.icon {
margin-top: 6px;
margin-top: 8px;
width: 24px;
height: 22px;
font-size: 0px;
img {
width: 100%;
height: 100%;
......@@ -2829,8 +2152,8 @@ onMounted(async () => {
.info {
margin-left: 13px;
width: 100%;
width: 20px;
flex: auto;
.info-header {
height: 24px;
display: flex;
......@@ -2845,9 +2168,6 @@ onMounted(async () => {
font-size: 18px;
font-weight: 700;
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.time {
......@@ -2865,30 +2185,27 @@ onMounted(async () => {
}
.info-content {
min-height: 24px;
max-height: 48px;
height: 24px;
margin-top: 6px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
:deep(.simple-pagination) {
padding-top: 10px;
}
}
}
.box8 {
margin-left: 16px;
width: 792px;
height: 450px;
height: 100%;
border-radius: 10px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
......
<template>
<div class="view-box">
<el-empty v-if="!dataList?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" />
<div v-if="dataList.length" class="main-content-main">
<el-empty v-if="!listData?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" />
<div v-if="listData.length" class="main-content-main">
<div class="main-mask"
@wheel.prevent="handleWheel"
@mousedown="handleMouseDown"
......@@ -11,8 +11,8 @@
></div>
<div class="fishbone-container" :style="{ transform: `translate(${translateX}px, ${translateY}px) scale(${scale})`, transformOrigin: 'center center' }">
<!-- 主轴上的标签 -->
<div class="main-line" :style="{ width: dataList.length * 200 + 300 + 'px' }">
<div class="main-line-text" v-for="(item, index) in dataList" :key="'label-' + index"
<div class="main-line" :style="{ width: listData.length * 200 + 300 + 'px' }">
<div class="main-line-text" v-for="(item, index) in listData" :key="'label-' + index"
:class="{
'blue-theme': index < 2,
'green-theme': index >= 2 && index < 4,
......@@ -59,7 +59,7 @@
</div>
</div>
</div>
<div v-if="dataList.length" class="main-content-footer">
<div v-if="listData.length" class="main-content-footer">
<div class="footer-item footer-item1">
<div class="footer-item-bottom">
<div class="icon">
......@@ -67,9 +67,9 @@
</div>
<div class="text">
{{
`中国企业${cnEntityOnChainData.upstreamInternalCount ||
0}家(${formatRate(cnEntityOnChainData.upstreamInternalRate)}%),受制裁${cnEntityOnChainData.upstreamEntityCount
|| 0}家(${formatRate(cnEntityOnChainData.upstreamEntityRate)}%)`
`中国企业${baseData.upstreamInternalCount ||
0}家(${formatRate(baseData.upstreamInternalRate)}%),受制裁${baseData.upstreamEntityCount
|| 0}家(${formatRate(baseData.upstreamEntityRate)}%)`
}}
</div>
</div>
......@@ -82,9 +82,9 @@
</div>
<div class="text">
{{
`中国企业${cnEntityOnChainData.midstreamInternalCount ||
0}家(${formatRate(cnEntityOnChainData.midstreamInternalRate)}%),受制裁${cnEntityOnChainData.midstreamEntityCount
|| 0}家(${formatRate(cnEntityOnChainData.midstreamEntityRate)}%)`
`中国企业${baseData.midstreamInternalCount ||
0}家(${formatRate(baseData.midstreamInternalRate)}%),受制裁${baseData.midstreamEntityCount
|| 0}家(${formatRate(baseData.midstreamEntityRate)}%)`
}}
</div>
</div>
......@@ -97,9 +97,9 @@
</div>
<div class="text">
{{
`中国企业${cnEntityOnChainData.downstreamInternalCount ||
0}家(${formatRate(cnEntityOnChainData.downstreamInternalRate)}%),受制裁${cnEntityOnChainData.downstreamEntityCount
|| 0}家(${formatRate(cnEntityOnChainData.downstreamEntityRate)}%)`
`中国企业${baseData.downstreamInternalCount ||
0}家(${formatRate(baseData.downstreamInternalRate)}%),受制裁${baseData.downstreamEntityCount
|| 0}家(${formatRate(baseData.downstreamEntityRate)}%)`
}}
</div>
</div>
......@@ -110,12 +110,35 @@
</template>
<script setup name="ChartChain">
import { ref, onMounted } from "vue";
import { ref } from "vue";
import defaultIcon2 from "@/assets/icons/default-icon2.png";
import noticeIcon from "../assets/images/notice-icon.png";
import { getDeepMiningSelect, getDeepMiningIndustry, getDeepMiningIndustryFishbone, getDeepMiningIndustryEntity } from "@/api/exportControlV2.0";
// 缩放功能处理
const props = defineProps({
baseData: {
type: Object,
default: () => ({
upstreamInternalCount: 0,
upstreamInternalRate: 0,
upstreamEntityCount: 0,
upstreamEntityRate: 0,
midstreamInternalCount: 0,
midstreamInternalRate: 0,
midstreamEntityCount: 0,
midstreamEntityRate: 0,
downstreamInternalCount: 0,
downstreamInternalRate: 0,
downstreamEntityCount: 0,
downstreamEntityRate: 0
})
},
listData: {
type: Array,
default: () => ([])
}
});
// #region 缩放功能处理
const scale = ref(1)
const minScale = 0.1
const maxScale = 10
......@@ -128,7 +151,9 @@ const handleWheel = (e) => {
scale.value = Math.max(scale.value - 0.1, minScale)
}
}
// 移动功能处理
// #endregion 缩放功能处理
// #region 移动功能处理
const translateX = ref(0) // X轴位移
const translateY = ref(0) // Y轴位移
let isDragging = false
......@@ -149,40 +174,11 @@ const handleMouseDown = (e) => {
const handleMouseUp = () => {
isDragging = false
}
// #endregion 移动功能处理
// 实体清单-深度挖掘-产业链中国企业实体信息查询
const cnEntityOnChainData = ref({});
const getCnEntityOnChainData = async () => {
const currentSanction = sanctionList.value.find(item => item.id === currentSanctionId.value);
const date = currentSanction ? currentSanction.date : '';
// 确保 date 格式正确
const formattedDate = date && date.includes('年') ? date.replace('年', '-').replace('月', '-').replace('日', '') : date;
const params = {
date: formattedDate
};
if (selectedIndustryId.value) {
params.chainId = selectedIndustryId.value;
}
try {
const res = await getDeepMiningIndustryEntity(params);
console.log("企业信息", res)
if (res.code === 200 && res.data) {
cnEntityOnChainData.value = res.data;
} else {
cnEntityOnChainData.value = {};
}
} catch (error) {
console.error("获取产业链中国企业实体信息失败:", error);
cnEntityOnChainData.value = {};
}
}
// 产业链鱼骨数据
const dataList = ref([]);
// 奇数索引的数据组放在上方, 偶数索引的数据组放在下方
const onFilterData = (num) => {
return dataList.value.filter((_, index) => index % 2 === num);
return listData.value.filter((_, index) => index % 2 === num);
};
// 获取左侧显示的项目(前半部分)
const getLeftItems = items => {
......@@ -194,122 +190,11 @@ const getRightItems = items => {
const midpoint = Math.ceil(items.length / 2);
return items.slice(midpoint);
};
const getFishboneData = async () => {
const currentSanction = sanctionList.value.find(item => item.id === currentSanctionId.value);
const date = currentSanction ? currentSanction.date : '';
// 确保 date 格式正确
const formattedDate = date && date.includes('年') ? date.replace('年', '-').replace('月', '-').replace('日', '') : date;
const params = {
date: formattedDate
};
if (selectedIndustryId.value) {
params.chainId = selectedIndustryId.value;
}
try {
const res = await getDeepMiningIndustryFishbone(params);
console.log("获取产业链数据:", res);
if (res.code === 200 && res.data?.causes?.length) {
dataList.value = res.data.causes;
} else {
dataList.value = [];
}
} catch (error) {
console.error("获取产业链鱼骨图数据失败:", error);
dataList.value = [];
}
}
// 实体清单-深度挖掘-产业链列表信息
const selectedIndustryId = ref(null);
const getIndustryList = async () => {
try {
const res = await getDeepMiningIndustry();
if (res.code === 200 && res.data && res.data.length > 0) {
selectedIndustryId.value = res.data[0].id;
getFishboneData();
getCnEntityOnChainData();
} else {
selectedIndustryId.value = null;
}
} catch (error) {
console.error("获取产业链列表数据失败:", error);
selectedIndustryId.value = null;
}
}
// 获取选择制裁
const loading = ref(false);
const currentPage = ref(1);
const pageSize = ref(10000);
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: "实体清单",
isCn: false,
pageNum: currentPage.value,
pageSize: pageSize.value
};
try {
const res = await getDeepMiningSelect(params);
if (res.code === 200 && res.data && res.data.content) {
sanctionList.value = res.data.content.map(item => ({
id: item.id,
date: item.postDate,
title: item.name,
count: item.cnEntityCount,
unit: '家中国实体', // 接口未返回单位,暂时固定
summary: item.summary, // 保留额外信息备用
techDomainList: item.techDomainList // 保留额外信息备用
}));
// 默认选中第一条
if (sanctionList.value.length > 0) {
currentSanctionId.value = sanctionList.value[0].id;
// getFishboneData(); // 这里不需要调用,因为getIndustryList会调用
}
} else {
sanctionList.value = [];
}
} catch (error) {
console.error("获取选择制裁数据失败:", error);
sanctionList.value = [];
} finally {
loading.value = false;
}
}
const dateRange = ref(["2025-01-01", "2025-12-31"]);
const sanctionList = ref([
{ id: 1, date: "2025年2月8日", title: "实体清单更新", count: 2, unit: "家中国实体" },
{ id: 2, date: "2025年4月10日", title: "实体清单更新", count: 5, unit: "家中国实体" },
{ id: 3, date: "2025年6月29日", title: "实体清单更新", count: 6, unit: "家中国实体" },
{ id: 4, date: "2025年8月12日", title: "实体清单更新", count: 24, unit: "家中国实体" },
{ id: 5, date: "2025年8月19日", title: "实体清单更新", count: 11, unit: "家中国实体" },
{ id: 6, date: "2025年9月12日", title: "实体清单更新", count: 3, unit: "家中国实体" },
{ id: 7, date: "2025年9月26日", title: "实体清单更新", count: 6, unit: "家中国实体" },
{ id: 8, date: "2025年10月12日", title: "实体清单更新", count: 18, unit: "家中国实体" }
]);
const currentSanctionId = ref(5);
// 格式化比率
const formatRate = (rate, ratio=false) => {
const formatRate = (rate) => {
if (!rate) return '0.00';
return (rate * 100).toFixed(2);
};
onMounted(() => {
// 获取选择制裁
getDeepMiningSelectData();
// 获取产业链信息
getIndustryList();
});
</script>
<style scoped lang="scss">
......
......@@ -5,25 +5,25 @@
<div class="box1-main">
<div class="data-filter">
<div class="filter-select">
<el-select v-model="curAreaId" :empty-values="[null, undefined]" style="width: 100%">
<el-select v-model="areaInfo.id" :empty-values="[null, undefined]" style="width: 100%">
<el-option label="全部领域" value="" />
<el-option v-for="item in areaList" :key="item.id" :label="item.name" :value="item.id" />
<el-option v-for="item in areaInfo.list" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</div>
<div class="filter-input">
<el-input v-model="commandWord" @keyup.enter="handleSearch" style="width: 100%; height: 100%;" :suffix-icon="Search" placeholder="搜索实体" />
<el-input v-model="entityInfo.keyword" @keyup.enter="onDecreeEntities(1)" :suffix-icon="Search" placeholder="搜索实体" />
</div>
</div>
<div class="data-title">实体名称</div>
<div style="height: 20px; flex: auto;">
<el-empty v-if="!showCompanyList?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" />
<el-empty v-if="!entityInfo.list?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" />
<el-scrollbar height="100%" always>
<div class="list-data">
<div class="list-item" v-for="item in showCompanyList" :key="item.id" :class="{ 'item-active': activeEntityId === item.id }" @click="handleToCompanyDetail(item)">
<div class="list-item" v-for="item in entityInfo.list" :key="item.id" :class="{ 'item-active': entityInfo.id==item.id }" @click="handleToCompanyDetail(item)">
<div class="item-icon">
<img :src="defaultIcon2" alt="" class="item-img" />
</div>
<div class="item-name one-line-ellipsis">{{ item.name }}</div>
<div class="item-name one-line-ellipsis">{{ item.companyName }}</div>
<div class="item-icon item-icon-tag">
<img :src="noticeIcon" alt="" class="item-img" />
</div>
......@@ -33,16 +33,16 @@
</el-scrollbar>
</div>
<div class="pagination-info">
<div class="pagination-left">{{ `共 ${companyTotalNum} 家企业` }}</div>
<div class="pagination-left">{{ `共 ${entityInfo.total} 家企业` }}</div>
<div class="pagination-right">
<el-pagination
@current-change="handleCurrentChange"
:pageSize="pageSize"
:current-page="currentPage"
@current-change="onDecreeEntities"
:pageSize="entityInfo.pageSize"
:current-page="entityInfo.pageNum"
background
layout="prev, pager, next"
size="small"
:total="companyTotalNum"
:total="entityInfo.total"
/>
</div>
</div>
......@@ -68,9 +68,8 @@
</div>
</div>
<div class="title-right" v-if="contentType==1">
<el-select v-model="curAreaId" :empty-values="[null, undefined]" style="width: 100%">
<el-option label="全部领域" value="" />
<el-option v-for="item in areaList" :key="item.id" :label="item.name" :value="item.id" />
<el-select v-model="industryChain.id" style="width: 100%">
<el-option v-for="item in industryChain.list" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</div>
</div>
......@@ -78,10 +77,10 @@
<div class="box2-main">
<AiTips :tips="tips" />
<div class="graph-box" v-if="contentType==1">
<ChartChain />
<ChartChain :listData="fishbone.list" :baseData="fishbone.base" />
</div>
<div class="graph-box" v-if="contentType==2">
<GraphChart :nodes="graphData.nodes" :links="graphData.links" layoutType="force" />
<GraphChart :nodes="graphInfo.nodes" :links="graphInfo.links" layoutType="force" />
</div>
</div>
</AnalysisBox>
......@@ -91,8 +90,9 @@
<script setup>
import { ref, onMounted, reactive } from "vue";
import { useRoute } from "vue-router";
import { Search } from '@element-plus/icons-vue'
import { getDecreehylyList, getDecreeCompany } from "@/api/decree/influence";
import { getDecreehylyList, getDecreeEntities } from "@/api/decree/influence";
import ChartChain from "./com/ChartChain.vue";
import AiTips from "./com/AiTips.vue";
import GraphChart from "@/components/base/GraphChart/index.vue";
......@@ -104,9 +104,73 @@ import icon1620 from "./assets/images/icon1620.png";
import icon1621 from "./assets/images/icon1621.png";
import company from "./assets/images/company.png";
const route = useRoute();
const tips = "这项政令标志着中美AI竞争进入一个新阶段,其核心特征是 “精准封锁”与“体系输出”相结合。它短期内无疑会给中国AI产业链带来压力,但长期看,这场竞争更可能是一场围绕技术路线、生态系统和治理规则的持久战。"
// 关系图数据
const graphData = reactive({
// 行业领域
const areaInfo = reactive({
list: [],
id: "",
})
const handleGetHylyList = async () => {
try {
const res = await getDecreehylyList();
console.log("行业领域:", res);
if (res.code === 200) {
areaInfo.list = res.data || [];
}
} catch (error) {
areaInfo.list = [];
}
};
// 受影响实体
const entityInfo = reactive({
keyword: "",
pageSize: 10,
pageNum: 1,
total: 0,
list: [],
id: '',
})
const onDecreeEntities = async (page=1) => {
entityInfo.pageNum = page;
try {
const res = await getDecreeEntities({id: route.query.id});
console.log("受影响实体:", res);
if (res.code === 200 && res.data) {
entityInfo.list = res.data.companies;
entityInfo.total = res.data.companies.length;
}
} catch (error) {
console.log("获取受影响实体失败", error);
}
};
const handleToCompanyDetail = (item) => {
entityInfo.id = item.id;
};
const contentType = ref(1);
const headerContentType = (type) => {
contentType.value = type;
};
// 产业链
const industryChain = reactive({
list: [],
id: "",
})
// 产业链鱼骨图
const fishbone = reactive({
list: [],
base: {},
})
// 实体关系
const graphInfo = reactive({
leader: { id: 0, name: "泰丰先行" },
list: [
{ id: 1, name: "国轩高科", formatter: '持股' },
......@@ -122,9 +186,9 @@ const graphData = reactive({
links: [],
});
const initGraphChart = () => {
graphData.links = graphData.list.map(onFormatLink)
graphData.nodes = graphData.list.map(onFormatNode)
graphData.nodes.unshift(onFormatNode(graphData.leader))
graphInfo.links = graphInfo.list.map(onFormatLink)
graphInfo.nodes = graphInfo.list.map(onFormatNode)
graphInfo.nodes.unshift(onFormatNode(graphInfo.leader))
}
const onFormatLink = (item, index) => {
return {
......@@ -163,86 +227,8 @@ const onWordWrap = (word, num) => {
return label;
}
// 受影响实体
const companyList = ref([]);
const activeEntityId = ref(1);
const currentPage = ref(1);
const pageSize = ref(10);
const handleToCompanyDetail = (item) => {
activeEntityId.value = item.id;
};
const handleCurrentChange = page => {
currentPage.value = page;
};
const showCompanyList = ref([
{ id: 1, name: "北京市", status: "上市" },
{ id: 2, name: "上海市", status: "上市" },
{ id: 3, name: "广州市", status: "上市" },
{ id: 4, name: "深圳市", status: "上市" },
{ id: 5, name: "成都市", status: "上市" },
{ id: 7, name: "天津市", status: "上市" },
{ id: 9, name: "武汉市", status: "上市" },
{ id: 10, name: "西安市", status: "上市" },
]);
const handleGetCompanyListByArea = async () => {
const params = {
id: curAreaId.value
};
try {
const res = await getDecreeCompany(params);
console.log("行业领域公司列表", res);
if (res.code === 200 && res.data) {
companyList.value = res.data.map(item => {
return {
name: item.name,
id: item.id,
status: item.marketChange
};
});
companyTotalNum.value = companyList.value.length;
if (res.data?.length) handleToCompanyDetail(res.data[0])
} else {
companyList.value = [];
companyTotalNum.value = 0;
}
} catch (error) {
companyList.value = [];
companyTotalNum.value = 0;
}
};
// 指令搜索
const commandWord = ref("");
const handleSearch = () => {
};
// 行业领域
const curAreaId = ref("");
const areaList = ref([]);
const handleGetHylyList = async () => {
try {
const res = await getDecreehylyList();
console.log("行业领域列表", res);
if (res.code === 200 && res.data) {
areaList.value = res.data;
}
} catch (error) {
areaList.value = [];
}
};
// 产业链/实体关系
const contentType = ref(1);
const headerContentType = (type) => {
contentType.value = type;
};
// 企业影响分析
const companyTotalNum = ref(0); // 企业数量
onMounted(() => {
// handleGetCompanyListByArea();
onDecreeEntities();
initGraphChart()
handleGetHylyList();
});
......@@ -283,6 +269,11 @@ onMounted(() => {
box-shadow: 0 0 0 1px var(--el-border-color) inset;
box-sizing: border-box;
height: 32px;
:deep(.el-input) {
height: 100%;
width: 100%;
}
}
}
......
......@@ -53,7 +53,7 @@ export default defineConfig({
'/api': {
target: 'http://8.140.26.4:9085/',
// target: 'http://192.168.0.6:28080/',
// target: 'http://172.20.10.3:28080/',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论