提交 72613fb4 authored 作者: 张伊明's avatar 张伊明

合并分支 'zy-dev' 到 'pre'

Zy dev 查看合并请求 !388
流水线 #640 已通过 于阶段
...@@ -306,3 +306,11 @@ export function getNetProfit(params) { ...@@ -306,3 +306,11 @@ export function getNetProfit(params) {
params params
}) })
} }
// 获取调查进展状态列表
export function getAllProgressStatus() {
return request({
method: 'GET',
url: `/api/marketsearchHome/getAllInvestProgressStatus`,
})
}
\ No newline at end of file
...@@ -265,12 +265,13 @@ const onHighlightedText = (text, nounList) => { ...@@ -265,12 +265,13 @@ const onHighlightedText = (text, nounList) => {
const key = `${searchInterval.start}-${searchInterval.end}`; const key = `${searchInterval.start}-${searchInterval.end}`;
if (end === searchInterval.end && !pointAdded.has(key)) { if (end === searchInterval.end && !pointAdded.has(key)) {
findWordMax.value++; findWordMax.value++;
list.push({ point: true, class: "" }); list.push({ point: findWordMax.value, class: "" });
pointAdded.add(key); pointAdded.add(key);
break; break;
} }
} }
} }
console.log('看看格式', list);
return list; return list;
}; };
......
...@@ -19,7 +19,7 @@ const decreeRoutes = [ ...@@ -19,7 +19,7 @@ const decreeRoutes = [
name: "Decree", name: "Decree",
component: Decree, component: Decree,
meta: { meta: {
title: "科技政令概", title: "科技政令概",
isShowHeader: true isShowHeader: true
} }
}, },
......
...@@ -6,19 +6,19 @@ ...@@ -6,19 +6,19 @@
<div class="hard-num text-title-2-show">{{ organizationInfo.total }}</div> <div class="hard-num text-title-2-show">{{ organizationInfo.total }}</div>
<div style="width: 0px; flex: auto;"></div> <div style="width: 0px; flex: auto;"></div>
<div class="hard-input"> <div class="hard-input">
<el-input v-model="organizationInfo.keyWord" @keyup.enter="onAllOrganization()" <el-input v-model="organizationInfo.keyWord" @keyup.enter="onAllOrganization()" @clear="onAllOrganization()"
style="width:100%; height:100%;" :suffix-icon="Search" placeholder="搜索机构" /> style="width:100%; height:100%;" :prefix-icon="Search" placeholder="搜索机构" clearable />
</div> </div>
<div class="hard-time"> <div class="hard-time">
<el-select v-model="organizationInfo.isSort" @change="onAllOrganization()" placeholder="发布时间" <el-select v-model="organizationInfo.isSort" @change="onAllOrganization()" style="width:100%;">
style="width:160px; margin-left:8px;">
<template #prefix> <template #prefix>
<div class="icon1"> <div class="icon1">
<img v-if="isSort" src="@/assets/icons/shengxu1.png" alt="" /> <img src="@/assets/icons/jiangxu1.png" alt="" />
<img v-else src="@/assets/icons/jiangxu1.png" alt="" /> <!-- <img src="@/assets/icons/shengxu1.png" alt="" /> -->
</div> </div>
</template> </template>
<el-option label="政令数量" :value="1" /> <el-option label="政令数据总量" :value="1" />
<el-option label="政令新增数量" :value="2" />
</el-select> </el-select>
</div> </div>
</div> </div>
...@@ -30,13 +30,12 @@ ...@@ -30,13 +30,12 @@
<TimeTabPane @time-click="handleDateChange" activeTime="近一年" /> <TimeTabPane @time-click="handleDateChange" activeTime="近一年" />
</div> </div>
<div class="organization-list" ref="refOrganization" v-loading="organizationInfo.loading"> <div class="organization-list" ref="refOrganization" v-loading="organizationInfo.loading">
<div class="organization-item" v-for="(item, index) in organizationInfo.list" :key="index" <div class="organization-item" v-for="item in organizationInfo.list" :key="item.orgId">
@click="handleToInstitution(item)">
<div class="item-left"> <div class="item-left">
<img :src="item.orgImage || DefaultIcon2" alt="" /> <img :src="item.orgImage || DefaultIcon2" alt="" />
</div> </div>
<div class="item-right one-line-ellipsis">{{ item.orgName }}</div> <div class="item-right one-line-ellipsis text-click-hover" @click="handleToInstitution(item)">{{ item.orgName }}</div>
<div class="item-total">{{ item.total }}项</div> <div class="item-total text-click-hover" @click="handleToDataLibrary(item)">{{ item.total }}项</div>
<el-icon color="var(--color-primary-100)"> <el-icon color="var(--color-primary-100)">
<ArrowRightBold /> <ArrowRightBold />
</el-icon> </el-icon>
...@@ -50,17 +49,15 @@ ...@@ -50,17 +49,15 @@
</div> </div>
</div> </div>
<div class="back-bnt" @click="router.back()"> <div class="back-bnt" @click="router.back()">
<el-icon> <el-icon> <Back /> </el-icon>
<Back />
</el-icon>
<div style="margin-left: 6px;">返回</div> <div style="margin-left: 6px;">返回</div>
</div> </div>
</div> </div>
</template> </template>
<script setup name="index"> <script setup>
import { onMounted, reactive, ref } from "vue" import { onMounted, reactive, ref } from "vue"
import { Search } from '@element-plus/icons-vue' import { Search, Back } from '@element-plus/icons-vue'
import router from "@/router"; import router from "@/router";
import TimeTabPane from '@/components/base/TimeTabPane/index.vue'; import TimeTabPane from '@/components/base/TimeTabPane/index.vue';
...@@ -112,9 +109,7 @@ const handleToInstitution = item => { ...@@ -112,9 +109,7 @@ const handleToInstitution = item => {
window.sessionStorage.setItem("curTabName", item.orgName); window.sessionStorage.setItem("curTabName", item.orgName);
const curRoute = router.resolve({ const curRoute = router.resolve({
path: "/institution", path: "/institution",
query: { query: { id: item.orgId }
id: item.orgId
}
}); });
window.open(curRoute.href, "_blank"); window.open(curRoute.href, "_blank");
// router.push({ // router.push({
...@@ -125,6 +120,15 @@ const handleToInstitution = item => { ...@@ -125,6 +120,15 @@ const handleToInstitution = item => {
// }) // })
}; };
// 下钻至数据资源库
const handleToDataLibrary = (item) => {
const route = router.resolve({
path: "/dataLibrary/dataDecree",
query: { orgnizationName: item.orgName }
});
window.open(route.href, "_blank");
}
const refOrganization = ref() const refOrganization = ref()
onMounted(() => { onMounted(() => {
// 根据元素的高度决定分页显示的机构数量 // 根据元素的高度决定分页显示的机构数量
...@@ -196,15 +200,14 @@ onMounted(() => { ...@@ -196,15 +200,14 @@ onMounted(() => {
background-color: var(--el-fill-color-blank); background-color: var(--el-fill-color-blank);
border-radius: var(--el-border-radius-base); border-radius: var(--el-border-radius-base);
box-shadow: 0 0 0 1px var(--el-border-color) inset; box-shadow: 0 0 0 1px var(--el-border-color) inset;
box-sizing: border-box;
margin-left: 20px;
width: 160px; width: 160px;
height: 32px; height: 32px;
} }
.hard-time { .hard-time {
height: 42px; height: 32px;
padding: 5px 0; width: 160px;
margin-left: 8px;
.icon1 { .icon1 {
width: 11px; width: 11px;
...@@ -269,7 +272,6 @@ onMounted(() => { ...@@ -269,7 +272,6 @@ onMounted(() => {
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1); box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
align-items: center; align-items: center;
justify-content: center; justify-content: center;
cursor: pointer;
transition: transform 0.3s ease, box-shadow 0.3s ease; transition: transform 0.3s ease, box-shadow 0.3s ease;
position: relative; position: relative;
......
...@@ -7,28 +7,6 @@ ...@@ -7,28 +7,6 @@
<SearchContainer style="margin-bottom: 0; margin-top: 48px; height: fit-content" v-if="containerRef" <SearchContainer style="margin-bottom: 0; margin-top: 48px; height: fit-content" v-if="containerRef"
placeholder="搜索政令" :containerRef="containerRef" areaName="政令" /> placeholder="搜索政令" :containerRef="containerRef" areaName="政令" />
</div> </div>
<!-- <div class="home-main-header-footer" v-show="!isShow">
<div class="home-main-header-footer-item">
<div class="item-top">3.8T</div>
<div class="item-footer">数据量</div>
</div>
<div class="home-main-header-footer-item">
<div class="item-top">28</div>
<div class="item-footer">科技动向</div>
</div>
<div class="home-main-header-footer-item">
<div class="item-top">326</div>
<div class="item-footer">总统政令</div>
</div>
<div class="home-main-header-footer-item">
<div class="item-top">341</div>
<div class="item-footer">通过法案</div>
</div>
<div class="home-main-header-footer-item">
<div class="item-top">285</div>
<div class="item-footer">分析报告</div>
</div>
</div> -->
<SummaryCardsPanel <SummaryCardsPanel
descriptionText="近期美国各联邦政府机构发布涉华政令数量汇总" descriptionText="近期美国各联邦政府机构发布涉华政令数量汇总"
:cards="keyOrganizationCards" :cards="keyOrganizationCards"
...@@ -51,7 +29,7 @@ ...@@ -51,7 +29,7 @@
<div class="center-top"> <div class="center-top">
<OverviewMainBox class="box1" title="最新科技政令" @toDetail="handleClickOrder"> <OverviewMainBox class="box1" title="最新科技政令" @toDetail="handleClickOrder">
<template #header-icon> <template #header-icon>
<img style="width: 100%; height: 100%" src="./assets/images/box1-header-icon.png" alt="" /> <img style="width: 100%; height: 100%" src="./assets/images/icon_1596.png" alt="" />
</template> </template>
<div class="box1-left" @click="handleSwithCurDecree('left')"> <div class="box1-left" @click="handleSwithCurDecree('left')">
<div class="icon"> <div class="icon">
...@@ -77,25 +55,20 @@ ...@@ -77,25 +55,20 @@
</div> </div>
</div> </div>
<div class="box1-main-right"> <div class="box1-main-right">
<div class="box1-main-right-title"> <div class="box1-main-right-title">{{ item.name }}</div>
{{ item.name }} <div class="box1-main-right-info" v-if="item.industryList?.length">
</div>
<div class="box1-main-right-info">
<AreaTag v-for="(tag, index) in item.industryList" :key="index" :tagName="tag.industryName" /> <AreaTag v-for="(tag, index) in item.industryList" :key="index" :tagName="tag.industryName" />
</div> </div>
<div class="box1-main-right-center"> <div class="box1-main-right-center">{{ item.describe }}</div>
{{ item.describe }} <div style="height: 0; flex: auto;"></div>
</div>
<div class="box1-main-right-footer"> <div class="box1-main-right-footer">
<div class="footer-left">{{ item.postDate }}</div> <div class="footer-left">{{ item.postDate }}</div>
<div class="footer-right"> <!-- <div class="footer-right">
<div class="footer-right-item1"> <div class="footer-right-item1">{{ item.officialUrl }}</div>
{{ item.officialUrl }}
</div>
<div class="footer-right-item2"> <div class="footer-right-item2">
<img src="./assets/images/open-icon.png" alt="" /> <img src="./assets/images/open-icon.png" alt="" />
</div> </div>
</div> </div> -->
</div> </div>
</div> </div>
</div> </div>
...@@ -112,204 +85,163 @@ ...@@ -112,204 +85,163 @@
<MessageBubble :messageList="messageList" @person-click="handleClickPerson" @info-click="handleGetMessage" <MessageBubble :messageList="messageList" @person-click="handleClickPerson" @info-click="handleGetMessage"
imageUrl="img" @more-click="handleToSocialDetail" /> imageUrl="img" @more-click="handleToSocialDetail" />
</div> </div>
<DivideHeader id="position3" class="divide3" :titleText="'数据总览'"></DivideHeader> <DivideHeader id="position3" class="divide3" :titleText="'全景概览'"></DivideHeader>
<div class="center-footer"> <div class="center-footer">
<div class="box5"> <div class="box5" v-loading="box5Params.loading">
<div class="box5-header"> <div class="box5-header">
<div class="box5-header-icon"> <div class="box5-header-icon">
<img src="./assets/images/box3-header-icon.png" alt="" /> <img src="./assets/images/box3-header-icon.png" alt="" />
</div> </div>
<div class="box5-header-title">{{ "数量变化趋势" }}</div> <div class="box5-header-title">{{ "数量变化趋势" }}</div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleBox5" v-model="box5Params.proposeName" :empty-values="[null, undefined]" <el-select @change="getBox5Data" v-model="box5Params.proposeName" :empty-values="[null, undefined]" style="width:150px" filterable>
style="width:150px">
<el-option label="全部政府部门" value="" /> <el-option label="全部政府部门" value="" />
<el-option v-for="item in keyOrganizationList" :key="item.orgId" :label="item.orgName" <el-option v-for="item in govInsList" :key="item.orgId" :label="item.orgName" :value="item.orgId" />
:value="item.orgId" />
</el-select> </el-select>
</div> </div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleBox5" v-model="box5Params.domainId" :empty-values="[null, undefined]" <el-select @change="getBox5Data" v-model="box5Params.domainId" :empty-values="[null, undefined]" style="width:120px">
style="width:120px">
<el-option label="全部领域" value="" /> <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 areaList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</div> </div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleBox5" v-model="box5Params.year" placeholder="选择时间" style="width:120px"> <el-select @change="getBox5Data" v-model="box5Params.year" placeholder="选择时间" style="width:120px">
<el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</div> </div>
</div> </div>
<div class="box5-main" v-loading="box5Params.loading"> <div class="box5-main" style="padding-top: 16px;">
<div class="box5-chart" id="chart1"></div> <div v-if="chart1Data.title?.length" class="box5-chart" id="chart1"></div>
</div> <el-empty v-else style="padding-top: 100px;" description="暂无数据" :image-size="100" />
<div class="data-origin-box">
<div class="data-origin-icon">
<img :src="tipsTcon" alt="">
</div>
<div class="data-origin-text">科技政令数量变化趋势,数据来源:美国各行政机构官网</div>
</div> </div>
<div class="ai-pane"> <div style="padding: 0px 22px 14px;">
<AiButton /> <TipTab text="数据来源:美国各行政机构官网" />
<AiPane :aiContent="aiContent.content1" />
</div> </div>
<AiReport ref="refAiReport1"></AiReport>
</div> </div>
<div class="box5" v-loading="box6Params.loading">
<div class="box5">
<div class="box5-header"> <div class="box5-header">
<div class="box5-header-icon"> <div class="box5-header-icon">
<img src="./assets/images/box4-header-icon.png" alt="" /> <img src="./assets/images/box4-header-icon.png" alt="" />
</div> </div>
<div class="box5-header-title">{{ "领域分布情况" }}</div> <div class="box5-header-title">{{ "领域分布情况" }}</div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleBox6YearChange" v-model="box6Params.proposeName" <el-select @change="getBox6Data" v-model="box6Params.proposeName" :empty-values="[null, undefined]" style="width:150px" filterable>
:empty-values="[null, undefined]" style="width:150px">
<el-option label="全部政府部门" value="" /> <el-option label="全部政府部门" value="" />
<el-option v-for="item in keyOrganizationList" :key="item.orgId" :label="item.orgName" <el-option v-for="item in govInsList" :key="item.orgId" :label="item.orgName" :value="item.orgId" />
:value="item.orgId" />
</el-select> </el-select>
</div> </div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleBox6YearChange" v-model="box6Params.year" placeholder="选择时间" <el-select @change="getBox6Data" v-model="box6Params.year" placeholder="选择时间" style="width: 120px">
style="width: 120px">
<el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</div> </div>
</div> </div>
<div class="box5-main" v-loading="box6Params.loading"> <div class="box5-main" style="padding: 16px 22px 0;">
<div class="box5-chart" id="chart2"></div> <div v-if="chart2Data.length" class="box5-chart" ref="box6Ref"></div>
</div> <el-empty v-else style="padding-top: 100px;" description="暂无数据" :image-size="100" />
<div class="data-origin-box">
<div class="data-origin-icon">
<img :src="tipsTcon" alt="">
</div> </div>
<div class="data-origin-text">科技政令领域分布情况,数据来源:美国各行政机构官网</div> <div style="padding: 0px 22px 14px;">
</div> <TipTab text="数据来源:美国各行政机构官网" />
<div class="ai-pane">
<AiButton />
<AiPane :aiContent="aiContent.content2" />
</div> </div>
<AiReport ref="refAiReport2"></AiReport>
</div> </div>
</div> </div>
<div class="center-footer1"> <div class="center-footer1">
<div class="box7"> <div class="box7" v-loading="box7Params.loading">
<div class="box7-header"> <div class="box7-header">
<div class="header-icon"> <div class="header-icon">
<img src="./assets/images/box5-header-icon.png" alt="" /> <img src="./assets/images/box5-header-icon.png" alt="" />
</div> </div>
<div class="header-title">{{ "关键科技政令" }}</div> <div class="header-title">{{ "关键科技政令" }}</div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleGetKeyDecree" v-model="box7Params.proposeName" <el-select @change="getBox7Data(1)" v-model="box7Params.proposeName" :empty-values="[null, undefined]" style="width:150px" filterable>
:empty-values="[null, undefined]" style="width:150px">
<el-option label="全部政府部门" value="" /> <el-option label="全部政府部门" value="" />
<el-option v-for="item in keyOrganizationList" :key="item.orgId" :label="item.orgName" <el-option v-for="item in govInsList" :key="item.orgId" :label="item.orgName" :value="item.orgId" />
:value="item.orgId" />
</el-select> </el-select>
</div> </div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleGetKeyDecree" v-model="box7Params.domainId" :empty-values="[null, undefined]" <el-select @change="getBox7Data(1)" v-model="box7Params.domainId" :empty-values="[null, undefined]" style="width:120px">
style="width:120px">
<el-option label="全部领域" value="" /> <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 areaList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</div> </div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleGetKeyDecree" v-model="box7Params.year" placeholder="选择时间" <el-select @change="getBox7Data(1)" v-model="box7Params.year" placeholder="选择时间" style="width:120px">
style="width:120px">
<el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</div> </div>
</div> </div>
<div class="box7-main" v-loading="box7Params.loading"> <div class="box7-main">
<div class="box7-list"> <div v-if="keyDecreeList?.length" class="box7-list">
<div class="box7-item" v-for="(item, index) in keyDecreeList" :key="index" <div class="box7-item" v-for="(item, index) in keyDecreeList" :key="index" @click="onNavigateToDetail(item)">
@click="onNavigateToDetail(item)">
<div class="icon"> <div class="icon">
<img src="./assets/images/warning.png" alt="" /> <img src="./assets/images/warning.png" alt="" />
</div> </div>
<div class="info"> <div class="info">
<div class="info-header"> <div class="info-header">
<div class="title one-line-ellipsis">{{ item.title }}</div> <div class="title one-line-ellipsis">{{ item.name }}</div>
<div class="time">{{ item.time }}</div> <div class="time">{{ item.postDate }}</div>
</div>
<div class="info-content one-line-ellipsis">{{ item.content || "暂无数据" }}</div>
</div> </div>
<div class="info-content one-line-ellipsis">{{ item.describe || "暂无数据" }}</div>
</div> </div>
</div> </div>
</div> </div>
<SimplePagination v-model:current-page="keyDecreeInfo.page" :page-size="keyDecreeInfo.size" <el-empty v-else style="padding-top: 100px;" description="暂无数据" :image-size="100" />
:total="keyDecreeInfo.total" @page-change="handleGetKeyDecree" />
<div class="data-origin-box">
<div class="data-origin-icon">
<img :src="tipsTcon" alt="">
</div> </div>
<div class="data-origin-text">关键科技政令列表,数据来源:美国各行政机构官网</div> <SimplePagination v-if="keyDecreeList?.length" v-model:current-page="keyDecreeInfo.page" :page-size="keyDecreeInfo.size" :total="keyDecreeInfo.total" @page-change="getBox7Data" />
<div style="padding: 14px 22px;">
<TipTab text="数据来源:美国各行政机构官网" />
</div> </div>
</div> </div>
<div class="box8"> <div class="box8" v-loading="box8Params.loading">
<div class="box8-header"> <div class="box8-header">
<div class="header-icon"> <div class="header-icon">
<img src="./assets/images/box5-header-icon.png" alt="" /> <img src="./assets/images/box5-header-icon.png" alt="" />
</div> </div>
<div class="header-title">{{ "关键条款词云" }}</div> <div class="header-title">{{ "关键条款词云" }}</div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleGetDecreeKeyInstruction" v-model="box8Params.proposeName" <el-select @change="getBox8Data" v-model="box8Params.proposeName" :empty-values="[null, undefined]" style="width:150px" filterable>
:empty-values="[null, undefined]" style="width:150px">
<el-option label="全部政府部门" value="" /> <el-option label="全部政府部门" value="" />
<el-option v-for="item in keyOrganizationList" :key="item.orgId" :label="item.orgName" <el-option v-for="item in govInsList" :key="item.orgId" :label="item.orgName" :value="item.orgId" />
:value="item.orgId" />
</el-select> </el-select>
</div> </div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleGetDecreeKeyInstruction" v-model="box8Params.domainId" <el-select @change="getBox8Data" v-model="box8Params.domainId" :empty-values="[null, undefined]" style="width:120px">
:empty-values="[null, undefined]" style="width:120px">
<el-option label="全部领域" value="" /> <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 areaList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</div> </div>
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<el-select @change="handleGetDecreeKeyInstruction" v-model="box8Params.year" placeholder="选择时间" <el-select @change="getBox8Data" v-model="box8Params.year" placeholder="选择时间" style="width:120px">
style="width:120px">
<el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</div> </div>
</div> </div>
<div class="box8-content" v-loading="box8Params.loading"> <div class="box8-content">
<WordCloudChart v-if="wordCloudData?.length" :data="wordCloudData" width="100%" height="100%" /> <WordCloudChart v-if="wordCloudData?.length" :data="wordCloudData" width="100%" height="100%" />
<el-empty v-else style="padding-top: 100px;" description="暂无数据" :image-size="100" />
</div> </div>
<div class="data-origin-box"> <div style="padding: 14px 22px;">
<div class="data-origin-icon"> <TipTab text="数据来源:美国各行政机构官网" />
<img :src="tipsTcon" alt="">
</div>
<div class="data-origin-text">科技政令重点条款词云,数据来源:美国各行政机构官网</div>
</div> </div>
<AiReport ref="refAiReport3"></AiReport>
</div> </div>
</div> </div>
</div> </div>
<div class="home-main-footer"> <div class="home-main-footer">
<DivideHeader id="position4" class="divide4" :titleText="'科技政令库'"></DivideHeader> <DivideHeader id="position4" class="divide4" :titleText="'科技政令数据库'"></DivideHeader>
<div class="home-main-footer-header"> <div class="home-main-footer-head">
<div class="search-box"> <div class="search-box">
<el-select v-model="searchType" :empty-values="[null, undefined]" style="width: 100%" filterable> <el-select v-model="box9Params.name" :empty-values="[null, undefined]" @change="getDecreeList(1)" style="width: 100%" filterable>
<el-option label="全部政府部门" value="" /> <el-option label="全部政府部门" value="" />
<el-option v-for="item in govInsList" :key="item.orgId" :label="item.orgName" :value="item.orgId" /> <el-option v-for="item in govInsList" :key="item.orgId" :label="item.orgName" :value="item.orgId" />
</el-select> </el-select>
</div> </div>
<div style="flex: auto;"></div> <div style="flex: auto;"></div>
<el-checkbox v-model="isChina">只看涉华政令</el-checkbox> <el-checkbox @change="getDecreeList(1)" v-model="box9Params.isCN">只看涉华政令</el-checkbox>
<div class="select-box"> <TimeSortSelectBox style="margin-left:12px;" @handle-px-change="handlePxChange"></TimeSortSelectBox>
<el-select v-model="isSort" placeholder="发布时间" style="width:120px; margin-left:8px;">
<template #prefix>
<div class="icon1">
<img v-if="isSort" src="@/assets/icons/shengxu1.png" alt="" />
<img v-else src="@/assets/icons/jiangxu1.png" alt="" />
</div>
</template>
<el-option label="正序" :value="true" />
<el-option label="倒序" :value="false" />
</el-select>
</div>
</div> </div>
<div class="home-main-footer-main"> <div class="home-main-footer-main">
<div class="left"> <div class="left">
...@@ -319,13 +251,12 @@ ...@@ -319,13 +251,12 @@
<div class="title">{{ "政令类型" }}</div> <div class="title">{{ "政令类型" }}</div>
</div> </div>
<div class="select-main"> <div class="select-main">
<div class="checkbox-group"> <el-checkbox-group class="checkbox-group" v-model="checkedDecreeType" @change="handleTypeChange">
<el-checkbox v-for="type in decreeTypeList" :key="type.id" v-model="checkedDecreeType" <el-checkbox label="" class="filter-checkbox">{{ "全部类型" }}</el-checkbox>
:label="type.typeId" style="width: 180px" class="filter-checkbox" <el-checkbox v-for="item in decreeTypeList" :key="item.typeId" :label="item.typeId" class="filter-checkbox">
@change="handleChangeCheckedDecreeType"> {{ item.typeName }}
{{ type.typeName }}
</el-checkbox> </el-checkbox>
</div> </el-checkbox-group>
</div> </div>
</div> </div>
<div class="select-box"> <div class="select-box">
...@@ -349,43 +280,44 @@ ...@@ -349,43 +280,44 @@
</div> </div>
<div class="select-main"> <div class="select-main">
<el-checkbox-group class="checkbox-group" v-model="activePubTime" @change="handlePubTimeChange"> <el-checkbox-group class="checkbox-group" v-model="activePubTime" @change="handlePubTimeChange">
<el-checkbox v-for="time in pubTime" :key="time.id" :label="time.id" class="filter-checkbox"> <el-checkbox class="filter-checkbox" label="">{{ "全部时间" }}</el-checkbox>
{{ time.name }} <el-checkbox class="filter-checkbox" v-for="time in pubTime" :key="time.value" :label="time.value">
{{ time.label }}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
</div> </div>
</div> </div>
</div> </div>
<div class="right"> <div class="right" v-loading="box9Params.loading">
<div class="content-header"> <div class="content-header">
<div class="icon"> <div class="icon">
<img src="./assets/images/footer-header-icon.png" alt="" /> <img src="./assets/images/footer-header-icon.png" alt="" />
</div> </div>
<div class="title">{{ "政令库" }}</div> <div class="title">{{ "政令库" }}</div>
</div> </div>
<div class="content-box" v-show="decreeList"> <div class="content-box">
<el-empty v-if="!decreeList.length" style="padding-top: 160px;" description="暂无数据" :image-size="100" />
<div class="main-item" v-for="(item, index) in decreeList" :key="index" @click="onNavigateToDetail(item)"> <div class="main-item" v-for="(item, index) in decreeList" :key="index" @click="onNavigateToDetail(item)">
<div class="main-item-left"> <div class="main-item-left">
<div class="left-left"> <div class="left-left">
{{ item.time?.split("-")[0] }}<br />{{ item.time?.split("-")[1] }}月{{ {{ item.postDate?.split("-")[0] }}<br />
item.time?.split("-")[2] {{ item.postDate?.split("-")[1] }}月{{ item.postDate?.split("-")[2] }}日
}}日
</div> </div>
<div class="left-right"> <div class="left-right">
<div class="icon"> <div class="icon">
<img :src="item.img ? item.img : DefaultIcon2" alt="" /> <img :src="item.orgImage || DefaultIcon2" alt="" />
</div> </div>
<div class="line" v-if="index !== 9 && index !== totalDecreesNum - 1"></div> <div class="line" v-if="index !== 9 && index !== totalDecreesNum - 1"></div>
</div> </div>
</div> </div>
<div class="main-item-center"> <div class="main-item-center">
<div class="center-header"> <div class="center-header">
<div class="title">{{ item.title }}</div> <div class="title one-line-ellipsis">{{ `${item.proposeOrgName}: ${item.name}` }}</div>
<!-- <div class="type-box type1">{{ item.type }}</div> --> <div class="type-box type1">{{ '行政命令' }}</div>
</div> </div>
<div class="desc">{{ item.desc }}</div> <div class="desc">{{ item.describe }}</div>
<div class="tag-box"> <div class="tag-box">
<AreaTag v-for="(tag, index) in item.tagList" :key="index" :tagName="tag.industryName" /> <AreaTag v-for="(tag, index) in item.industryList" :key="index" :tagName="tag.industryName" />
</div> </div>
</div> </div>
</div> </div>
...@@ -395,7 +327,7 @@ ...@@ -395,7 +327,7 @@
{{ `共 ${totalDecreesNum} 项` }} {{ `共 ${totalDecreesNum} 项` }}
</div> </div>
<div class="footer-right"> <div class="footer-right">
<el-pagination @current-change="handleCurrentChange" :pageSize="10" :current-page="currentPage" <el-pagination @current-change="handleCurrentChange" :pageSize="box9Params.size" :current-page="box9Params.page"
background layout="prev, pager, next" :total="totalDecreesNum" /> background layout="prev, pager, next" :total="totalDecreesNum" />
</div> </div>
</div> </div>
...@@ -414,15 +346,16 @@ ...@@ -414,15 +346,16 @@
</template> </template>
<script setup> <script setup>
import { onMounted, ref, watch, nextTick, reactive, computed } from "vue"; import { onMounted, ref, nextTick, reactive, computed } from "vue";
import router from "@/router"; import router from "@/router";
import { navigateToViewRiskSignal } from "@/utils/riskSignalOverviewNavigate"; import { navigateToViewRiskSignal } from "@/utils/riskSignalOverviewNavigate";
import RiskSignalOverviewDetailDialog from "@/components/base/RiskSignalOverviewDetailDialog/index.vue"; import RiskSignalOverviewDetailDialog from "@/components/base/RiskSignalOverviewDetailDialog/index.vue";
import WordCloudChart from "@/components/base/WordCloundChart/index.vue" import WordCloudChart from "@/components/base/WordCloundChart/index.vue"
import SimplePagination from "@/components/SimplePagination.vue"; import SimplePagination from "@/components/SimplePagination.vue";
import SummaryCardsPanel from "@/components/base/SummaryCardsPanel/index.vue"; import SummaryCardsPanel from "@/components/base/SummaryCardsPanel/index.vue";
import AiButton from '@/components/base/Ai/AiButton/index.vue'; import AiReport from '@/views/marketAccessRestrictions/marketAccessHome/com/AiReport.vue';
import AiPane from '@/components/base/Ai/AiPane/index.vue'; import TimeSortSelectBox from '@/components/base/TimeSortSelectBox/index.vue';
import TipTab from "@/components/base/TipTab/index.vue"
import { import {
getDepartmentList, getDepartmentList,
getLatestDecree, getLatestDecree,
...@@ -441,31 +374,26 @@ import { getNews, getSocialMedia } from "@/api/general/index"; ...@@ -441,31 +374,26 @@ import { getNews, getSocialMedia } from "@/api/general/index";
import DivideHeader from "@/components/DivideHeader.vue"; import DivideHeader from "@/components/DivideHeader.vue";
import { useContainerScroll } from "@/hooks/useScrollShow"; import { useContainerScroll } from "@/hooks/useScrollShow";
import getBarChart from "./utils/barChart"; import getBarChart from "./utils/barChart";
import getPieChart from "./utils/piechart"; import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js";
import setChart from "@/utils/setChart"; import setChart from "@/utils/setChart";
import DefaultIcon2 from "@/assets/icons/default-icon2.png"; import DefaultIcon2 from "@/assets/icons/default-icon2.png";
import tipsTcon from "./assets/images/tips-icon.png"; import tipsTcon from "./assets/images/tips-icon.png";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { getAIReport, getNearYearList } from "@/views/marketAccessRestrictions/utils/index.ts" import { getNearYearList } from "@/views/marketAccessRestrictions/utils/index.ts"
import { useGotoNewsDetail } from '@/router/modules/news'; import { useGotoNewsDetail } from '@/router/modules/news';
const containerRef = ref(null); const containerRef = ref(null);
const { isShow } = useContainerScroll(containerRef); const { isShow } = useContainerScroll(containerRef);
const currentPage = ref(1);
const pageSize = ref(10);
// 处理页码改变事件 // 处理页码改变事件
const handleCurrentChange = page => { const handleCurrentChange = page => {
currentPage.value = page;
handleToPosi('position4') handleToPosi('position4')
handleGetDecreeOrderList(); getDecreeList(page);
}; };
// 机构列表 // 机构列表
const govInsList = ref([]); const govInsList = ref([]);
const checkedGovIns = ref([]);
const handleGetDepartmentList = async () => { const handleGetDepartmentList = async () => {
try { try {
const res = await getDepartmentList({}); const res = await getDepartmentList({});
...@@ -473,9 +401,7 @@ const handleGetDepartmentList = async () => { ...@@ -473,9 +401,7 @@ const handleGetDepartmentList = async () => {
if (res.code === 200) { if (res.code === 200) {
govInsList.value = res.data.orgList; govInsList.value = res.data.orgList;
} }
} catch (error) { } catch (error) {}
console.error("获取机构列表error", error);
}
}; };
// 跳转行政机构主页 // 跳转行政机构主页
const handleToInstitution = item => { const handleToInstitution = item => {
...@@ -540,9 +466,7 @@ const handleGetLatestDecree = async () => { ...@@ -540,9 +466,7 @@ const handleGetLatestDecree = async () => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
box1DataList.value = res.data; box1DataList.value = res.data;
} }
} catch (error) { } catch (error) {}
console.error("最新科技政令error", error);
}
}; };
const handleBox1 = async () => { const handleBox1 = async () => {
...@@ -588,9 +512,7 @@ const handlegetDecreeRiskSignal = async () => { ...@@ -588,9 +512,7 @@ const handlegetDecreeRiskSignal = async () => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
warningList.value = res.data.map(item => ({ ...item, id: item.orderId })); warningList.value = res.data.map(item => ({ ...item, id: item.orderId }));
} }
} catch (error) { } catch (error) {}
console.error("风险信号error", error);
}
}; };
handlegetDecreeRiskSignal(); handlegetDecreeRiskSignal();
...@@ -624,9 +546,7 @@ const handleGetNews = async () => { ...@@ -624,9 +546,7 @@ const handleGetNews = async () => {
}; };
}); });
} }
} catch (error) { } catch (error) {}
console.error("新闻资讯error", error);
}
}; };
// 点击新闻条目,跳转到新闻分析页 // 点击新闻条目,跳转到新闻分析页
const gotoNewsDetail = useGotoNewsDetail() const gotoNewsDetail = useGotoNewsDetail()
...@@ -735,18 +655,17 @@ const handleClickPerson = async item => { ...@@ -735,18 +655,17 @@ const handleClickPerson = async item => {
const yearList = getNearYearList(); const yearList = getNearYearList();
// 获取AI智能报告 // 获取AI智能报告
const aiContent = reactive({ const refAiReport1 = ref(null)
content1: "正在生成...", const refAiReport2 = ref(null)
content2: "正在生成...", const refAiReport3 = ref(null)
})
const onAIReport = (data, key) => { // 数量变化趋势
getAIReport(data).then(res => { aiContent[key] = res }) const chart1Data = reactive({
} title: [],
data: [
// 行政令发布频度 { name: '全部政令', list: [] },
const chart1Data = ref({ { name: '涉华政令', list: [] },
dataX: [], ],
dataY: []
}); });
const box5Params = reactive({ const box5Params = reactive({
year: yearList[0].value, year: yearList[0].value,
...@@ -757,121 +676,91 @@ const box5Params = reactive({ ...@@ -757,121 +676,91 @@ const box5Params = reactive({
const handleGetDecreeYearOrder = async () => { const handleGetDecreeYearOrder = async () => {
box5Params.loading = true box5Params.loading = true
try { try {
let { year, domainId, proposeName } = box5Params;
const res = await getDecreeYearOrder({ const res = await getDecreeYearOrder({
year, year: box5Params.year,
domainId: domainId || undefined, domainId: box5Params.domainId || null,
orgId: proposeName || undefined orgId: box5Params.proposeName || null
}); });
console.log("行政令发布频度", res); console.log("数量变化趋势", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
chart1Data.value.dataX = res.data.map(item => { chart1Data.title = res.data.map(item => item.year);
return item.year; chart1Data.data = [
}); { name: '全部政令', list: res.data.map(item => item.count) },
chart1Data.value.dataY = res.data.map(item => { { name: '涉华政令', list: res.data.map(item => item.count) },
return item.count; ];
});
onAIReport({ type: "柱状图", name: "数量变化趋势", data: res.data }, "content1")
} else { } else {
chart1Data.value.dataX = []; chart1Data.title = [];
chart1Data.value.dataY = []; chart1Data.data = [
aiContent.content1 = "" { name: '全部政令', list: [] },
{ name: '涉华政令', list: [] },
];
} }
} catch (error) { } catch (error) {
console.error("行政令发布频度error", error); chart1Data.title = [];
chart1Data.data = [
{ name: '全部政令', list: [] },
{ name: '涉华政令', list: [] },
];
} }
refAiReport1.value?.onDataInfo({ type: "柱状图", name: "数量变化趋势", data: chart1Data })
box5Params.loading = false box5Params.loading = false
}; };
const getBox5Data = async () => {
const handleBox5 = async () => {
await handleGetDecreeYearOrder(); await handleGetDecreeYearOrder();
let chart1 = getBarChart(chart1Data.value.dataX, chart1Data.value.dataY); let chart1 = getBarChart(chart1Data.title, chart1Data.data);
chart1.yAxis.name = "数量"; let org = govInsList.value.find(item => item.orgId === box5Params.proposeName)?.orgName || '全部机构'
chart1.yAxis.nameTextStyle = { align: 'right' } let domain = areaList.value.find(item => item.id === box5Params.domainId)?.name || '全部领域'
let org = '全部机构' nextTick(() => {
if (box5Params.proposeName) { setChart(chart1, "chart1", true, {
org = keyOrganizationList.value.filter(item => {
return item.orgId === box5Params.proposeName
})[0].orgName
}
let domain = '全部领域'
if (box5Params.domainId) {
domain = areaList.value.filter(item => {
return item.id === box5Params.domainId
})[0].name
}
const selectParam = {
moduleType: '政令', moduleType: '政令',
orgnizationName: org, orgnizationName: org,
domains: domain, domains: domain,
selectDate: box5Params.year selectDate: box5Params.year
} })
setChart(chart1, "chart1", true, selectParam); })
}; };
// 政令科技领域 // 领域分布情况
const chart2Data = ref([ const chart2Data = ref([]);
// {
// name: "集成电路",
// value: 50
// },
// {
// name: "人工智能",
// value: 46
// },
]);
// const colorList = ["#69B1FF", "#FFC069", "#87E8DE", "#85A5FF", "#FF7875", "#B37FEB", "#4096FF"];
const box6Params = reactive({ const box6Params = reactive({
year: yearList[0].value, year: yearList[0].value,
proposeName: '', proposeName: '',
loading: false, loading: false,
}); });
const handleGetDecreeArea = async () => { const box6Ref = ref(null);
const getBox6Data = async () => {
box6Params.loading = true box6Params.loading = true
try { try {
let { year, proposeName } = box6Params;
const res = await getDecreeArea({ const res = await getDecreeArea({
year, year: box6Params.year,
orgId: proposeName || undefined orgId: box6Params.proposeName || null
}); });
console.log("政令科技领域", res); console.log("领域分布情况", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
chart2Data.value = res.data.map(item => { chart2Data.value = res.data.map(item => ({name: item.industry, value: item.count}));
return {
name: item.industry,
value: item.count
};
});
onAIReport({ type: "环形图", name: "领域分布情况", data: res.data }, "content2")
} else { } else {
chart2Data.value = [] chart2Data.value = []
aiContent.content2 = ""
} }
} catch (error) { } catch (error) {
console.error("政令科技领域error", error); chart2Data.value = []
} }
refAiReport2.value?.onDataInfo({ type: "环形图", name: "领域分布情况", data: chart2Data.value })
box6Params.loading = false box6Params.loading = false
}; nextTick(() => {
const handleBox6 = async () => { let box6Chart = createPieChart(box6Ref, chart2Data.value)
await handleGetDecreeArea(); box6Chart.on('click', (node) => {
let org = '全部机构' const route = router.resolve({
if (box6Params.proposeName) { path: "/dataLibrary/dataDecree",
org = keyOrganizationList.value.filter(item => { query: {
return item.orgId === box6Params.proposeName
})[0].orgName
}
const selectParam = {
moduleType: '政令', moduleType: '政令',
orgnizationName: org, orgnizationName: govInsList.value.find(item => item.orgId === box6Params.proposeName)?.orgName || '全部机构',
selectedDate: JSON.stringify([box6Params.year + '-01-01', box6Params.year + '-12-31']) domains: node.name,
selectedDate: JSON.stringify([`${box6Params.year}-01-01`, `${box6Params.year}-12-31`])
} }
let chart2 = getPieChart(chart2Data.value); });
setChart(chart2, "chart2", true, selectParam); window.open(route.href, "_blank");
}; })
})
const handleBox6YearChange = () => {
handleBox6();
}; };
// 关键行政令 // 关键行政令
...@@ -887,7 +776,8 @@ const box7Params = reactive({ ...@@ -887,7 +776,8 @@ const box7Params = reactive({
proposeName: '', proposeName: '',
loading: false, loading: false,
}) })
const handleGetKeyDecree = async () => { const getBox7Data = async (page) => {
if (page) keyDecreeInfo.page = page
box7Params.loading = true box7Params.loading = true
try { try {
let { year, domainId, proposeName } = box7Params; let { year, domainId, proposeName } = box7Params;
...@@ -899,22 +789,21 @@ const handleGetKeyDecree = async () => { ...@@ -899,22 +789,21 @@ const handleGetKeyDecree = async () => {
orgId: proposeName || undefined orgId: proposeName || undefined
}); });
console.log("关键行政令", res); console.log("关键行政令", res);
if (res.code === 200 && res.data?.total) { if (res.code === 200 && res.data.list) {
keyDecreeInfo.total = res.data.total || 0; keyDecreeInfo.total = res.data.total || 0;
keyDecreeList.value = res.data.list.map(item => { keyDecreeList.value = res.data.list;
return { } else {
title: item.name, keyDecreeInfo.total = 0
content: item.describe, keyDecreeList.value = []
time: item.postDate, }
id: item.orderId } catch (error) {
}; keyDecreeInfo.total = 0
}); keyDecreeList.value = []
} }
} catch (error) { }
box7Params.loading = false box7Params.loading = false
}; };
// 政令重点条款 // 关键条款词云
const wordCloudData = ref([]); const wordCloudData = ref([]);
const box8Params = reactive({ const box8Params = reactive({
year: yearList[0].value, year: yearList[0].value,
...@@ -922,7 +811,7 @@ const box8Params = reactive({ ...@@ -922,7 +811,7 @@ const box8Params = reactive({
proposeName: '', proposeName: '',
loading: false, loading: false,
}) })
const handleGetDecreeKeyInstruction = async () => { const getBox8Data = async () => {
box8Params.loading = true box8Params.loading = true
wordCloudData.value = [] wordCloudData.value = []
try { try {
...@@ -932,7 +821,7 @@ const handleGetDecreeKeyInstruction = async () => { ...@@ -932,7 +821,7 @@ const handleGetDecreeKeyInstruction = async () => {
domainId: domainId || undefined, domainId: domainId || undefined,
orgId: proposeName || undefined orgId: proposeName || undefined
}); });
console.log("政令重点条款", res); console.log("关键条款词云", res);
if (res.code == 200) { if (res.code == 200) {
wordCloudData.value = res.data.map(item => ({ name: item.clause, value: item.count })); wordCloudData.value = res.data.map(item => ({ name: item.clause, value: item.count }));
} else { } else {
...@@ -940,16 +829,11 @@ const handleGetDecreeKeyInstruction = async () => { ...@@ -940,16 +829,11 @@ const handleGetDecreeKeyInstruction = async () => {
} }
} catch (error) { } catch (error) {
wordCloudData.value = [] wordCloudData.value = []
console.error("政令重点条款error", error);
} }
refAiReport3.value?.onDataInfo({ type: "词云图", name: "关键条款词云", data: wordCloudData.value })
box8Params.loading = false box8Params.loading = false
}; };
// 资源库
const searchType = ref("");
const isChina = ref(false);
const isSort = ref(false); // true 升序 false 降序
const handleToPosi = id => { const handleToPosi = id => {
const element = document.getElementById(id); const element = document.getElementById(id);
if (element && containerRef.value) { if (element && containerRef.value) {
...@@ -975,8 +859,7 @@ const handleToPosi = id => { ...@@ -975,8 +859,7 @@ const handleToPosi = id => {
// 政令类型 // 政令类型
const decreeTypeList = ref([]); const decreeTypeList = ref([]);
const checkedDecreeType = ref([]); const checkedDecreeType = ref(['']);
const handleGetDecreeTypeList = async () => { const handleGetDecreeTypeList = async () => {
try { try {
const res = await getDecreeTypeList(); const res = await getDecreeTypeList();
...@@ -984,8 +867,17 @@ const handleGetDecreeTypeList = async () => { ...@@ -984,8 +867,17 @@ const handleGetDecreeTypeList = async () => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
decreeTypeList.value = res.data; decreeTypeList.value = res.data;
} }
} catch (error) { } } catch (error) {}
}; };
const handleTypeChange = async (event) => {
if (event.length && event[event.length-1] !== "") {
checkedDecreeType.value = event.filter(item => item !== "");
} else {
checkedDecreeType.value = [""];
}
getDecreeList(1);
}
// 查看社交媒体详情 // 查看社交媒体详情
const handleToSocialDetail = item => { const handleToSocialDetail = item => {
const route = router.resolve({ const route = router.resolve({
...@@ -996,21 +888,9 @@ const handleToSocialDetail = item => { ...@@ -996,21 +888,9 @@ const handleToSocialDetail = item => {
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
const handleChangeCheckedDecreeType = () => {
handleGetDecreeOrderList();
};
const pubTime = ref([ const pubTime = getNearYearList(7);
{ id: "", name: "全部时间" }, const activePubTime = ref([pubTime[0].value]);
{ id: "2026", name: "2026年" },
{ id: "2025", name: "2025年" },
{ id: "2024", name: "2024年" },
{ id: "2023", name: "2023年" },
{ id: "2022", name: "2022年" },
{ id: "2021", name: "2021年" },
{ id: "2020", name: "2020年" }
]);
const activePubTime = ref(["2026"]);
// 处理发布时间全选逻辑 // 处理发布时间全选逻辑
const handlePubTimeChange = (event) => { const handlePubTimeChange = (event) => {
if (event.length && event[event.length-1] !== "") { if (event.length && event[event.length-1] !== "") {
...@@ -1018,8 +898,7 @@ const handlePubTimeChange = (event) => { ...@@ -1018,8 +898,7 @@ const handlePubTimeChange = (event) => {
} else { } else {
activePubTime.value = [""]; activePubTime.value = [""];
} }
currentPage.value = 1; getDecreeList(1);
handleGetDecreeOrderList();
}; };
const activeAreaList = ref([""]); const activeAreaList = ref([""]);
...@@ -1029,18 +908,10 @@ const handleAreaChange = (event) => { ...@@ -1029,18 +908,10 @@ const handleAreaChange = (event) => {
} else { } else {
activeAreaList.value = [""]; activeAreaList.value = [""];
} }
getDecreeList(1);
currentPage.value = 1;
handleGetDecreeOrderList();
}; };
const areaList = ref([ const areaList = ref([]);
// { id: "人工智能", name: "人工智能" },
// { id: "集成电路", name: "集成电路" },
// { id: "通信网络", name: "通信网络" },
// { id: "量子科技", name: "量子科技" }
]);
// 修改获取科技领域列表,添加全选选项 // 修改获取科技领域列表,添加全选选项
const handleGetAreaList = async () => { const handleGetAreaList = async () => {
try { try {
...@@ -1048,8 +919,6 @@ const handleGetAreaList = async () => { ...@@ -1048,8 +919,6 @@ const handleGetAreaList = async () => {
console.log("行业领域列表", res); console.log("行业领域列表", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
areaList.value = res.data; areaList.value = res.data;
// 获取列表后重新查询
handleGetDecreeOrderList();
} }
} catch (error) { } } catch (error) { }
}; };
...@@ -1058,51 +927,50 @@ const totalDecreesNum = ref(0); ...@@ -1058,51 +927,50 @@ const totalDecreesNum = ref(0);
const decreeList = ref([]); const decreeList = ref([]);
// 修改请求方法,处理全选时不传参数的情况 // 科技政令库
const handleGetDecreeOrderList = async () => { const handlePxChange = (event) => {
box9Params.sortFun = event - 1;
getDecreeList(1)
};
const box9Params = reactive({
page: 1,
size: 10,
name: '',
sortFun: 0,
isCN: false,
loading: false,
})
const getDecreeList = async (page) => {
if (page) box9Params.page = page;
box9Params.loading = true;
const params = { const params = {
currentPage: currentPage.value, currentPage: box9Params.page,
pageSize: pageSize.value, pageSize: box9Params.size,
proposeName: box9Params.name,
isCN: box9Params.isCN ? 1 : 0,
sortFun: box9Params.sortFun,
typeIds: checkedDecreeType.value.join(',') || null,
researchTypeIds: activeAreaList.value.join(',') || null, researchTypeIds: activeAreaList.value.join(',') || null,
sortFun: isSort.value,
isCN: isChina.value ? 1 : 0,
proposeName: searchType.value,
years: activePubTime.value.join(',') || null, years: activePubTime.value.join(',') || null,
typeIds: checkedDecreeType.value.toString()
}; };
try { try {
const res = await getDecreeOrderList(params); const res = await getDecreeOrderList(params);
console.log("资源库列表", res); console.log("科技政令库", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
totalDecreesNum.value = res.data.totalElements; totalDecreesNum.value = res.data.totalElements;
decreeList.value = res.data.content.map(item => { decreeList.value = res.data.content;
return {
id: item.id,
time: item.postDate,
title: item.proposeOrgName + ": " + item.name,
desc: item.describe,
img: item.orgImage,
tagList: item.industryList
};
});
} else { } else {
decreeList.value = []; decreeList.value = [];
totalDecreesNum.value = 0; totalDecreesNum.value = 0;
} }
} catch (error) { } catch (error) {
console.error("资源库列表error", error);
decreeList.value = []; decreeList.value = [];
totalDecreesNum.value = 0; totalDecreesNum.value = 0;
} }
box9Params.loading = false;
}; };
watch([checkedGovIns, isSort, isChina, searchType], val => {
// 切换页码到第一页
currentPage.value = 1;
handleGetDecreeOrderList();
});
// 切换当前政令 // 切换当前政令
const handleSwithCurDecree = name => { const handleSwithCurDecree = name => {
if (name === "left") { if (name === "left") {
...@@ -1160,12 +1028,12 @@ onMounted(async () => { ...@@ -1160,12 +1028,12 @@ onMounted(async () => {
handleGetNews(); handleGetNews();
handleGetDecreeTypeList(); handleGetDecreeTypeList();
handleGetAreaList(); handleGetAreaList();
handleGetDecreeOrderList();
handleBox1(); // 最新科技政令 handleBox1(); // 最新科技政令
handleGetKeyDecree(); getBox5Data();
handleBox5(); getBox6Data();
handleBox6(); getBox7Data();
handleGetDecreeKeyInstruction(); getBox8Data();
getDecreeList();
}); });
</script> </script>
...@@ -1174,59 +1042,6 @@ onMounted(async () => { ...@@ -1174,59 +1042,6 @@ onMounted(async () => {
box-shadow: none; box-shadow: none;
} }
.ai-pane {
position: absolute;
right: 0px;
bottom: 15px;
z-index: 2;
:deep(.ai-pane-wrapper) {
display: none;
}
:deep(.ai-button-wrapper) {
display: flex;
}
&:hover {
width: 100%;
bottom: 0px;
:deep(.ai-pane-wrapper) {
display: block;
}
:deep(.ai-button-wrapper) {
display: none;
}
}
}
.data-origin-box {
width: 100%;
display: flex;
align-items: center;
padding: 16px 22px;
.data-origin-icon {
width: 16px;
height: 16px;
font-size: 0px;
margin-right: 8px;
img {
width: 100%;
height: 100%;
}
}
.data-origin-text {
font-family: Source Han Sans CN;
font-size: 14px;
color: var(--text-primary-50-color);
}
}
.home-wrapper { .home-wrapper {
width: 100%; width: 100%;
height: 100%; height: 100%;
...@@ -1638,17 +1453,14 @@ onMounted(async () => { ...@@ -1638,17 +1453,14 @@ onMounted(async () => {
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between;
.box1-main-right-title { .box1-main-right-title {
width: 100%; width: 100%;
// height: 26px;
color: var(--color-main-active); color: var(--color-main-active);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 20px; font-size: 20px;
font-weight: 700; font-weight: bold;
line-height: 26px; line-height: 30px;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
...@@ -1657,10 +1469,10 @@ onMounted(async () => { ...@@ -1657,10 +1469,10 @@ onMounted(async () => {
} }
.box1-main-right-info { .box1-main-right-info {
margin-top: 14px; margin-top: 10px;
display: flex; display: flex;
height: 24px;
gap: 8px; gap: 8px;
flex-wrap: wrap;
} }
.box1-main-right-center { .box1-main-right-center {
...@@ -1990,8 +1802,6 @@ onMounted(async () => { ...@@ -1990,8 +1802,6 @@ onMounted(async () => {
.box5-main { .box5-main {
flex: auto; flex: auto;
height: 20px; height: 20px;
padding-top: 16px;
.box5-chart { .box5-chart {
height: 100%; height: 100%;
} }
...@@ -2136,6 +1946,7 @@ onMounted(async () => { ...@@ -2136,6 +1946,7 @@ onMounted(async () => {
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative;
.box8-header { .box8-header {
width: 100%; width: 100%;
...@@ -2189,10 +2000,10 @@ onMounted(async () => { ...@@ -2189,10 +2000,10 @@ onMounted(async () => {
margin-bottom: 6px; margin-bottom: 6px;
} }
.home-main-footer-header { .home-main-footer-head {
width: 1600px; width: 1600px;
height: 50px; height: 50px;
margin: 0 auto 16px; margin: 16px auto 22px;
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -2238,30 +2049,6 @@ onMounted(async () => { ...@@ -2238,30 +2049,6 @@ onMounted(async () => {
.search-box { .search-box {
width: 360px; width: 360px;
} }
.select-box {
margin-left: 10px;
height: 42px;
box-sizing: border-box;
padding: 5px 0;
.icon1 {
width: 11px;
height: 14px;
font-size: 0px;
img {
width: 100%;
height: 100%;
}
}
:deep(.el-select__selected-item) {
text-align: center;
font-size: 16px;
font-family: Microsoft YaHei;
}
}
} }
.home-main-footer-main { .home-main-footer-main {
...@@ -2334,6 +2121,7 @@ onMounted(async () => { ...@@ -2334,6 +2121,7 @@ onMounted(async () => {
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
box-sizing: border-box; box-sizing: border-box;
border-radius: 10px; border-radius: 10px;
overflow: hidden;
.content-header { .content-header {
height: 48px; height: 48px;
...@@ -2365,25 +2153,16 @@ onMounted(async () => { ...@@ -2365,25 +2153,16 @@ onMounted(async () => {
} }
.content-box { .content-box {
border-bottom: 1px solid rgba(234, 236, 238, 1);
overflow: hidden; overflow: hidden;
min-height: 790px; min-height: 480px;
box-sizing: border-box;
.main-item { .main-item {
display: flex; display: flex;
width: 100%; width: 100%;
min-height: 100px; min-height: 100px;
// height: 136px;
// background: orange;
box-sizing: border-box;
padding: 16px 36px 0px 0px; padding: 16px 36px 0px 0px;
cursor: pointer; cursor: pointer;
// &:hover {
// background: var(--color-bg-hover);
// }
.main-item-left { .main-item-left {
display: flex; display: flex;
gap: 18px; gap: 18px;
...@@ -2440,30 +2219,29 @@ onMounted(async () => { ...@@ -2440,30 +2219,29 @@ onMounted(async () => {
gap: 16px; gap: 16px;
.title { .title {
width: 20px;
flex: auto;
height: 26px; height: 26px;
line-height: 26px;
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 20px; font-size: 20px;
font-weight: 700; font-weight: bold;
line-height: 26px;
letter-spacing: 0px; letter-spacing: 0px;
flex: auto;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.type-box { .type-box {
flex: none; flex: none;
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
padding: 0 8px; padding: 0 12px;
text-align: center; text-align: center;
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 16px; font-size: 16px;
font-weight: 400; font-weight: 400;
letter-spacing: 0px; letter-spacing: 0px;
border-radius: 4px; border-radius: 14px;
margin-left: 20px;
} }
.type1 { .type1 {
...@@ -2504,8 +2282,8 @@ onMounted(async () => { ...@@ -2504,8 +2282,8 @@ onMounted(async () => {
} }
.footer-box { .footer-box {
margin: 20px 30px; border-top: 1px solid rgba(234, 236, 238, 1);
height: 32px; padding: 20px 30px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
......
import * as echarts from "echarts"; import * as echarts from "echarts";
import { DOUBLECHARTCOLORS } from '@/common/constant'
import { hexToRgba } from '@/views/marketAccessRestrictions/utils/index.ts'
const getBarChart = (nameList, valueList) => { const getSerie = (index, data) => {
return {
name: data[index].name,
type: 'bar',
data: data[index].list,
label: {
show: true,
position: 'top',
color: DOUBLECHARTCOLORS[index],
fontWeight: 'bold', // 文字加粗
fontSize: 14,
formatter: (params) => params.value,
},
barWidth: 20,
itemStyle: {
color: function (params) {
return new echarts.graphic.LinearGradient(0, 1, 0, 0,
[{
offset: 0,
color: hexToRgba(DOUBLECHARTCOLORS[index], 0.3)
},
{
offset: 1,
color: hexToRgba(DOUBLECHARTCOLORS[index], 1)
}
]);
},
barBorderRadius: 10,
}
}
}
const getBarChart = (dataX, dataY) => {
const option = { const option = {
color: DOUBLECHARTCOLORS,
legend: {
show: true,
top: 0,
icon: 'circle',
textStyle: {
color: 'rgba(95, 101, 108, 1)',
fontFamily: 'Microsoft YaHei',
fontSize: '14px',
}
},
tooltip: {}, tooltip: {},
grid: { grid: {
top: '8%', top: '8%',
...@@ -12,6 +57,8 @@ const getBarChart = (nameList, valueList) => { ...@@ -12,6 +57,8 @@ const getBarChart = (nameList, valueList) => {
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
name: '项',
nameTextStyle: { align: 'right' },
splitLine: { splitLine: {
show: true, show: true,
lineStyle: { lineStyle: {
...@@ -34,7 +81,7 @@ const getBarChart = (nameList, valueList) => { ...@@ -34,7 +81,7 @@ const getBarChart = (nameList, valueList) => {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: nameList, data: dataX,
splitLine: { splitLine: {
show: false show: false
}, },
...@@ -56,36 +103,7 @@ const getBarChart = (nameList, valueList) => { ...@@ -56,36 +103,7 @@ const getBarChart = (nameList, valueList) => {
} }
} }
}, },
series: [{ series: [ getSerie(0, dataY), getSerie(1, dataY) ]
type: 'bar',
data: valueList,
label: {
show: true,
position: 'top',
color: 'rgba(5, 95, 194, 1)',
fontWeight: 'bold', // 文字加粗
fontSize: 14,
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 return option
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<div class="box1"> <div class="box1">
<AnalysisBox title="相关政令" :showAllBtn="false"> <AnalysisBox title="相关政令" :showAllBtn="false">
<div class="box1-main" v-loading="isLoading"> <div class="box1-main" v-loading="isLoading">
<el-empty v-if="!siderList?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" /> <el-empty v-if="!siderList?.length" style="height: 100%;" description="暂无数据" :image-size="100" />
<el-scrollbar height="100%" always> <el-scrollbar height="100%" always>
<div class="left-item" :class="{ 'item-active': false }" v-for="(item, index) in siderList" :key="index" @click="handleClickDecree(item)"> <div class="left-item" :class="{ 'item-active': false }" v-for="(item, index) in siderList" :key="index" @click="handleClickDecree(item)">
<div class="item-head"> <div class="item-head">
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<div class="box2"> <div class="box2">
<AnalysisBox title="政令关系挖掘" :showAllBtn="false"> <AnalysisBox title="政令关系挖掘" :showAllBtn="false">
<div style="height: 100%; width: 100%;" v-loading="isLoading"> <div style="height: 100%; width: 100%;" v-loading="isLoading">
<el-empty v-if="!siderList?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" /> <el-empty v-if="!siderList?.length" style="height: 100%;" description="暂无数据" :image-size="100" />
<div class="box2-main" v-if="graphData.nodes?.length"> <div class="box2-main" v-if="graphData.nodes?.length">
<GraphChart :nodes="graphData.nodes" :links="graphData.links" layoutType="force" @handleClickNode="handleClickNode" /> <GraphChart :nodes="graphData.nodes" :links="graphData.links" layoutType="force" @handleClickNode="handleClickNode" />
</div> </div>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="layout-container"> <div class="layout-container">
<!-- 导航菜单 --> <!-- 导航菜单 -->
<div class="layout-main"> <div class="layout-main">
<div class="header-main"> <div class="layout-head">
<div class="layout-main-header"> <div class="layout-main-header">
<div class="layout-main-header-container"> <div class="layout-main-header-container">
<div class="layout-main-header-left-box"> <div class="layout-main-header-left-box">
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layout-main-center"> <div class="layout-down">
<router-view /> <router-view />
</div> </div>
</div> </div>
...@@ -236,68 +236,7 @@ onMounted(() => { ...@@ -236,68 +236,7 @@ onMounted(() => {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
overflow-y: auto; overflow-y: auto;
background-color: white;
.report {
padding: 10px 150px;
position: absolute;
left: 0;
top: 0;
z-index: 999999;
width: 100%;
height: 100%;
background: #f7f8f9;
.report-header {
width: 100%;
height: 50px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-style: Bold;
font-size: 20px;
font-weight: 700;
line-height: 50px;
letter-spacing: 0px;
text-align: left;
padding-left: 30px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
}
.report-main {
display: flex;
height: calc(100% - 100px);
justify-content: space-between;
.left {
width: 800px;
.noContent {
height: 100px;
line-height: 100px;
text-align: center;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 20px;
font-weight: 400;
}
}
.right {
width: 800px;
.noContent {
height: 100px;
line-height: 100px;
text-align: center;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 20px;
font-weight: 400;
}
}
}
}
.layout-main { .layout-main {
width: 100%; width: 100%;
...@@ -305,10 +244,10 @@ onMounted(() => { ...@@ -305,10 +244,10 @@ onMounted(() => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.header-main { .layout-head {
width: 100%; width: 100%;
border-bottom: 1px solid rgba(234, 236, 238, 1); border-bottom: 1px solid rgb(234, 236, 238);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1); box-shadow: 0 0 20px #1945821a;
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
} }
...@@ -316,7 +255,6 @@ onMounted(() => { ...@@ -316,7 +255,6 @@ onMounted(() => {
width: 1600px; width: 1600px;
height: 137px; height: 137px;
margin: 0 auto; margin: 0 auto;
background: rgba(255, 255, 255, 1);
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
position: sticky; position: sticky;
...@@ -554,10 +492,9 @@ onMounted(() => { ...@@ -554,10 +492,9 @@ onMounted(() => {
} }
} }
.layout-main-center { .layout-down {
height: 20px; height: 20px;
flex: auto; flex: auto;
background-color: #f7f8f9;
} }
} }
} }
......
<template> <template>
<div class="view-box"> <div class="view-box">
<el-empty v-if="!listData?.length" style="padding: 60px 0" description="暂无数据" :image-size="100" /> <el-empty v-if="!listData?.length" style="height: 100%;" description="暂无数据" :image-size="100" />
<div <div
v-if="listData.length" v-if="listData.length"
class="main-content-main" class="main-content-main"
...@@ -10,12 +10,8 @@ ...@@ -10,12 +10,8 @@
@mouseleave="handleMouseUp" @mouseleave="handleMouseUp"
@mousemove="handleMouseMove" @mousemove="handleMouseMove"
> >
<div <div class="fishbone-container"
class="fishbone-container" :style="{ transform: `translate(${translateX}px, ${translateY}px) scale(${scale})` }"
:style="{
transform: `translate(${translateX}px, ${translateY}px) scale(${scale})`,
transformOrigin: 'center center'
}"
> >
<!-- 主轴上的标签 --> <!-- 主轴上的标签 -->
<div class="main-line" :style="{ width: listData.length * 200 + 300 + 'px' }"> <div class="main-line" :style="{ width: listData.length * 200 + 300 + 'px' }">
...@@ -152,18 +148,18 @@ ...@@ -152,18 +148,18 @@
</template> </template>
<script setup name="ChartChain"> <script setup name="ChartChain">
import { ref } from "vue"; import { onBeforeUnmount, ref, watch } from "vue";
import defaultIcon2 from "@/assets/icons/default-icon2.png"; import defaultIcon2 from "@/assets/icons/default-icon2.png";
import noticeIcon from "../assets/images/notice-icon.png"; import noticeIcon from "../assets/images/notice-icon.png";
const props = defineProps({ const props = defineProps({
baseData: { baseData: {
type: Object, type: Array,
default: () => [] default: () => ([])
}, },
listData: { listData: {
type: Array, type: Array,
default: () => [] default: () => ([])
} }
}); });
...@@ -211,6 +207,15 @@ const handleMouseUp = () => { ...@@ -211,6 +207,15 @@ const handleMouseUp = () => {
}; };
// #endregion 移动功能处理 // #endregion 移动功能处理
// 初始化布局
const watchInfo = watch(() => props.listData, val => {
scale.value = 1;
translateX.value = 0;
translateY.value = 0;
})
onBeforeUnmount(() => { watchInfo() });
// 奇数索引的数据组放在上方, 偶数索引的数据组放在下方 // 奇数索引的数据组放在上方, 偶数索引的数据组放在下方
const onFilterData = num => { const onFilterData = num => {
return props.listData.filter((_, index) => index % 2 === num); return props.listData.filter((_, index) => index % 2 === num);
...@@ -247,9 +252,14 @@ const formatRate = (item, key) => { ...@@ -247,9 +252,14 @@ const formatRate = (item, key) => {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
overflow: hidden; overflow: hidden;
-webkit-user-select: none; /* Safari/Chrome */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE/Edge */
user-select: none; /* 标准语法 */
.fishbone-container { .fishbone-container {
position: relative; position: relative;
transform-origin: center center;
.main-line { .main-line {
height: 3px; height: 3px;
......
<template> <template>
<div class="wrapper"> <div class="wrapper">
<div class="box1"> <div class="box1" v-loading="entityInfo.loading">
<AnalysisBox title="受影响实体" :showAllBtn="false"> <AnalysisBox title="受影响实体" :showAllBtn="false">
<div class="box1-main"> <div class="box1-main">
<div class="data-filter"> <div class="data-filter">
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
</div> </div>
<div class="data-title">实体名称</div> <div class="data-title">实体名称</div>
<div style="height: 20px; flex: auto;"> <div style="height: 20px; flex: auto;">
<el-empty v-if="!entityInfo.list?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" /> <el-empty v-if="!entityInfo.list?.length" style="height: 100%;" description="暂无数据" :image-size="100" />
<el-scrollbar height="100%" always> <el-scrollbar height="100%" always>
<div class="list-data"> <div class="list-data">
<div class="list-item" v-for="item in entityInfo.list" :key="item.id" :class="{ 'item-active': entityInfo.id==item.id }" @click="headerChartData(item)"> <div class="list-item" v-for="item in entityInfo.list" :key="item.id" :class="{ 'item-active': entityInfo.id==item.id }" @click="headerChartData(item)">
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
<div class="box2"> <div class="box2" v-loading="box2Params.loading">
<AnalysisBox :showAllBtn="false"> <AnalysisBox :showAllBtn="false">
<template #custom-title> <template #custom-title>
<div class="custom-title"> <div class="custom-title">
...@@ -80,8 +80,9 @@ ...@@ -80,8 +80,9 @@
<ChartChain :listData="fishbone.list" :baseData="fishbone.base" /> <ChartChain :listData="fishbone.list" :baseData="fishbone.base" />
</div> </div>
<div class="graph-box" v-if="contentType==2"> <div class="graph-box" v-if="contentType==2">
<GraphChart v-if="graphInfo.nodes?.length" :nodes="graphInfo.nodes" :links="graphInfo.links" layoutType="force" /> <!-- <GraphChart v-if="graphInfo.nodes?.length" :nodes="graphInfo.nodes" :links="graphInfo.links" layoutType="force" /> -->
<el-empty v-else style="padding: 60px 0" description="暂无数据" :image-size="100" /> <RelationChart v-if="graphInfo.nodes?.length" :graphData="graphInfo"></RelationChart>
<el-empty v-else style="height: 100%;" description="暂无数据" :image-size="100" />
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
...@@ -103,6 +104,7 @@ import { ...@@ -103,6 +104,7 @@ import {
import ChartChain from "./com/ChartChain.vue"; import ChartChain from "./com/ChartChain.vue";
// import AiTips from "./com/AiTips.vue"; // import AiTips from "./com/AiTips.vue";
import GraphChart from "@/components/base/GraphChart/index.vue"; import GraphChart from "@/components/base/GraphChart/index.vue";
import RelationChart from "@/components/base/RelationChart/index.vue"
import defaultIcon2 from "@/assets/icons/default-icon2.png"; import defaultIcon2 from "@/assets/icons/default-icon2.png";
import noticeIcon from "./assets/images/notice-icon.png"; import noticeIcon from "./assets/images/notice-icon.png";
import icon422 from "./assets/images/icon422.png"; import icon422 from "./assets/images/icon422.png";
...@@ -134,6 +136,7 @@ const handleGetHylyList = async () => { ...@@ -134,6 +136,7 @@ const handleGetHylyList = async () => {
// 受影响实体 // 受影响实体
const entityInfo = reactive({ const entityInfo = reactive({
loading: false,
keyword: "", keyword: "",
pageSize: 10, pageSize: 10,
pageNum: 1, pageNum: 1,
...@@ -144,6 +147,7 @@ const entityInfo = reactive({ ...@@ -144,6 +147,7 @@ const entityInfo = reactive({
}) })
const onDecreeEntities = async (page=1) => { const onDecreeEntities = async (page=1) => {
entityInfo.pageNum = page; entityInfo.pageNum = page;
entityInfo.loading = true;
try { try {
let params = { let params = {
id: route.query.id, id: route.query.id,
...@@ -154,19 +158,31 @@ const onDecreeEntities = async (page=1) => { ...@@ -154,19 +158,31 @@ const onDecreeEntities = async (page=1) => {
} }
const res = await getDecreeEntities(params); const res = await getDecreeEntities(params);
console.log("受影响实体:", res); console.log("受影响实体:", res);
if (res.code === 200) { if (res.code === 200 && res.data) {
entityInfo.list = res.data.companyInfos; entityInfo.list = res.data.companyInfos;
entityInfo.total = res.data.total; entityInfo.total = res.data.total;
if (entityInfo.total && entityInfo.list.every(item => item.id!=entityInfo.id)) { if (entityInfo.total && entityInfo.list.every(item => item.id!=entityInfo.id)) {
headerChartData(entityInfo.list[0]) headerChartData(entityInfo.list[0])
} }
} else {
entityInfo.list = [];
entityInfo.total = 0;
fishbone.list = [];
graphInfo.nodes = [];
} }
} catch (error) { } catch (error) {
console.log("获取受影响实体失败", error); entityInfo.list = [];
entityInfo.total = 0;
fishbone.list = [];
graphInfo.nodes = [];
} }
entityInfo.loading = false;
}; };
const contentType = ref(1); const contentType = ref(1);
const box2Params = reactive({
loading: false,
})
const headerContentType = (type) => { const headerContentType = (type) => {
contentType.value = type; contentType.value = type;
if (!entityInfo.total) return; if (!entityInfo.total) return;
...@@ -206,9 +222,7 @@ const onDecreeRelatedChain = async (id) => { ...@@ -206,9 +222,7 @@ const onDecreeRelatedChain = async (id) => {
industryChain.list = res.data; industryChain.list = res.data;
if (industryChain.list.length) onDecreeChainNodes(industryChain.list[0].id) if (industryChain.list.length) onDecreeChainNodes(industryChain.list[0].id)
} }
} catch (error) { } catch (error) {}
console.log("获取产业链失败", error);
}
}; };
// 产业链鱼骨图 // 产业链鱼骨图
...@@ -217,6 +231,7 @@ const fishbone = reactive({ ...@@ -217,6 +231,7 @@ const fishbone = reactive({
base: [], base: [],
}) })
const onDecreeChainNodes = async (id) => { const onDecreeChainNodes = async (id) => {
box2Params.loading = true;
industryChain.id = id; industryChain.id = id;
try { try {
const res = await getDecreeChainNodes({ id }); const res = await getDecreeChainNodes({ id });
...@@ -234,36 +249,61 @@ const onDecreeChainNodes = async (id) => { ...@@ -234,36 +249,61 @@ const onDecreeChainNodes = async (id) => {
} }
}) })
fishbone.list = Object.values(obj); fishbone.list = Object.values(obj);
console.log("fishbone.list:", fishbone.list);
fishbone.base = res.data.levelInfos.map((item, index) => { fishbone.base = res.data.levelInfos.map((item, index) => {
return {...item, name: ['上游', '中游', '下游'][index]} return {...item, name: ['上游', '中游', '下游'][index]}
}); });
} }
} catch (error) { } catch (error) {}
console.log("获取产业链鱼骨图失败", error); box2Params.loading = false;
}
}; };
// 实体关系 // 实体关系
const graphInfo = reactive({ const graphInfo = reactive({
nodes: [], nodes: [],
links: [], links: [],
rootId: "",
}); });
const onDecreeRelatedEntitie = async (orgId) => { const onDecreeRelatedEntitie = async (orgId) => {
box2Params.loading = true;
try { try {
const res = await getDecreeRelatedEntitie({ orgId, rule:false, withSanInfo:false }); const res = await getDecreeRelatedEntitie({ orgId, rule:false, withSanInfo:false });
console.log("实体关系:", res); console.log("实体关系:", res);
if (res.code === 200) { if (res.code === 200) {
let arr1 = res.data.parentOrgList.map(item => ({ ...item, level: 1 })) let arr1 = res.data.parentOrgList.map((item, index) => {
let arr3 = res.data.childrenOrgList.map(item => ({ ...item, level: 3 })) return {
id: `1-${index}`,
graphInfo.links = [...arr1,...arr3].map(onFormatLink) text: item.name,
graphInfo.nodes = [...arr1,...arr3].map(onFormatNode) description: item.description,
graphInfo.nodes.unshift(onFormatNode({name:res.data.orgName, id:res.data.orgId}, -1)) level: 1,
} }
} catch (error) { })
console.log("获取实体关系失败", error); let arr3 = res.data.childrenOrgList.map((item, index) => {
return {
id: `3-${index}`,
text: item.name,
description: item.description,
level: 3,
} }
})
graphInfo.links = [...arr1,...arr3].map((item => {
return {
from: '0-0',
to: item.id,
text: (item.level==1 ? '被' : '') + item.description,
fontColor: (item.level==1 ? '#ff954d' : '#218139'),
color: (item.level==1 ? '#fbf0e9' : '#e4eee7'),
textOffset_x: -20,
lineWidth: 5
}
}))
graphInfo.nodes = [...arr1,...arr3]
graphInfo.nodes.unshift({text:res.data.orgName, id:'0-0', level: 2})
graphInfo.rootId = '0-0'
console.log('graphInfo', graphInfo)
}
} catch (error) {}
box2Params.loading = false
} }
const onFormatLink = (item, index) => { const onFormatLink = (item, index) => {
return { return {
...@@ -448,10 +488,13 @@ onMounted(() => { ...@@ -448,10 +488,13 @@ onMounted(() => {
:deep(.header-icon) { :deep(.header-icon) {
display: none; display: none;
} }
:deep(.wrapper-header) {
padding-top: 8px;
}
.custom-title { .custom-title {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: flex-end; align-items: center;
width: 100%; width: 100%;
height: 100%; height: 100%;
padding: 0 20px; padding: 0 20px;
......
<template> <template>
<div class="introduction-wrap"> <div class="introduction-wrap">
<div class="left"> <div class="left">
<div class="box1"> <div class="box1" v-loading="box1Params.loading">
<AnalysisBox title="提出背景" :showAllBtn="false"> <AnalysisBox title="提出背景" :showAllBtn="false">
<template #header-btn> <template #header-btn>
<div class="header-btn-box"> <div class="header-btn-box">
<div class="btn" :class="{ btnActive: box1ActiveBtn === item }" v-for="(item, index) in box1BtnList" <div class="btn" :class="{ btnActive: box1Params.active === 1 }" @click="handleClickBox1Btn(1)">涉华背景</div>
:key="index" @click="handleClickBox1Btn(item)"> <div class="btn" :class="{ btnActive: box1Params.active === 2 }" @click="handleClickBox1Btn(2)">全部背景</div>
{{ item }}
</div>
</div> </div>
</template> </template>
<div class="box1-container"> <div class="box1-container">
...@@ -17,30 +15,30 @@ ...@@ -17,30 +15,30 @@
<div class="box1-item" v-for="(item, index) in backgroundList" :key="index"> <div class="box1-item" v-for="(item, index) in backgroundList" :key="index">
<div class="id">{{ index + 1 }}</div> <div class="id">{{ index + 1 }}</div>
<div class="title text-align-justify">{{ item.content }}</div> <div class="title text-align-justify">{{ item.content }}</div>
<div class="open"> <!-- <div class="open">
<img src="./assets/images/open-icon.png" alt="" /> <img src="./assets/images/open-icon.png" alt="" />
</div> -->
</div> </div>
</div> </div>
</div> <div class="box-footer">
<div class="box1-footer" v-if="backgroundListNum > 10"> <div class="box-footer-left">{{ `共 ${box1Params.total} 项` }}</div>
<div class="box1-footer-left">{{ `共 ${backgroundListNum} 项` }}</div> <div class="box-footer-right">
<div class="box1-footer-right"> <el-pagination :page-size="box1Params.size" @current-change="handleGetBackground" :current-page="box1Params.page"
<el-pagination :page-size="10" @current-change="handleCurrentChange" :current-page="currentPage" background layout="prev, pager, next" :total="box1Params.total" />
background layout="prev, pager, next" :total="backgroundListNum" />
</div> </div>
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
<div class="box2"> <div class="box2" v-loading="box2Params.loading">
<AnalysisBox title="法律依据" :showAllBtn="false"> <AnalysisBox title="法律依据" :showAllBtn="false">
<el-empty v-if="!dependList?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" /> <el-empty v-if="!box2Params.list?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" />
<div class="box2-main"> <div class="box2-main">
<div class="custom-collapse"> <div class="custom-collapse">
<el-collapse v-model="dependActive"> <el-collapse v-model="box2Params.active">
<el-collapse-item v-for="(item, index) in dependList" :key="item.billId" :name="item.billId"> <el-collapse-item v-for="(item, index) in box2Params.list" :key="item.billId" :name="item.billId">
<template #icon> <template #icon>
<el-icon v-if="dependActive.includes(item.billId)"> <el-icon v-if="box2Params.active.includes(item.billId)">
<ArrowDownBold /> <ArrowDownBold />
</el-icon> </el-icon>
<el-icon v-else> <el-icon v-else>
...@@ -62,6 +60,13 @@ ...@@ -62,6 +60,13 @@
</el-collapse> </el-collapse>
</div> </div>
</div> </div>
<div class="box-footer" style="padding: 0 18px 16px;">
<div class="box-footer-left">{{ `共 ${box2Params.total} 项` }}</div>
<div class="box-footer-right">
<el-pagination :page-size="box2Params.size" @current-change="handleGetLaws" :current-page="box2Params.page"
background layout="prev, pager, next" :total="box2Params.total" />
</div>
</div>
</AnalysisBox> </AnalysisBox>
</div> </div>
</div> </div>
...@@ -92,7 +97,7 @@ ...@@ -92,7 +97,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted, computed } from "vue"; import { ref, onMounted, computed, reactive } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { getDecreeBackground, getDecreeDepend, getDecreePrev } from "@/api/decree/background"; import { getDecreeBackground, getDecreeDepend, getDecreePrev } from "@/api/decree/background";
import router from "@/router"; import router from "@/router";
...@@ -128,58 +133,46 @@ const decodeMaybeBase64NumericId = (raw) => { ...@@ -128,58 +133,46 @@ const decodeMaybeBase64NumericId = (raw) => {
const decreeId = computed(() => decodeMaybeBase64NumericId(route.query.id)); const decreeId = computed(() => decodeMaybeBase64NumericId(route.query.id));
// 提出背景 // 提出背景
const box1BtnList = ref(["涉华背景", "全部背景"]);
const box1ActiveBtn = ref("涉华背景"); const backgroundList = ref([]);
const box1Params = reactive({
loading: false,
size: 5,
page: 1,
total: 0,
active: 1,
})
const handleClickBox1Btn = btn => { const handleClickBox1Btn = btn => {
box1ActiveBtn.value = btn; box1Params.active = btn;
handleCurrentChange(1) handleGetBackground()
}; };
const backgroundListNum = ref(0); const handleGetBackground = async (page = 1) => {
const backgroundList = ref([ box1Params.page = page;
// { box1Params.loading = true;
// content: "认为人工智能(AI)是一项将决定未来几十年经济增长、国家安全和全球竞争力的基础性技术"
// },
// {
// content: "要求美国不仅必须在开发通用和前沿AI能力方面领先,还必须确保美国的人工智能技术、标准和治理模式在全球范围内被采用"
// },
]);
const currentPage = ref(1);
const handleCurrentChange = page => {
currentPage.value = page;
handleGetBackground();
};
const handleGetBackground = async () => {
const params = {
cRelated: box1ActiveBtn.value === "涉华背景" ? true : false,
currentPage: currentPage.value - 1,
pageSize: 10,
id: decreeId.value
};
try { try {
const res = await getDecreeBackground(params); const res = await getDecreeBackground({
cRelated: box1Params.active == 1,
currentPage: box1Params.page - 1,
pageSize: box1Params.size,
id: decreeId.value
});
console.log("提出背景", res); console.log("提出背景", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
backgroundListNum.value = res.data.numberOfElements; box1Params.total = res.data.numberOfElements;
backgroundList.value = res.data.content; backgroundList.value = res.data.content;
} else { } else {
backgroundListNum.value = 0; box1Params.total = 0;
backgroundList.value = []; backgroundList.value = [];
} }
} catch (error) { } catch (error) {
backgroundListNum.value = 0; box1Params.total = 0;
backgroundList.value = []; backgroundList.value = [];
console.error("获取提出背景数据失败", error);
} }
box1Params.loading = false;
}; };
// 前序政令 // 前序政令
const prevList = ref([ const prevList = ref([]);
// {
// proposeOrgName: "白宫",
// postDate: "2025-07-31",
// describe: "美商务部发布指南,警告全球企业使用华为昇腾芯片可能违反美国出口管制。意在限制中国AI产业发展,阻碍其获得先进算力。"
// },
]);
const handleGetPrev = async () => { const handleGetPrev = async () => {
try { try {
const res = await getDecreePrev({ id: decreeId.value }); const res = await getDecreePrev({ id: decreeId.value });
...@@ -191,7 +184,6 @@ const handleGetPrev = async () => { ...@@ -191,7 +184,6 @@ const handleGetPrev = async () => {
} }
} catch (error) { } catch (error) {
prevList.value = []; prevList.value = [];
console.error("获取前序政令数据失败", error);
} }
}; };
// 跳转行政机构主页 // 跳转行政机构主页
...@@ -204,12 +196,6 @@ const handleToInstitution = item => { ...@@ -204,12 +196,6 @@ const handleToInstitution = item => {
} }
}); });
window.open(curRoute.href, "_blank"); window.open(curRoute.href, "_blank");
// router.push({
// path: "/institution",
// query: {
// id: item.orgId
// }
// })
}; };
// 跳转科技政令详情页 // 跳转科技政令详情页
const handleClickDecree = item => { const handleClickDecree = item => {
...@@ -220,31 +206,39 @@ const handleClickDecree = item => { ...@@ -220,31 +206,39 @@ const handleClickDecree = item => {
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
// router.push({
// path: "/decreeLayout",
// query: {
// id: item.id
// }
// })
}; };
// 法律依据 // 法律依据
const dependList = ref([]); const box2Params = reactive({
const dependActive = ref([]); loading: false,
const handleGetLaws = async () => { size: 5,
page: 1,
total: 0,
active: [],
list: [],
})
const handleGetLaws = async (page = 1) => {
box2Params.page = page;
box2Params.loading = true;
try { try {
const res = await getDecreeDepend({ id: decreeId.value }); const res = await getDecreeDepend({
id: decreeId.value,
currentPage: box2Params.page - 1,
pageSize: box2Params.size,
});
console.log("法律依据", res); console.log("法律依据", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
dependList.value = res.data; box2Params.list = res.data;
// dependActive.value = res.data.map(item => item.billId); box2Params.total = 0
} else { } else {
dependList.value = []; box2Params.list = [];
box2Params.total = 0
} }
} catch (error) { } catch (error) {
dependList.value = []; box2Params.list = [];
console.error("获取法律依据数据失败", error); box2Params.total = 0
} }
box2Params.loading = false;
}; };
// 跳转科技法案详情页 // 跳转科技法案详情页
const handleClickBull = decree => { const handleClickBull = decree => {
...@@ -314,10 +308,11 @@ onMounted(() => { ...@@ -314,10 +308,11 @@ onMounted(() => {
} }
.box1-main { .box1-main {
width: 1034px; width: 100%;
padding: 0 6px;
.box1-item { .box1-item {
width: 1015px; width: 100%;
min-height: 48px; min-height: 48px;
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: var(--font-size-base); font-size: var(--font-size-base);
...@@ -326,11 +321,10 @@ onMounted(() => { ...@@ -326,11 +321,10 @@ onMounted(() => {
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
display: flex; display: flex;
align-items: center; align-items: center;
padding: 18px 0; padding: 18px 16px;
.id { .id {
margin-right: 16px; margin-right: 16px;
margin-left: 15px;
width: 24px; width: 24px;
height: 24px; height: 24px;
text-align: center; text-align: center;
...@@ -363,27 +357,11 @@ onMounted(() => { ...@@ -363,27 +357,11 @@ onMounted(() => {
background-color: rgba(247, 248, 249, 1); background-color: rgba(247, 248, 249, 1);
} }
} }
.box1-footer {
display: flex;
justify-content: space-between;
margin-top: 10px;
.box1-footer-left {
height: 20px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
}
} }
.box2 { .box2 {
.box2-main { .box2-main {
padding: 16px 20px; padding: 10px 24px 16px;
.custom-collapse { .custom-collapse {
padding-left: 32px; padding-left: 32px;
...@@ -395,6 +373,8 @@ onMounted(() => { ...@@ -395,6 +373,8 @@ onMounted(() => {
:deep(.el-collapse-item__header) { :deep(.el-collapse-item__header) {
border-bottom: 1px solid rgba(234, 236, 238, 1); border-bottom: 1px solid rgba(234, 236, 238, 1);
min-height: 50px;
line-height: 50px;
} }
:deep(.el-collapse-item__content) { :deep(.el-collapse-item__content) {
...@@ -408,18 +388,19 @@ onMounted(() => { ...@@ -408,18 +388,19 @@ onMounted(() => {
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: var(--font-size-base); font-size: var(--font-size-base);
position: absolute; position: absolute;
top: 12px; top: 13px;
left: -32px; left: -32px;
width: 24px; width: 24px;
height: 24px; height: 24px;
text-align: center;
line-height: 24px; line-height: 24px;
text-align: center;
border-radius: 50%; border-radius: 50%;
background: #e7f3ff; background: #e7f3ff;
color: #0a57a6; color: #0a57a6;
} }
.custom-collapse-name { .custom-collapse-name {
padding-left: 6px;
font-weight: 600; font-weight: 600;
font-size: 18px; font-size: 18px;
color: var(--el-collapse-header-text-color); color: var(--el-collapse-header-text-color);
...@@ -507,4 +488,20 @@ onMounted(() => { ...@@ -507,4 +488,20 @@ onMounted(() => {
} }
} }
} }
.box-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10px;
.box-footer-left {
height: 20px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
}
</style> </style>
\ No newline at end of file
...@@ -96,7 +96,6 @@ onMounted(() => { ...@@ -96,7 +96,6 @@ onMounted(() => {
.decree-overview-wrap { .decree-overview-wrap {
width: 100%; width: 100%;
overflow: hidden; overflow: hidden;
background: rgba(247, 248, 249, 1);
.main { .main {
position: relative; position: relative;
width: 1600px; width: 1600px;
......
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
<div> <div v-loading="relateParams.loading">
<AnalysisBox title="相关事件" :showAllBtn="false"> <AnalysisBox title="相关事件" :showAllBtn="false">
<div class="box2-main"> <div class="box2-main">
<el-empty v-if="!relatedData.length" description="暂无数据" :image-size="100" /> <el-empty v-if="!relatedData.length" description="暂无数据" :image-size="100" />
...@@ -90,6 +90,7 @@ ...@@ -90,6 +90,7 @@
<div class="content">{{ item.sjnr }}</div> <div class="content">{{ item.sjnr }}</div>
</div> </div>
</div> </div>
<SimplePagination v-model:current-page="relateParams.page" :page-size="relateParams.size" :total="relateParams.total" @page-change="onDecreeRelatedEvent" />
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -106,12 +107,12 @@ ...@@ -106,12 +107,12 @@
<div class="box3"> <div class="box3">
<AnalysisBox title="发布机构" :showAllBtn="false"> <AnalysisBox title="发布机构" :showAllBtn="false">
<div class="box3-top"> <div class="box3-top">
<div class="box3-top-top" @click="handleToInstitution(box3TopTopData)"> <div class="box3-top-top">
<div class="left"> <div class="left">
<img :src="box3TopTopData?.logo || DefaultIcon2" alt="" /> <img :src="box3TopTopData?.logo || DefaultIcon2" alt="" />
</div> </div>
<div class="right"> <div class="right">
<div class="name">{{ box3TopTopData.name + " >" }}</div> <div class="name text-click-hover" @click="handleToInstitution(box3TopTopData)">{{ box3TopTopData.name + " >" }}</div>
<div class="ename">{{ box3TopTopData.eName }}</div> <div class="ename">{{ box3TopTopData.eName }}</div>
</div> </div>
</div> </div>
...@@ -145,7 +146,7 @@ ...@@ -145,7 +146,7 @@
<div class="box3-bottom-main"> <div class="box3-bottom-main">
<el-timeline style="max-width: 500px"> <el-timeline style="max-width: 500px">
<el-timeline-item :timestamp="item.postDate" placement="top" v-for="(item, index) in eventList?.slice(0, 3)" :key="index"> <el-timeline-item :timestamp="item.postDate" placement="top" v-for="(item, index) in eventList?.slice(0, 3)" :key="index">
<div class="timeline-content">{{ item.describe }}</div> <div class="timeline-content text-align-justify">{{ item.describe }}</div>
</el-timeline-item> </el-timeline-item>
</el-timeline> </el-timeline>
</div> </div>
...@@ -158,7 +159,7 @@ ...@@ -158,7 +159,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted, reactive } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import router from "@/router"; import router from "@/router";
import WarnningPane from '@/components/base/WarningPane/index.vue' import WarnningPane from '@/components/base/WarningPane/index.vue'
...@@ -171,7 +172,8 @@ import { ...@@ -171,7 +172,8 @@ import {
getOverview, getOverview,
} from "@/api/decree/introduction"; } from "@/api/decree/introduction";
import { getDecreeRelatedEvent } from "@/api/decree/background"; import { getDecreeRelatedEvent } from "@/api/decree/background";
import AiSummary from '@/components/base/Ai/AiSummary/index.vue' import AiSummary from '@/components/base/Ai/AiSummary/index.vue';
import SimplePagination from "@/components/SimplePagination.vue";
import DefaultIcon1 from "@/assets/icons/default-icon1.png"; import DefaultIcon1 from "@/assets/icons/default-icon1.png";
import DefaultIcon2 from "@/assets/icons/default-icon2.png"; import DefaultIcon2 from "@/assets/icons/default-icon2.png";
...@@ -296,9 +298,21 @@ const onOverview = async () => { ...@@ -296,9 +298,21 @@ const onOverview = async () => {
// 相关事件 // 相关事件
const relatedData = ref([]); const relatedData = ref([]);
const handleGetRelateEvents = async () => { const relateParams = reactive({
size: 5,
page: 1,
total: 0,
loading: false,
})
const onDecreeRelatedEvent = async (page) => {
if (page) keyDecreeInfo.page = page
relateParams.loading = true;
try { try {
const res = await getDecreeRelatedEvent({id: decreeId.value}); const res = await getDecreeRelatedEvent({
id: decreeId.value,
pageNum: relateParams.page -1,
pageSize: relateParams.size,
});
console.log("相关事件", res); console.log("相关事件", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
relatedData.value = res.data; relatedData.value = res.data;
...@@ -307,8 +321,8 @@ const handleGetRelateEvents = async () => { ...@@ -307,8 +321,8 @@ const handleGetRelateEvents = async () => {
} }
} catch (error) { } catch (error) {
relatedData.value = []; relatedData.value = [];
console.error("获取相关事件数据失败", error);
} }
relateParams.loading = false;
}; };
// 发布机构 // 发布机构
...@@ -382,7 +396,7 @@ onMounted(() => { ...@@ -382,7 +396,7 @@ onMounted(() => {
onOverview() onOverview()
onKeyWordUp() onKeyWordUp()
onRiskSignalData() onRiskSignalData()
handleGetRelateEvents(); onDecreeRelatedEvent();
handleGetOrgnization(); handleGetOrgnization();
}); });
</script> </script>
...@@ -825,6 +839,12 @@ onMounted(() => { ...@@ -825,6 +839,12 @@ onMounted(() => {
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
line-height: 26px; line-height: 26px;
max-height: 78px;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
} }
} }
} }
......
<template> <template>
<div class="introduction-wrap"> <div class="introduction-wrap">
<div class="page-left"> <div class="page-left">
<div class="box1"> <div class="box1" v-loading="box1Params.loading">
<AnalysisBox title="主要指令" :showAllBtn="false"> <AnalysisBox title="主要指令" :showAllBtn="false">
<template #header-btn> <template #header-btn>
<div class="mind-bnt" @click="onDecreeMindMap()"> <div class="mind-bnt" @click="onDecreeMindMap()">
...@@ -23,18 +23,18 @@ ...@@ -23,18 +23,18 @@
<div style="margin-left: 6px;">高亮实体</div> --> <div style="margin-left: 6px;">高亮实体</div> -->
<div class="select-input"> <div class="select-input">
<el-input v-model="commandWord" @keyup.enter="onMainContentData()" style="width: 100%; height: 100%;" <el-input v-model="commandWord" @keyup.enter="onMainContentData()" style="width: 100%; height: 100%;"
:suffix-icon="Search" placeholder="指令搜索" /> :prefix-icon="Search" placeholder="指令搜索" clearable @clear="onMainContentData()" />
</div> </div>
</div> </div>
<div class="analysis-content"> <div class="analysis-content">
<!-- 遍历文档章节 --> <!-- 遍历文档章节 -->
<el-empty v-if="!contentList?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" /> <el-empty v-if="!contentList?.length" style="padding: 80px 0 96px;" description="暂无数据" :image-size="100" />
<div v-for="(section, index) in contentList" :key="index" class="section"> <div v-for="(section, index) in contentList" :key="index" class="section">
<div class="section-header"> <div class="section-header">
<div class="section-title text-align-justify" v-html="section.content"></div> <div class="section-title text-align-justify" v-html="section.content"></div>
<div class="section-icon"> <!-- <div class="section-icon">
<img src="./assets/images/open-icon.png" alt="" /> <img src="./assets/images/open-icon.png" alt="" />
</div> </div> -->
</div> </div>
<!-- 渲染一级列表 --> <!-- 渲染一级列表 -->
<div class="numbered-list"> <div class="numbered-list">
...@@ -61,28 +61,34 @@ ...@@ -61,28 +61,34 @@
</div> </div>
</div> </div>
</div> </div>
<div class="box-footer" style="padding: 10px 18px 16px;">
<div class="box-footer-left">{{ `共 ${box1Params.total} 项` }}</div>
<div class="box-footer-right">
<el-pagination :page-size="box1Params.size" @current-change="onMainContentData" :current-page="box1Params.page"
background layout="prev, pager, next" :total="box1Params.total" />
</div>
</div>
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
</div> </div>
<div class="page-right"> <div class="page-right">
<div class="box3"> <div class="box3" v-loading="orgInfo.loading">
<AnalysisBox title="执行机构" :showAllBtn="false"> <AnalysisBox title="执行机构" :showAllBtn="false">
<div class="box3-top"> <div class="box3-top" v-if="orgInfo.list?.length">
<div class="organization-list"> <div class="organization-list">
<div class="organization-item" v-for="item in organizationInfo.list" :key="item.id"> <div class="organization-item" v-for="item in orgInfo.list" :key="item.id">
<ActionButton @click="handleOrganization(item)" :name="item.obb" <ActionButton @click="handleOrganization(item)" :name="item.obb" :type="item.id == orgInfo.node.id ? 'active' : 'normal'" />
:type="item.id == organizationInfo.node.id ? 'active' : 'normal'" />
</div> </div>
</div> </div>
<div class="box3-top-top" @click="handleToInstitution()"> <div class="box3-top-top">
<div class="left"> <div class="left">
<img :src="organizationInfo.node.logo || DefaultIcon2" alt="" /> <img :src="orgInfo.node.logo || DefaultIcon2" alt="" />
</div> </div>
<div class="right"> <div class="right">
<div class="name">{{ organizationInfo.node.name + " >" }}</div> <div class="name text-click-hover" @click="handleToInstitution()">{{ orgInfo.node.name + " >" }}</div>
<div class="ename">{{ organizationInfo.node.ename }}</div> <div class="ename">{{ orgInfo.node.ename }}</div>
</div> </div>
</div> </div>
<div class="box3-top-bottom"> <div class="box3-top-bottom">
...@@ -93,7 +99,8 @@ ...@@ -93,7 +99,8 @@
<div class="text">{{ "关键人物" }}</div> <div class="text">{{ "关键人物" }}</div>
</div> </div>
<div class="box3-top-bottom-main"> <div class="box3-top-bottom-main">
<div class="box3-top-bottom-item" v-for="(item, index) in organizationInfo.node.leaders" :key="index"> <el-empty v-if="!orgInfo.node.leaders?.length" style="width:100%; height:100%;" description="暂无数据" :image-size="60" />
<div class="box3-top-bottom-item" v-for="(item, index) in orgInfo.node.leaders" :key="index">
<div class="box3-top-bottom-item-left"> <div class="box3-top-bottom-item-left">
<img :src="item.avatar || DefaultIcon1" alt="" /> <img :src="item.avatar || DefaultIcon1" alt="" />
</div> </div>
...@@ -112,32 +119,34 @@ ...@@ -112,32 +119,34 @@
</el-icon> </el-icon>
</div> </div>
</div> </div>
<el-empty v-else style="padding: 98px 0 138px;" description="暂无数据" :image-size="100" />
</AnalysisBox> </AnalysisBox>
</div> </div>
<div class="box4"> <div class="box4" v-loading="box4Params.loading">
<AnalysisBox title="相关实体" :showAllBtn="false"> <AnalysisBox title="相关实体" :showAllBtn="false">
<el-empty v-if="!entityList?.length" style="padding: 60px 0;" description="暂无数据" :image-size="100" /> <div v-if="box4Params.list?.length" class="left-bottom-main">
<div class="left-bottom-main"> <div v-for="(item, index) in box4Params.list" :key="index" class="main-box">
<div v-for="(item, index) in entityList" :key="index" class="main-box">
<div class="icon"> <div class="icon">
<img style="width: 100%; height: 100%;" :src="item.imgUrl || defaultCom" alt="" /> <img style="width: 100%; height: 100%;" :src="item.imgUrl || defaultCom" alt="" />
</div> </div>
<div class="name one-line-ellipsis">{{ item.name }}</div> <div class="name one-line-ellipsis text-click-hover" @click="handleSearch(item)">{{ item.name }}</div>
<div class="type">{{ item.entityType }}</div> <div class="type">{{ item.entityType }}</div>
</div> </div>
</div> </div>
<el-empty v-else style="padding: 60px 0 100px;" description="暂无数据" :image-size="100" />
</AnalysisBox> </AnalysisBox>
</div> </div>
</div> </div>
<el-dialog v-model="isTreeDialog" width="1400px" top="8vh" class="viewpoint-dialog" destroy-on-close> <el-dialog v-model="mindParams.isShow" width="1400px" top="8vh" class="viewpoint-dialog" destroy-on-close>
<template #header> <template #header>
<div class="viewpoint-header"> <div class="viewpoint-header">
<div class="viewpoint-title">政令举措思维导图</div> <div class="viewpoint-title">政令举措思维导图</div>
</div> </div>
</template> </template>
<div class="viewpoint-body"> <div class="viewpoint-body" v-loading="mindParams.loading">
<MindGraph ref="refMindGraph"></MindGraph> <MindGraph v-if="mindParams.isData" ref="refMindGraph"></MindGraph>
<el-empty v-else style="height: 100%;" description="暂无数据" :image-size="100" />
</div> </div>
</el-dialog> </el-dialog>
</div> </div>
...@@ -157,6 +166,7 @@ import ActionButton from '@/components/base/ActionButton/index.vue' ...@@ -157,6 +166,7 @@ import ActionButton from '@/components/base/ActionButton/index.vue'
import DefaultIcon1 from "@/assets/icons/default-icon1.png"; import DefaultIcon1 from "@/assets/icons/default-icon1.png";
import DefaultIcon2 from "@/assets/icons/default-icon2.png"; import DefaultIcon2 from "@/assets/icons/default-icon2.png";
import defaultCom from "@/views/coopRestriction/assets/images/default-icon2.png" import defaultCom from "@/views/coopRestriction/assets/images/default-icon2.png"
import SimplePagination from "@/components/SimplePagination.vue";
import { onNumToChinese } from "@/views/marketAccessRestrictions/utils/index" import { onNumToChinese } from "@/views/marketAccessRestrictions/utils/index"
const route = useRoute(); const route = useRoute();
...@@ -205,7 +215,6 @@ const handleGetAreaList = async () => { ...@@ -205,7 +215,6 @@ const handleGetAreaList = async () => {
} }
} catch (error) { } catch (error) {
areaList.value = [] areaList.value = []
console.error("获取科技领域数据失败:", error);
} }
}; };
...@@ -214,12 +223,26 @@ const isHighlight = ref(false); ...@@ -214,12 +223,26 @@ const isHighlight = ref(false);
const commandWord = ref(""); const commandWord = ref("");
const contentList = ref([]); const contentList = ref([]);
const ALPHABET = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]; const ALPHABET = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
const onMainContentData = async () => { const box1Params = reactive({
loading: false,
size: 5,
page: 1,
total: 0,
})
const onMainContentData = async (page=1) => {
box1Params.page = page
box1Params.loading = true;
try { try {
const keyword = commandWord.value; const keyword = commandWord.value;
const id = decreeId.value; const id = decreeId.value;
if (!id) return; if (!id) return;
const res = await getDecreeMainContent({ id, keyword, domainId: areaType.value }); const res = await getDecreeMainContent({
id,
keyword: keyword || null,
domainId: areaType.value || null,
currentPage: box1Params.page,
pageSize: box1Params.size,
});
console.log("主要指令", res); console.log("主要指令", res);
if (res && res.code === 200) { if (res && res.code === 200) {
contentList.value = res.data || []; contentList.value = res.data || [];
...@@ -233,8 +256,8 @@ const onMainContentData = async () => { ...@@ -233,8 +256,8 @@ const onMainContentData = async () => {
} }
} catch (error) { } catch (error) {
contentList.value = [] contentList.value = []
console.error("获取主要指令数据失败:", error);
} }
box1Params.loading = false;
}; };
// 搜索高亮效果 // 搜索高亮效果
const onHighlight = (word, row) => { const onHighlight = (word, row) => {
...@@ -247,9 +270,15 @@ const onHighlight = (word, row) => { ...@@ -247,9 +270,15 @@ const onHighlight = (word, row) => {
} }
// 思维导图 // 思维导图
const isTreeDialog = ref(false);
const refMindGraph = ref(null); const refMindGraph = ref(null);
const mindParams = reactive({
isData: true,
loading: false,
isShow: false,
})
const onDecreeMindMap = async () => { const onDecreeMindMap = async () => {
mindParams.loading = true;
mindParams.isData = true;
let labelCfg = { let labelCfg = {
position: 'left', position: 'left',
offset: -20, offset: -20,
...@@ -260,13 +289,13 @@ const onDecreeMindMap = async () => { ...@@ -260,13 +289,13 @@ const onDecreeMindMap = async () => {
autoWrap: true autoWrap: true
} }
} }
isTreeDialog.value = true; mindParams.isShow = true;
try { try {
const id = decreeId.value; const id = decreeId.value;
if (!id) return; if (!id) return;
let res = await getDecreeMindMap({ id }); let res = await getDecreeMindMap({ id });
console.log("思维导图", res); console.log("思维导图", res);
if (res.code === 200) { if (res.code === 200 && res.data) {
let nodes = [] let nodes = []
let edges = [] let edges = []
let obj = {} let obj = {}
...@@ -286,12 +315,14 @@ const onDecreeMindMap = async () => { ...@@ -286,12 +315,14 @@ const onDecreeMindMap = async () => {
edges.push({ id: `edge-${index}`, source: `root-virtual`, target: `node-${item.orderNum}-${item.sectionId}` }) edges.push({ id: `edge-${index}`, source: `root-virtual`, target: `node-${item.orderNum}-${item.sectionId}` })
} }
}) })
setTimeout(() => { refMindGraph.value.onMindGraphData(nodes, edges) }, 100) setTimeout(() => { refMindGraph.value.onMindGraphData(nodes, edges) }, 100)
} else {
mindParams.isData = false
} }
} catch (error) { } catch (error) {
console.error("获取思维导图数据失败:", error); mindParams.isData = false
} }
mindParams.loading = false
} }
// 对象数组去重 // 对象数组去重
...@@ -307,54 +338,68 @@ const onUniqueArray = (list, key = 'id') => { ...@@ -307,54 +338,68 @@ const onUniqueArray = (list, key = 'id') => {
} }
// 相关实体 // 相关实体
const entityList = ref([]); const box4Params = reactive({
loading: false,
list: [],
})
const onRelatedEntityData = async () => { const onRelatedEntityData = async () => {
box4Params.loading = true;
try { try {
const id = decreeId.value; const id = decreeId.value;
if (!id) return; if (!id) return;
const res = await getDecreeRelatedEntity({ id }); const res = await getDecreeRelatedEntity({ id });
console.log("相关实体", res); console.log("相关实体", res);
if (res && res.code === 200) { if (res && res.code === 200) {
entityList.value = res.data; box4Params.list = res.data;
} else { } else {
entityList.value = [] box4Params.list = []
} }
} catch (error) { } catch (error) {
entityList.value = [] box4Params.list = []
console.error("获取相关实体数据失败:", error);
} }
box4Params.loading = false;
};
const handleSearch = (item) => {
window.sessionStorage.setItem("curTabName", `搜索-${item.name}`);
const curRoute = router.resolve({
path: "/searchResults",
query: {searchText: item.name}
});
window.open(curRoute.href, "_blank");
}; };
// 执行机构 // 执行机构
const organizationInfo = reactive({ const orgInfo = reactive({
loading: false,
list: [], list: [],
node: { id: "", obb: "", logo: "", name: "", ename: "", leaders: [] }, node: { id: "", obb: "", logo: "", name: "", ename: "", leaders: [] },
}) })
const handleGetOrgnization = async () => { const handleGetOrgnization = async () => {
orgInfo.loading = true
try { try {
const id = decreeId.value; const id = decreeId.value;
if (!id) return; if (!id) return;
const res = await getDecreeOrganization({ id }); const res = await getDecreeOrganization({ id });
console.log("执行机构", res); console.log("执行机构", res);
if (res.code === 200 && res.data?.length) { if (res.code === 200 && res.data?.length) {
organizationInfo.list = res.data; orgInfo.list = res.data;
organizationInfo.node = res.data[0]; orgInfo.node = res.data[0];
} }
} catch (error) { } catch (error) {
organizationInfo.node = { id: "", obb: "", logo: "", name: "", ename: "", leaders: [] }; orgInfo.node = { id: "", obb: "", logo: "", name: "", ename: "", leaders: [] };
console.error("获取执行机构数据失败", error);
} }
orgInfo.loading = false;
}; };
// 切换执行机构 // 切换执行机构
const handleOrganization = (node) => { const handleOrganization = (node) => {
organizationInfo.node = node; orgInfo.node = node;
}; };
// 跳转机构主页 // 跳转机构主页
const handleToInstitution = () => { const handleToInstitution = () => {
const curRoute = router.resolve({ const curRoute = router.resolve({
path: "/institution", path: "/institution",
query: { query: {
id: organizationInfo.node.id id: orgInfo.node.id
} }
}); });
window.open(curRoute.href, "_blank"); window.open(curRoute.href, "_blank");
...@@ -484,6 +529,9 @@ onMounted(() => { ...@@ -484,6 +529,9 @@ onMounted(() => {
letter-spacing: 1px; letter-spacing: 1px;
width: 20px; width: 20px;
flex: auto; flex: auto;
font-weight: bold;
color: var(--text-primary-80-color);
font-family: Source Han Sans CN;
} }
.section-icon { .section-icon {
...@@ -502,7 +550,9 @@ onMounted(() => { ...@@ -502,7 +550,9 @@ onMounted(() => {
margin-bottom: 12px; margin-bottom: 12px;
font-size: 16px; font-size: 16px;
line-height: 1.7; line-height: 1.7;
color: #374151; color: var(--text-primary-80-color);
font-family: Source Han Sans CN;
font-size: 16px;
.list-item { .list-item {
position: relative; position: relative;
...@@ -576,7 +626,7 @@ onMounted(() => { ...@@ -576,7 +626,7 @@ onMounted(() => {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
margin-bottom: 16px; margin-bottom: 16px;
gap: 8px 16px; gap: 8px 8px;
} }
.organization-button { .organization-button {
...@@ -605,7 +655,6 @@ onMounted(() => { ...@@ -605,7 +655,6 @@ onMounted(() => {
background: rgba(247, 248, 249, 1); background: rgba(247, 248, 249, 1);
display: flex; display: flex;
align-items: center; align-items: center;
cursor: pointer;
.left { .left {
width: 64px; width: 64px;
...@@ -832,7 +881,6 @@ onMounted(() => { ...@@ -832,7 +881,6 @@ onMounted(() => {
padding: 0 15px; padding: 0 15px;
display: flex; display: flex;
align-items: center; align-items: center;
cursor: pointer;
.icon { .icon {
width: 24px; width: 24px;
...@@ -906,4 +954,20 @@ onMounted(() => { ...@@ -906,4 +954,20 @@ onMounted(() => {
} }
} }
} }
.box-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10px;
.box-footer-left {
height: 20px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
}
</style> </style>
\ No newline at end of file
<template> <template>
<AnalysisBox :title="props.title" :showAllBtn="false" height="auto"> <AnalysisBox :title="props.title" :showAllBtn="false" height="auto">
<div class="box-main"> <div class="box-main">
<el-empty v-if="!props.listData?.length" description="暂无数据" :image-size="200" /> <el-empty v-if="!props.listData?.length" description="暂无数据" :image-size="100" />
<div v-for="(item, index) in props.listData" :key="index" class="box-item"> <div v-for="(item, index) in props.listData" :key="index" class="box-item">
<div class="item-tag" :class="getClassName(item)">{{ item.TYPE }}</div> <div class="item-tag" :class="getClassName(item)">{{ item.TYPE }}</div>
<div class="item-right" @click="onNavigateTo(item)"> <div class="item-right" @click="onNavigateTo(item)">
......
<template> <template>
<div class="view-box"> <div class="view-box">
<el-empty v-if="!props.surveyList?.length" description="暂无数据" :image-size="100" /> <el-empty v-if="!props.surveyList?.length" description="暂无数据" style="padding-top: 200px;" :image-size="100" />
<div class="timeline-item" v-for="(item, index) in props.surveyList" :key="item.searchid" @click="onNavigateToDetail(item)"> <div class="timeline-item" v-for="(item, index) in props.surveyList" :key="item.searchid" @click="onNavigateToDetail(item)">
<div class="timeline-date"> <div class="timeline-date">
<div class="date-text">{{ item.searchdatezh.slice(0,4) }}</div> <div class="date-text">{{ item.searchdatezh.slice(0,4) }}</div>
......
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24.000000" height="24.000000" fill="none" customFrame="#000000"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24.000000" height="24.000000" fill="none" customFrame="#000000">
<rect id="折线图" width="24.000000" height="24.000000" x="0.000000" y="0.000000" /> <rect id="容器 239" width="24.000000" height="24.000000" x="0.000000" y="0.000000" />
<path id="合并" d="M20.5419 4.83623L13.1957 9.57293C13.0388 9.6741 12.867 9.72717 12.6804 9.73213C12.4937 9.7371 12.3194 9.69325 12.1573 9.60057L8.08207 7.27011L4.50424 9.35944C4.02065 9.64183 3.41881 9.48376 3.13642 9.00018C2.85402 8.51659 3.0121 7.91475 3.49568 7.63236L7.57254 5.25161C7.72693 5.16146 7.8935 5.11598 8.07228 5.11516C8.25106 5.11435 8.41804 5.15832 8.57324 5.24707L12.6226 7.56272L19.4581 3.15534C19.9287 2.85188 20.537 2.98324 20.8404 3.45388C21.1439 3.92453 21.0125 4.53276 20.5419 4.83623ZM4.00352 13.6788L7.58044 11.6333C7.88802 11.4574 8.2657 11.4574 8.57327 11.6333L12.1169 13.6597C12.4459 13.8478 12.853 13.8338 13.1683 13.6234L18.9449 9.76933C19.6095 9.32597 20.4999 9.80233 20.4999 10.6012L20.4999 19.4969C20.4999 20.0492 20.0522 20.4969 19.4999 20.4969L4.49997 20.4971C3.94769 20.4971 3.49997 20.0494 3.49997 19.4971L3.49993 14.5468C3.49993 14.1881 3.6921 13.8568 4.00352 13.6788Z" fill="rgb(5,95,194)" fill-rule="evenodd" /> <path id="合并" d="M21.582 2.81364L14.582 7.81329C14.42 7.92898 14.2396 7.9908 14.0407 7.99874C13.8418 8.00668 13.657 7.95945 13.4863 7.85704L9.00066 5.16578L4.5155 7.8569C4.0353 8.14502 3.43163 7.99411 3.14351 7.51391C2.85539 7.03372 3.0063 6.43004 3.4865 6.14192L8.48614 3.1421C8.64448 3.0471 8.81598 2.99959 9.00063 2.99959C9.18528 2.99959 9.35678 3.04709 9.51512 3.14209L13.9531 5.80474L20.4196 1.18613C20.8753 0.860653 21.4891 0.962974 21.8146 1.41868C22.1401 1.87438 22.0377 2.48816 21.582 2.81364ZM3.00092 12.7841L8.11631 9.89203L13.2317 12.784L22.0009 6.99978L22.0009 19.9995L3.00096 19.9998L3.00092 12.7841Z" fill="rgb(5,95,194)" fill-rule="evenodd" />
</svg> </svg>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24.000000" height="24.000000" fill="none" customFrame="#000000"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24.000000" height="24.000000" fill="none">
<rect id="容器 1714" width="24.000000" height="24.000000" x="0.000000" y="0.000000" /> <rect id="雷达图_图表-雷达图 1" width="24.000000" height="24.000000" x="0.000000" y="0.000000" />
<path id="合并" d="M12 2.72656C10.6193 2.72656 9.5 3.84585 9.5 5.22656C9.5 6.60727 10.6193 7.72656 12 7.72656C13.3807 7.72656 14.5 6.60727 14.5 5.22656C14.5 3.84585 13.3807 2.72656 12 2.72656ZM8.5 5.28283C8.5 5.19541 8.5032 5.10875 8.5095 5.02295C5.55588 6.35486 3.5 9.32509 3.5 12.7755C3.5 13.5624 3.60693 14.3243 3.80705 15.0475C4.32848 14.6278 4.97275 14.3546 5.67741 14.2902C5.56142 13.8042 5.5 13.297 5.5 12.7755C5.5 10.2821 6.90397 8.11655 8.9645 7.02635C8.66902 6.51302 8.5 5.91766 8.5 5.28283ZM15.5 5.28283C15.5 5.19542 15.4968 5.10875 15.4905 5.02295C18.4441 6.35485 20.5 9.32509 20.5 12.7755C20.5 13.5624 20.3931 14.3243 20.193 15.0475C19.6715 14.6278 19.0273 14.3546 18.3226 14.2902C18.4386 13.8042 18.5 13.297 18.5 12.7755C18.5 10.2821 17.096 8.11655 15.0355 7.02635C15.331 6.51302 15.5 5.91766 15.5 5.28283ZM8.5 17.7754C8.5 16.3947 7.38071 15.2754 6 15.2754C4.61929 15.2754 3.5 16.3947 3.5 17.7754C3.5 19.1561 4.61929 20.2754 6 20.2754C7.38071 20.2754 8.5 19.1561 8.5 17.7754ZM18 15.2754C19.3807 15.2754 20.5 16.3947 20.5 17.7754C20.5 19.1561 19.3807 20.2754 18 20.2754C16.6193 20.2754 15.5 19.1561 15.5 17.7754C15.5 16.3947 16.6193 15.2754 18 15.2754ZM14.6294 18.7217C14.8172 19.3922 15.1997 19.9813 15.7121 20.4242C14.5905 20.9696 13.331 21.2755 12 21.2755C10.669 21.2755 9.40951 20.9696 8.28791 20.4242C8.80027 19.9813 9.18277 19.3922 9.3706 18.7217C10.1745 19.0777 11.0642 19.2755 12 19.2755C12.9358 19.2755 13.8255 19.0777 14.6294 18.7217Z" fill="rgb(5,95,194)" fill-rule="evenodd" /> <g id="组合 1062">
<path id="多边形 25" d="M19.7942 7.5L19.7942 16.5L12 21L4.20577 16.5L4.20577 7.5L12 3L19.7942 7.5Z" fill-rule="evenodd" stroke="rgb(5,95,194)" stroke-linejoin="round" stroke-width="2.000000" />
<path id="多边形 26" d="M16.3301 9.5L16.3301 14.5L12 17L7.66987 14.5L7.66987 9.5L12 7L16.3301 9.5Z" fill-rule="evenodd" stroke="rgb(5,95,194)" stroke-width="2.000000" />
<path id="多边形 27" d="M13.7321 11L13.7321 13L12 14L10.2679 13L10.2679 11L12 10L13.7321 11Z" fill="rgb(5,95,194)" fill-rule="evenodd" />
</g>
</svg> </svg>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24.000000" height="24.000000" fill="none"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24.000000" height="24.000000" fill="none">
<rect id="定位" width="24.000000" height="24.000000" x="0.000000" y="0.000000" /> <rect id="位置 1" width="24.000000" height="24.000000" x="0.000000" y="0.000000" />
<path id="矢量 573" d="M11.7453 2.01562C8.03585 2.01562 5.02783 5.03994 5.02783 8.77327C5.02783 10.6381 5.78079 12.3271 6.99554 13.5507L11.7453 18.3294L16.4964 13.5507C16.6523 13.394 16.8001 13.2301 16.9399 13.0589C17.0797 12.8877 17.2107 12.7101 17.3331 12.526C17.4554 12.3419 17.5685 12.1523 17.6722 11.9572C17.776 11.7621 17.8699 11.5623 17.954 11.3579C18.0382 11.1536 18.1121 10.9456 18.1758 10.7339C18.2396 10.5223 18.2928 10.3081 18.3355 10.0913C18.3782 9.87441 18.4102 9.65599 18.4315 9.43601C18.4527 9.21603 18.4632 8.99553 18.4628 8.77452C18.4628 5.04119 15.4561 2.01687 11.7453 2.01687L11.7453 2.01562ZM11.7453 11.775C11.6473 11.7748 11.5495 11.7697 11.4519 11.7598C11.3543 11.75 11.2575 11.7354 11.1613 11.716C11.0652 11.6966 10.9703 11.6726 10.8765 11.6439C10.7827 11.6152 10.6906 11.582 10.6001 11.5442C10.5096 11.5064 10.4211 11.4643 10.3348 11.4179C10.2484 11.3715 10.1645 11.3209 10.0831 11.2662C10.0017 11.2115 9.92319 11.153 9.84754 11.0906C9.77189 11.0282 9.69948 10.9622 9.63031 10.8927C9.56115 10.8232 9.49555 10.7504 9.43353 10.6745C9.37151 10.5985 9.31337 10.5197 9.25909 10.438C9.20481 10.3564 9.15467 10.2722 9.10866 10.1856C9.06265 10.099 9.021 10.0104 8.9837 9.91968C8.9464 9.82898 8.91364 9.73668 8.8854 9.64277C8.85717 9.54885 8.83362 9.45378 8.81473 9.35756C8.79584 9.26133 8.78171 9.16441 8.77234 9.06679C8.76298 8.96917 8.75842 8.87133 8.75867 8.77327L8.75867 8.77077C8.75838 8.67272 8.7629 8.57489 8.77222 8.47729C8.78155 8.37969 8.79564 8.28277 8.81449 8.18655C8.83334 8.09033 8.85686 7.99527 8.88506 7.90136C8.91325 7.80745 8.94598 7.71515 8.98324 7.62446C9.02051 7.53377 9.06213 7.44512 9.10811 7.35852C9.15409 7.27192 9.2042 7.18778 9.25844 7.1061C9.31269 7.02443 9.37081 6.94561 9.4328 6.86964C9.4948 6.79368 9.56036 6.72094 9.62951 6.65142C9.69865 6.5819 9.77103 6.51593 9.84666 6.45353C9.92228 6.39112 10.0008 6.33257 10.0822 6.27788C10.1635 6.22319 10.2474 6.17262 10.3338 6.12617C10.4201 6.07972 10.5085 6.03762 10.599 5.99986C10.6895 5.9621 10.7816 5.92887 10.8754 5.90017C10.9691 5.87146 11.0641 5.84742 11.1602 5.82805C11.2563 5.80867 11.3531 5.79405 11.4507 5.7842C11.5482 5.77434 11.646 5.76929 11.7441 5.76904L11.7453 5.76904C11.8434 5.76929 11.9412 5.77434 12.0388 5.7842C12.1363 5.79405 12.2332 5.80867 12.3293 5.82804C12.4255 5.84741 12.5204 5.87145 12.6142 5.90015C12.708 5.92885 12.8001 5.96208 12.8906 5.99984C12.9811 6.03759 13.0695 6.07969 13.1559 6.12614C13.2423 6.17258 13.3262 6.22315 13.4076 6.27783C13.489 6.33252 13.5675 6.39106 13.6431 6.45346C13.7188 6.51587 13.7912 6.58182 13.8604 6.65134C13.9295 6.72086 13.9951 6.7936 14.0571 6.86956C14.1192 6.94552 14.1773 7.02433 14.2316 7.10601C14.2859 7.18768 14.336 7.27182 14.382 7.35842C14.428 7.44502 14.4697 7.53367 14.507 7.62436C14.5443 7.71506 14.577 7.80736 14.6053 7.90127C14.6335 7.99519 14.6571 8.09026 14.6759 8.18649C14.6948 8.28271 14.709 8.37963 14.7183 8.47725C14.7277 8.57487 14.7322 8.67271 14.732 8.77077L14.732 8.77327C14.7322 8.87124 14.7277 8.96899 14.7183 9.06651C14.709 9.16404 14.6949 9.26087 14.676 9.35701C14.6572 9.45315 14.6336 9.54813 14.6055 9.64196C14.5773 9.73579 14.5445 9.82801 14.5073 9.91862C14.4701 10.0092 14.4285 10.0978 14.3825 10.1843C14.3366 10.2709 14.2865 10.3549 14.2323 10.4366C14.1781 10.5182 14.12 10.5969 14.0581 10.6728C13.9962 10.7488 13.9307 10.8215 13.8616 10.8909C13.7925 10.9604 13.7202 11.0263 13.6447 11.0887C13.5691 11.1511 13.4907 11.2096 13.4094 11.2643C13.3281 11.319 13.2443 11.3695 13.1581 11.416C13.0718 11.4624 12.9835 11.5046 12.8931 11.5423C12.8027 11.5801 12.7107 11.6134 12.617 11.6421C12.5233 11.6708 12.4285 11.6949 12.3325 11.7143C12.2365 11.7338 12.1397 11.7484 12.0422 11.7584C11.9448 11.7683 11.8471 11.7734 11.7491 11.7737L11.7453 11.7737L11.7453 11.775ZM8.75867 20.5254C8.75867 20.5665 8.76346 20.6075 8.77305 20.6484C8.78264 20.6893 8.79697 20.7299 8.81605 20.7703C8.83514 20.8106 8.85888 20.8504 8.88727 20.8897C8.91567 20.929 8.94858 20.9677 8.98601 21.0057C9.02345 21.0436 9.06522 21.0807 9.11133 21.117C9.15744 21.1532 9.20767 21.1884 9.26201 21.2226C9.31635 21.2568 9.37455 21.2898 9.43661 21.3215C9.49866 21.3533 9.56427 21.3837 9.63344 21.4128C9.70261 21.4418 9.775 21.4694 9.85061 21.4955C9.92623 21.5216 10.0047 21.546 10.086 21.5688C10.1674 21.5917 10.2512 21.6128 10.3374 21.6322C10.4237 21.6515 10.512 21.6691 10.6024 21.6848C10.6928 21.7005 10.7847 21.7144 10.8783 21.7263C10.972 21.7382 11.0667 21.7482 11.1627 21.7562C11.2586 21.7642 11.3552 21.7703 11.4526 21.7743C11.5499 21.7783 11.6475 21.7803 11.7453 21.7803C11.8432 21.7803 11.9407 21.7783 12.0381 21.7743C12.1354 21.7703 12.2321 21.7642 12.328 21.7562C12.4239 21.7482 12.5187 21.7382 12.6123 21.7263C12.7059 21.7144 12.7979 21.7005 12.8883 21.6848C12.9787 21.6691 13.067 21.6515 13.1532 21.6322C13.2395 21.6128 13.3233 21.5917 13.4046 21.5688C13.486 21.546 13.5644 21.5216 13.6401 21.4955C13.7157 21.4694 13.7881 21.4418 13.8572 21.4128C13.9264 21.3837 13.992 21.3533 14.0541 21.3215C14.1161 21.2898 14.1743 21.2568 14.2287 21.2226C14.283 21.1884 14.3332 21.1532 14.3793 21.117C14.4254 21.0807 14.4672 21.0436 14.5047 21.0057C14.5421 20.9677 14.575 20.929 14.6034 20.8897C14.6318 20.8504 14.6555 20.8106 14.6746 20.7703C14.6937 20.7299 14.708 20.6893 14.7176 20.6484C14.7272 20.6075 14.732 20.5665 14.732 20.5254C14.732 20.4843 14.7272 20.4433 14.7176 20.4024C14.708 20.3615 14.6937 20.3209 14.6746 20.2806C14.6555 20.2403 14.6318 20.2005 14.6034 20.1612C14.575 20.1218 14.5421 20.0832 14.5047 20.0452C14.4672 20.0072 14.4254 19.9701 14.3793 19.9339C14.3332 19.8976 14.283 19.8624 14.2287 19.8283C14.1743 19.7941 14.1161 19.7611 14.0541 19.7293C13.992 19.6976 13.9264 19.6672 13.8572 19.6381C13.7881 19.609 13.7157 19.5815 13.6401 19.5554C13.5644 19.5293 13.486 19.5049 13.4046 19.482C13.3233 19.4592 13.2395 19.4381 13.1532 19.4187C13.067 19.3993 12.9787 19.3818 12.8883 19.3661C12.7979 19.3503 12.7059 19.3365 12.6123 19.3246C12.5187 19.3126 12.4239 19.3027 12.328 19.2947C12.2321 19.2866 12.1354 19.2806 12.0381 19.2766C11.9407 19.2726 11.8432 19.2705 11.7453 19.2705C11.6475 19.2705 11.5499 19.2726 11.4526 19.2766C11.3552 19.2806 11.2586 19.2866 11.1627 19.2947C11.0667 19.3027 10.972 19.3126 10.8784 19.3246C10.7847 19.3365 10.6928 19.3503 10.6024 19.3661C10.512 19.3818 10.4237 19.3993 10.3374 19.4187C10.2512 19.4381 10.1674 19.4592 10.086 19.482C10.0047 19.5049 9.92623 19.5293 9.85061 19.5554C9.775 19.5815 9.70261 19.609 9.63344 19.6381C9.56427 19.6672 9.49866 19.6976 9.43661 19.7293C9.37455 19.7611 9.31635 19.7941 9.26201 19.8283C9.20767 19.8624 9.15744 19.8976 9.11133 19.9339C9.06522 19.9701 9.02345 20.0072 8.98601 20.0452C8.94858 20.0832 8.91567 20.1218 8.88727 20.1612C8.85888 20.2005 8.83514 20.2403 8.81605 20.2806C8.79697 20.3209 8.78264 20.3615 8.77305 20.4024C8.76346 20.4433 8.75867 20.4843 8.75867 20.5254L8.75867 20.5254Z" fill="rgb(5,95,194)" fill-rule="nonzero" /> <path id="矢量 544" d="M12 3C8.17162 3 5.05724 6.114 5.05762 9.942C5.05762 11.364 5.48474 12.7312 6.28424 13.8821C6.32437 13.9511 6.36487 14.0179 6.41249 14.0828L11.4799 20.7623C11.6175 20.9156 11.8024 21 12.0004 21C12.1957 21 12.3817 20.9149 12.5426 20.7345L17.5867 14.0816C17.6366 14.0156 17.679 13.9432 17.7022 13.9009C18.5134 12.7339 18.9427 11.3651 18.9427 9.94275C18.9427 6.114 15.8284 3 12 3ZM12 12.4249C10.6327 12.4249 9.52012 11.3123 9.52012 9.94462C9.52012 8.57737 10.6327 7.46513 12 7.46513C13.3672 7.46513 14.4799 8.57775 14.4799 9.94462C14.4799 11.3123 13.3672 12.4249 12 12.4249Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
</svg> </svg>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24.000000" height="24.000000" fill="none"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24.000000" height="24.000000" fill="none" customFrame="#000000">
<rect id="热门" width="24.000000" height="24.000000" x="0.000000" y="0.000000" /> <rect id="容器 239" width="24.000000" height="24.000000" x="0.000000" y="0.000000" />
<g id="组合 130"> <path id="合并" d="M17.822 5.13656C19.2945 6.38564 20.3262 8.07517 20.7648 9.95562C21.2033 11.8361 21.0255 13.8077 20.2576 15.5793C19.4896 17.351 18.1722 18.8286 16.5 19.7941L14.25 15.897C15.0861 15.4142 15.7448 14.6754 16.1288 13.7896C16.5128 12.9038 16.6017 11.918 16.3824 10.9777C16.1631 10.0375 15.6472 9.19274 14.911 8.5682C14.1747 7.94366 13.2572 7.57247 12.2938 7.50944L12.5875 3.01904C14.5143 3.14509 16.3495 3.88748 17.822 5.13656ZM4.97144 6.37851C4.19446 7.35001 3.62731 8.47202 3.30579 9.67374C2.98428 10.8755 2.91538 12.1308 3.10345 13.3605L7.55172 12.6802C7.45769 12.0653 7.49214 11.4377 7.6529 10.8368C7.81365 10.2359 8.09723 9.67493 8.48572 9.18918C8.87422 8.70343 9.35919 8.3035 9.91003 8.01462C10.4609 7.72574 11.0656 7.5542 11.6861 7.51081L11.3722 3.02177C10.1312 3.10855 8.92174 3.45164 7.82006 4.0294C6.71837 4.60715 5.74843 5.40702 4.97144 6.37851ZM11.6528 20.9931C10.4138 20.9453 9.19809 20.642 8.08187 20.1022C6.96565 19.5624 5.973 18.7978 5.16618 17.8564C4.35936 16.9149 3.75577 15.8169 3.39326 14.6312L7.69663 13.3155C7.87788 13.9084 8.17968 14.4574 8.58309 14.9281C8.9865 15.3988 9.48283 15.7811 10.0409 16.051C10.599 16.3209 11.2069 16.4726 11.8264 16.4965C12.4459 16.5204 13.0636 16.4161 13.6409 16.19L15.2817 20.3802C14.1272 20.8323 12.8917 21.041 11.6528 20.9931Z" fill="rgb(5,95,194)" fill-rule="evenodd" />
<path id="矢量 473" d="M8.5148 21C7.29316 18.4839 7.95351 17.0645 8.91101 15.7419C9.93455 14.2258 10.1987 12.8065 10.1987 12.8065C10.1987 12.8065 11.0241 13.8065 10.727 15.4516C12.1467 13.871 12.3778 11.3871 12.2127 10.4516C15.4154 12.6452 16.8352 17.4516 14.9532 20.9677C24.8253 15.4516 17.3964 7.25807 16.1088 6.3871C16.571 7.32258 16.637 8.90323 15.7126 9.64516C14.2268 4.06452 10.5619 3 10.5619 3C11.0241 5.80645 9.01006 8.87097 7.09506 11.1935C7.02903 10.0645 6.96299 9.32258 6.33566 8.19355C6.2036 10.2581 4.61877 11.9032 4.15653 13.9677C3.56221 16.8065 4.58575 18.8064 8.5148 21Z" fill="rgb(5,95,194)" fill-rule="nonzero" />
</g>
</svg> </svg>
<template>
<div class="view-box"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave">
<AiButton />
<AiPane :aiContent="myParams.content" />
</div>
</template>
<script setup lang="ts" name="AiReport">
import {reactive} from "vue"
import AiButton from '@/components/base/Ai/AiButton/index.vue';
import AiPane from '@/components/base/Ai/AiPane/index.vue';
const myParams = reactive({
data: "",
content: "",
isState: false,
})
const onDataInfo = (event:any) => {
console.log("需要分析的数据", event);
myParams.isState = false;
myParams.data = JSON.stringify(event);
}
let controller = null;
let reader = null;
// 鼠标进入监听
const handleMouseEnter = async () => {
if (myParams.isState) return;
myParams.content = "正在生成...";
if (controller) controller.abort();
controller = new AbortController();
try {
const res = await fetch('/aiAnalysis/chart_interpretation', {
method: 'POST',
headers: {
"X-API-Key": "aircasKEY19491001",
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: myParams.data }),
signal: controller.signal
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true });
const match = chunk.match(/"解读":\s*"([^"]*)"/);
if (match?.[1]) {
myParams.content = match[1];
myParams.isState = true;
return; // 获取到结果直接返回
}
}
myParams.content = "未获取到解读内容";
} catch (err) {
myParams.content = "系统异常,生成失败";
} finally {
reader?.cancel();
reader = null;
}
};
// 鼠标离开监听
const handleMouseLeave = () => {
controller?.abort();
reader?.cancel();
controller = null;
reader = null;
};
defineExpose({ onDataInfo })
</script>
<style scoped lang="scss">
.view-box {
position: absolute;
right: 0px;
bottom: 15px;
z-index: 2;
:deep(.ai-pane-wrapper) {
display: none;
}
:deep(.ai-button-wrapper) {
display: flex;
}
&:hover {
width: 100%;
bottom: 0px;
:deep(.ai-pane-wrapper) {
display: block;
}
:deep(.ai-button-wrapper) {
display: none;
}
}
}
</style>
\ No newline at end of file
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<div class="date-icon"> <div class="date-icon">
<img :src="tipsTcon" alt=""> <img :src="tipsTcon" alt="">
</div> </div>
<div class="date-text">近期美国各联邦政府机构市场准入限制调查数量汇总</div> <div class="date-text">近期美国各联邦政府机构市场准入限制涉华调查数量汇总</div>
<TimeTabPane @time-click="handleGetStatSort" activeTime="近一年" /> <TimeTabPane @time-click="handleGetStatSort" activeTime="近一年" />
</div> </div>
<div class="home-main-header-card-box"> <div class="home-main-header-card-box">
...@@ -77,10 +77,10 @@ ...@@ -77,10 +77,10 @@
</MessageBubble> </MessageBubble>
</div> </div>
<DivideHeader id="position3" class="divide-header" :titleText="'数据总览'"></DivideHeader> <DivideHeader id="position3" class="divide-header" :titleText="'全景概览'"></DivideHeader>
<div class="center-footer"> <div class="center-footer">
<div class="box5"> <div class="box5" v-loading="box5Loading">
<OverviewNormalBox title="数量变化趋势"> <OverviewNormalBox title="数量变化趋势" width="auto" height="100%">
<template #header-icon> <template #header-icon>
<img style="width: 100%; height: 100%;" src="./assets/icons/icon2.svg" alt="" /> <img style="width: 100%; height: 100%;" src="./assets/icons/icon2.svg" alt="" />
</template> </template>
...@@ -97,16 +97,13 @@ ...@@ -97,16 +97,13 @@
<el-empty v-if="!box5ChartData.title.length" description="暂无数据" style="padding: 100px 0 0;" :image-size="100" /> <el-empty v-if="!box5ChartData.title.length" description="暂无数据" style="padding: 100px 0 0;" :image-size="100" />
<div v-if="box5ChartData.title.length" style="width: 100%; height: 100%;" ref="box5Ref"></div> <div v-if="box5ChartData.title.length" style="width: 100%; height: 100%;" ref="box5Ref"></div>
</div> </div>
<TipTab text="美对华发起调查案件数量变化趋势,数据来源:美国国际贸易委员会、商务部、贸易代表办公室官网" style="margin-top: 16px;" /> <TipTab text="数据来源:美国国际贸易委员会、商务部、贸易代表办公室官网" style="margin-top: 16px;" />
<div class="ai-pane"> <AiReport ref="refAiReport5"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content5" />
</div>
</div> </div>
</OverviewNormalBox> </OverviewNormalBox>
</div> </div>
<div class="box6"> <div class="box6" v-loading="box6Loading">
<OverviewNormalBox title="领域分布情况" width="521px"> <OverviewNormalBox title="领域分布情况" width="auto" height="100%">
<template #header-icon> <template #header-icon>
<img style="width: 100%; height: 100%;" src="./assets/icons/icon3.svg" alt="" /> <img style="width: 100%; height: 100%;" src="./assets/icons/icon3.svg" alt="" />
</template> </template>
...@@ -122,18 +119,15 @@ ...@@ -122,18 +119,15 @@
<el-empty v-if="!box6Data.title.length" description="暂无数据" style="padding: 100px 0 0;" :image-size="100" /> <el-empty v-if="!box6Data.title.length" description="暂无数据" style="padding: 100px 0 0;" :image-size="100" />
<div v-if="box6Data.title.length" style="width: 100%; height: 100%;" id="box6Chart"></div> <div v-if="box6Data.title.length" style="width: 100%; height: 100%;" id="box6Chart"></div>
</div> </div>
<TipTab text="美对华发起调查案件领域分布情况,数据来源:美国国际贸易委员会、商务部、贸易代表办公室官网" ellipsis style="padding-right: 50px;" /> <TipTab text="数据来源:美国国际贸易委员会、商务部、贸易代表办公室官网" style="padding-right: 50px;" />
<div class="ai-pane"> <AiReport ref="refAiReport6"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content6" />
</div>
</div> </div>
</OverviewNormalBox> </OverviewNormalBox>
</div> </div>
</div> </div>
<div class="center-footer1"> <div class="center-footer1">
<div class="box7"> <div class="box7" v-loading="box7Loading">
<OverviewNormalBox title="国家分布情况" width="1064px"> <OverviewNormalBox title="国家分布情况" width="auto" height="100%">
<template #header-icon> <template #header-icon>
<img style="width: 100%; height: 100%;" src="./assets/icons/icon4.svg" alt="" /> <img style="width: 100%; height: 100%;" src="./assets/icons/icon4.svg" alt="" />
</template> </template>
...@@ -154,16 +148,13 @@ ...@@ -154,16 +148,13 @@
<el-empty v-if="!box7Data.data.length" description="暂无数据" style="padding: 100px 0 0;" :image-size="100" /> <el-empty v-if="!box7Data.data.length" description="暂无数据" style="padding: 100px 0 0;" :image-size="100" />
<div v-if="box7Data.data.length" style="width: 100%; height: 100%;" id="box7Chart"></div> <div v-if="box7Data.data.length" style="width: 100%; height: 100%;" id="box7Chart"></div>
</div> </div>
<TipTab :text="`美发起调查案件的被调查国家分布情况,数据来源:${box7TipText}`" style="margin-top: 10px;" /> <TipTab :text="`数据来源:${box7TipText}`" style="margin-top: 10px;" />
<div class="ai-pane"> <AiReport ref="refAiReport7"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content7" />
</div>
</div> </div>
</OverviewNormalBox> </OverviewNormalBox>
</div> </div>
<div class="box8"> <div class="box8" v-loading="box8Loading">
<OverviewNormalBox title="结果分布情况" width="521px"> <OverviewNormalBox title="结果分布情况" width="auto" height="100%">
<template #header-icon> <template #header-icon>
<img style="width: 100%; height: 100%" src="./assets/icons/icon5.svg" alt="" /> <img style="width: 100%; height: 100%" src="./assets/icons/icon5.svg" alt="" />
</template> </template>
...@@ -179,11 +170,8 @@ ...@@ -179,11 +170,8 @@
<el-empty v-if="!box8Data.length" description="暂无数据" style="padding: 100px 0 0;" :image-size="100" /> <el-empty v-if="!box8Data.length" description="暂无数据" style="padding: 100px 0 0;" :image-size="100" />
<div v-if="box8Data.length" style="width: 100%; height: 100%;" ref="box8Ref"></div> <div v-if="box8Data.length" style="width: 100%; height: 100%;" ref="box8Ref"></div>
</div> </div>
<TipTab :text="`美发起调查案件的被调查国家分布情况,数据来源:${box8TipText}`" ellipsis style="padding-right: 50px;" /> <TipTab :text="`数据来源:${box8TipText}`" style="padding-right: 50px;" />
<div class="ai-pane"> <AiReport ref="refAiReport8"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content8" />
</div>
</div> </div>
</OverviewNormalBox> </OverviewNormalBox>
</div> </div>
...@@ -191,19 +179,10 @@ ...@@ -191,19 +179,10 @@
</div> </div>
<div class="home-main-footer"> <div class="home-main-footer">
<DivideHeader id="position4" class="divide-header" :titleText="'资源库'"></DivideHeader> <DivideHeader id="position4" class="divide-header" titleText="市场准入限制数据库"></DivideHeader>
<div class="home-main-footer-header"> <div class="home-main-footer-header">
<SourceTabList :sourceTabList="categoryList" :activeSouceTabId="activeCateId" @clickTab="handleClickCate"></SourceTabList> <SourceTabList :sourceTabList="categoryList" :activeSouceTabId="activeCateId" @clickTab="handleClickCate"></SourceTabList>
<div class="select-box"> <TimeSortSelectBox @handle-px-change="handlePxChange"></TimeSortSelectBox>
<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/jiangxu1.png" 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="home-main-footer-main"> <div class="home-main-footer-main">
<div class="left"> <div class="left">
...@@ -225,8 +204,9 @@ ...@@ -225,8 +204,9 @@
</div> </div>
<div class="left-main"> <div class="left-main">
<el-checkbox-group class="check-list" v-model="checkedYearList" @change="handleCheckedYearsChange"> <el-checkbox-group class="check-list" v-model="checkedYearList" @change="handleCheckedYearsChange">
<el-checkbox class="check-item" v-for="item in surveyYearList" :key="item.id" :label="item.id"> <el-checkbox class="check-item" label="">全部时间</el-checkbox>
{{ item.name }} <el-checkbox class="check-item" v-for="item in nearYearList" :key="item.value" :label="item.value">
{{ item.label }}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
</div> </div>
...@@ -295,21 +275,21 @@ import NewsList from "@/components/base/newsList/index.vue"; ...@@ -295,21 +275,21 @@ import NewsList from "@/components/base/newsList/index.vue";
import DivideHeader from "@/components/DivideHeader.vue"; import DivideHeader from "@/components/DivideHeader.vue";
import SurveyHistory from "@/views/marketAccessRestrictions/com/SurveyHistory.vue" import SurveyHistory from "@/views/marketAccessRestrictions/com/SurveyHistory.vue"
import TimeTabPane from '@/components/base/TimeTabPane/index.vue'; import TimeTabPane from '@/components/base/TimeTabPane/index.vue';
import TimeSortSelectBox from '@/components/base/TimeSortSelectBox/index.vue';
import CarouselItem337 from '@/views/marketAccessRestrictions/marketAccessHome/com/CarouselItem337.vue'; import CarouselItem337 from '@/views/marketAccessRestrictions/marketAccessHome/com/CarouselItem337.vue';
import CarouselItem301 from '@/views/marketAccessRestrictions/marketAccessHome/com/CarouselItem301.vue'; import CarouselItem301 from '@/views/marketAccessRestrictions/marketAccessHome/com/CarouselItem301.vue';
import CarouselItem232 from '@/views/marketAccessRestrictions/marketAccessHome/com/CarouselItem232.vue'; import CarouselItem232 from '@/views/marketAccessRestrictions/marketAccessHome/com/CarouselItem232.vue';
import setChart from "@/utils/setChart"; import setChart from "@/utils/setChart";
import { getDateBefore, getAIReport, getNearYearList } from "@/views/marketAccessRestrictions/utils/index.ts"; import { getDateBefore, getNearYearList } from "@/views/marketAccessRestrictions/utils/index.ts";
import router from "@/router"; import router from "@/router";
import { navigateToViewRiskSignal } from "@/utils/riskSignalOverviewNavigate"; import { navigateToViewRiskSignal } from "@/utils/riskSignalOverviewNavigate";
import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChart"; import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChart.js";
import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js"; import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js";
import getRadarChart from "./utils/radarChart"; import getRadarChart from "./utils/radarChart";
import getBarChart from "./utils/barChart1"; import getBarChart from "@/views/marketAccessRestrictions/marketAccessHome/utils/barChart1.js";
import AiButton from '@/components/base/Ai/AiButton/index.vue'; import AiReport from '@/views/marketAccessRestrictions/marketAccessHome/com/AiReport.vue';
import AiPane from '@/components/base/Ai/AiPane/index.vue';
import { getPersonSummaryInfo } from "@/api/common/index"; import { getPersonSummaryInfo } from "@/api/common/index";
import { import {
...@@ -332,15 +312,15 @@ import tipsTcon from "./assets/icons/tips-icon.png"; ...@@ -332,15 +312,15 @@ import tipsTcon from "./assets/icons/tips-icon.png";
const getCardClass = (code) => ['theme-card', `theme-${code}`] const getCardClass = (code) => ['theme-card', `theme-${code}`]
// 获取AI智能报告 // 获取AI智能报告
const aiContent = reactive({ const refAiReport5 = ref(null)
content5: "正在生成...", const refAiReport6 = ref(null)
content6: "正在生成...", const refAiReport7 = ref(null)
content7: "正在生成...", const refAiReport8 = ref(null)
content8: "正在生成...",
}) const box5Loading = ref(false);
const onAIReport = (data, key) => { const box6Loading = ref(false);
getAIReport(data).then(res => { aiContent[key] = res }) const box7Loading = ref(false);
} const box8Loading = ref(false);
const handleToPosi = id => { const handleToPosi = id => {
const element = document.getElementById(id); const element = document.getElementById(id);
...@@ -653,6 +633,7 @@ const box5Ref = ref(null) ...@@ -653,6 +633,7 @@ const box5Ref = ref(null)
const box5Active = ref(1); const box5Active = ref(1);
const hadleGetStatNum = async (event) => { const hadleGetStatNum = async (event) => {
if (event) box5Active.value = event; if (event) box5Active.value = event;
box5Loading.value = true;
try { try {
let byYorM = box5Active.value let byYorM = box5Active.value
const res = await getStatNum({byYorM}); const res = await getStatNum({byYorM});
...@@ -663,7 +644,6 @@ const hadleGetStatNum = async (event) => { ...@@ -663,7 +644,6 @@ const hadleGetStatNum = async (event) => {
} else { } else {
box5ChartData.value = transformAllData(res.data); box5ChartData.value = transformAllData(res.data);
} }
onAIReport({ type: "折线图", name: "数量变化趋势", data: res.data }, "content5")
} else { } else {
box5ChartData.value.title = []; box5ChartData.value.title = [];
box5ChartData.value.list = [ box5ChartData.value.list = [
...@@ -671,7 +651,6 @@ const hadleGetStatNum = async (event) => { ...@@ -671,7 +651,6 @@ const hadleGetStatNum = async (event) => {
{ name: "301调查", value: [] }, { name: "301调查", value: [] },
{ name: "232调查", value: [] } { name: "232调查", value: [] }
] ]
aiContent.content5 = "";
} }
} catch (error) { } catch (error) {
box5ChartData.value.title = []; box5ChartData.value.title = [];
...@@ -680,9 +659,10 @@ const hadleGetStatNum = async (event) => { ...@@ -680,9 +659,10 @@ const hadleGetStatNum = async (event) => {
{ name: "301调查", value: [] }, { name: "301调查", value: [] },
{ name: "232调查", value: [] } { name: "232调查", value: [] }
] ]
aiContent.content5 = "";
} }
refAiReport5.value?.onDataInfo({ type: "折线图", name: "数量变化趋势", data: box5ChartData.value })
nextTick(() => { createLineChart(box5Ref, box5ChartData.value) }) nextTick(() => { createLineChart(box5Ref, box5ChartData.value) })
box5Loading.value = false;
}; };
// 领域分布情况 // 领域分布情况
...@@ -700,24 +680,16 @@ const box6Data = ref({ ...@@ -700,24 +680,16 @@ const box6Data = ref({
maxNum: 0 maxNum: 0
}); });
const handleGetStatArea = async () => { const handleGetStatArea = async () => {
const params = { box6Loading.value = true;
years: box6SelectedYear.value
};
try { try {
const res = await getStatArea(params); const res = await getStatArea({years: box6SelectedYear.value});
console.log("领域分布情况", res); console.log("领域分布情况", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const arr = res.data.map(item => { const arr = res.data.map(item => item.areaname);
return item.areaname;
});
box6Data.value.title = [...new Set(arr)]; box6Data.value.title = [...new Set(arr)];
const arr1 = res.data.filter(item => { const arr1 = res.data.filter(item => item.sortname === "337调查");
return item.sortname === "337调查"; const arr1Name = arr1.map(item => item.areaname);
});
const arr1Name = arr1.map(item => {
return item.areaname;
});
box6Data.value.title.forEach((item, index) => { box6Data.value.title.forEach((item, index) => {
if (arr1Name.indexOf(item) > -1) { if (arr1Name.indexOf(item) > -1) {
const idx = arr1Name.indexOf(item); const idx = arr1Name.indexOf(item);
...@@ -727,12 +699,8 @@ const handleGetStatArea = async () => { ...@@ -727,12 +699,8 @@ const handleGetStatArea = async () => {
} }
}); });
const arr2 = res.data.filter(item => { const arr2 = res.data.filter(item => item.sortname === "232调查");
return item.sortname === "232调查"; const arr2Name = arr2.map(item => item.areaname);
});
const arr2Name = arr2.map(item => {
return item.areaname;
});
box6Data.value.title.forEach((item, index) => { box6Data.value.title.forEach((item, index) => {
if (arr2Name.indexOf(item) > -1) { if (arr2Name.indexOf(item) > -1) {
const idx = arr2Name.indexOf(item); const idx = arr2Name.indexOf(item);
...@@ -742,12 +710,8 @@ const handleGetStatArea = async () => { ...@@ -742,12 +710,8 @@ const handleGetStatArea = async () => {
} }
}); });
const arr3 = res.data.filter(item => { const arr3 = res.data.filter(item => item.sortname === "301调查");
return item.sortname === "301调查"; const arr3Name = arr3.map(item => item.areaname);
});
const arr3Name = arr3.map(item => {
return item.areaname;
});
box6Data.value.title.forEach((item, index) => { box6Data.value.title.forEach((item, index) => {
if (arr3Name.indexOf(item) > -1) { if (arr3Name.indexOf(item) > -1) {
const idx = arr3Name.indexOf(item); const idx = arr3Name.indexOf(item);
...@@ -756,14 +720,8 @@ const handleGetStatArea = async () => { ...@@ -756,14 +720,8 @@ const handleGetStatArea = async () => {
box6Data.value.data[2].value[index] = 0; box6Data.value.data[2].value[index] = 0;
} }
}); });
const numArr = res.data.map(item => item.AREACOUNT);
const numArr = res.data.map(item => {
return item.AREACOUNT;
});
box6Data.value.maxNum = Math.max(...numArr); box6Data.value.maxNum = Math.max(...numArr);
onAIReport({ type: "雷达图", name: "领域分布情况", data: res.data }, "content6")
} else { } else {
box6Data.value.title = []; box6Data.value.title = [];
box6Data.value.data = [ box6Data.value.data = [
...@@ -772,9 +730,18 @@ const handleGetStatArea = async () => { ...@@ -772,9 +730,18 @@ const handleGetStatArea = async () => {
{ name: "301调查", value: [] } { name: "301调查", value: [] }
]; ];
box6Data.value.maxNum = 0; box6Data.value.maxNum = 0;
aiContent.content6 = "";
} }
} catch (error) { } } catch (error) {
box6Data.value.title = [];
box6Data.value.data = [
{ name: "337调查", value: [] },
{ name: "232调查", value: [] },
{ name: "301调查", value: [] }
];
box6Data.value.maxNum = 0;
}
refAiReport6.value?.onDataInfo({ type: "雷达图", name: "领域分布情况", data: box6Data.value })
box6Loading.value = false;
}; };
const handleBox6 = async () => { const handleBox6 = async () => {
await handleGetStatArea(); await handleGetStatArea();
...@@ -797,12 +764,12 @@ const box7TipText = computed(() => { ...@@ -797,12 +764,12 @@ const box7TipText = computed(() => {
return "" return ""
}) })
const handleGetBox7Data = async () => { const handleGetBox7Data = async () => {
const params = { box7Loading.value = true
try {
const res = await getSearchCountry({
sortCode: box7SelectedSurvey.value, sortCode: box7SelectedSurvey.value,
years: box7SelectedYear.value years: box7SelectedYear.value
}; });
try {
const res = await getSearchCountry(params);
console.log("国家分布情况", res); console.log("国家分布情况", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
box7Data.title = res.data.map(item => { box7Data.title = res.data.map(item => {
...@@ -814,17 +781,16 @@ const handleGetBox7Data = async () => { ...@@ -814,17 +781,16 @@ const handleGetBox7Data = async () => {
box7Data.data = res.data.map(item => { box7Data.data = res.data.map(item => {
return item.NUM; return item.NUM;
}); });
onAIReport({ type: "柱状图", name: "国家分布情况", data: res.data }, "content7")
} else { } else {
box7Data.title = []; box7Data.title = [];
box7Data.data = []; box7Data.data = [];
aiContent.content7 = "";
} }
} catch (error) { } catch (error) {
box7Data.title = []; box7Data.title = [];
box7Data.data = []; box7Data.data = [];
aiContent.content7 = "";
} }
refAiReport7.value?.onDataInfo({ type: "柱状图", name: "国家分布情况", data: box7Data })
box7Loading.value = false;
}; };
const handleBox7 = async () => { const handleBox7 = async () => {
...@@ -849,21 +815,21 @@ const box8TipText = computed(() => { ...@@ -849,21 +815,21 @@ const box8TipText = computed(() => {
return "" return ""
}) })
const handleGetBox8Data = async () => { const handleGetBox8Data = async () => {
box8Loading.value = true;
try { try {
const res = await getSearchResult({sortCode: box8SelectedSurvey.value}); const res = await getSearchResult({sortCode: box8SelectedSurvey.value});
console.log("结果分布情况", res); console.log("结果分布情况", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
box8Data.value = res.data.map(item => ({ name: item.RESULTNAME, value: item.RESULTNUM })) box8Data.value = res.data.map(item => ({ name: item.RESULTNAME, value: item.RESULTNUM }))
onAIReport({ type: "环形图", name: "结果分布情况", data: res.data }, "content8")
} else { } else {
box8Data.value = [] box8Data.value = []
aiContent.content8 = "";
} }
} catch (error) { } catch (error) {
box8Data.value = [] box8Data.value = []
aiContent.content8 = "";
} }
nextTick(() => { createPieChart(box8Ref, box8Data.value, {labelType:1}) }) refAiReport8.value?.onDataInfo({ type: "环形图", name: "结果分布情况", data: box8Data.value })
nextTick(() => { createPieChart(box8Ref, box8Data.value) })
box8Loading.value = false;
}; };
// 资源库 // 资源库
...@@ -889,24 +855,14 @@ const handleClickCate = item => { ...@@ -889,24 +855,14 @@ const handleClickCate = item => {
handleFetchSurveyList(); handleFetchSurveyList();
}; };
const releaseTimeList = ref([
{ label: "按发布时间倒序", value: true },
{ label: "按发布时间升序", value: false }
]);
const isSort = ref(true); const isSort = ref(true);
const handlePxChange = () => { const handlePxChange = (event) => {
isSort.value = event == 1;
currentPage.value = 1; currentPage.value = 1;
handleFetchSurveyList(); handleFetchSurveyList();
}; };
const surveyYearList = ref([ const nearYearList = getNearYearList(7);
{ name: "全部时间", id: "" },
{ name: "2025年", id: "2025" },
{ name: "2024年", id: "2024" },
{ name: "2023年", id: "2023" },
{ name: "2022年", id: "2022" },
{ name: "2021年", id: "2021" }
]);
const checkedYearList = ref(['']); const checkedYearList = ref(['']);
const handleCheckedYearsChange = event => { const handleCheckedYearsChange = event => {
if (event.length && event[event.length-1] !== "") { if (event.length && event[event.length-1] !== "") {
...@@ -925,7 +881,7 @@ const handleGetSearchAllArea = async () => { ...@@ -925,7 +881,7 @@ const handleGetSearchAllArea = async () => {
try { try {
const res = await getHylyList(); const res = await getHylyList();
if (res.code === 200) { if (res.code === 200) {
surveyAreaList.value = res.data.map(item => ({ name: item.name, id: item.id })); surveyAreaList.value = res.data;
} }
} catch (error) {} } catch (error) {}
surveyAreaList.value.unshift({ name: "全部领域", id: "" }); surveyAreaList.value.unshift({ name: "全部领域", id: "" });
...@@ -1814,15 +1770,16 @@ onMounted(async () => { ...@@ -1814,15 +1770,16 @@ onMounted(async () => {
} }
.center-footer { .center-footer {
margin-top: 21px; margin: 21px auto 0;
height: 460px; height: 460px;
display: flex; display: flex;
justify-content: center; gap: 16px;
gap: 15px; width: 1600px;
.box5 { .box5 {
width: 1064px; width: 20px;
height: 460px; flex: auto;
height: 100%;
.box-header-right { .box-header-right {
height: 48px; height: 48px;
...@@ -1865,8 +1822,9 @@ onMounted(async () => { ...@@ -1865,8 +1822,9 @@ onMounted(async () => {
} }
.box6 { .box6 {
width: 521px; width: 20px;
height: 460px; flex: auto;
height: 100%;
.box-header-right { .box-header-right {
height: 48px; height: 48px;
...@@ -1879,14 +1837,16 @@ onMounted(async () => { ...@@ -1879,14 +1837,16 @@ onMounted(async () => {
} }
.center-footer1 { .center-footer1 {
margin-top: 16px; margin: 16px auto 0;
height: 460px;
display: flex; display: flex;
justify-content: center; gap: 16px;
gap: 15px; width: 1600px;
.box7 { .box7 {
width: 1064px; width: 20px;
height: 460px; flex: auto;
height: 100%;
.box-header-right { .box-header-right {
height: 48px; height: 48px;
...@@ -1903,8 +1863,9 @@ onMounted(async () => { ...@@ -1903,8 +1863,9 @@ onMounted(async () => {
} }
.box8 { .box8 {
width: 521px; width: 20px;
height: 460px; flex: auto;
height: 100%;
.box-header-right { .box-header-right {
height: 48px; height: 48px;
...@@ -1929,47 +1890,7 @@ onMounted(async () => { ...@@ -1929,47 +1890,7 @@ onMounted(async () => {
margin: 0 auto; margin: 0 auto;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center;
.btn-box {
width: 1000px;
display: flex;
.btn {
color: rgba(95, 101, 108, 1);
font-family: Source Han Sans CN;
font-size: 16px;
font-weight: 400;
line-height: 42px;
padding: 0 24px;
border-radius: 21px;
background: rgba(20, 89, 187, 0);
margin-right: 20px;
cursor: pointer;
&:hover {
background: rgba(20, 89, 187, 0.1);
}
}
.btnActive {
padding: 0 24px;
border-radius: 21px;
background: rgba(20, 89, 187, 1);
color: #fff;
&:hover {
color: #fff;
background: rgba(20, 89, 187, 1);
}
}
}
.select-box {
height: 42px;
box-sizing: border-box;
padding: 5px 0;
}
} }
.home-main-footer-main { .home-main-footer-main {
......
...@@ -83,13 +83,8 @@ const getBarChart = (nameList, valueList) => { ...@@ -83,13 +83,8 @@ const getBarChart = (nameList, valueList) => {
xAxis: index, xAxis: index,
yAxis: valueList[index], yAxis: valueList[index],
symbol: `image://${item.img}`, symbol: `image://${item.img}`,
symbolSize: 20, symbolSize: [20, 20],
symbolCircle: 20, symbolOffset: [0, 10]
itemStyle: {
borderRadius: '50%',
borderColor: '#fff',
borderWidth: 2
}
}); });
}); });
return data; return data;
......
const getRadarChart = (data) => { const getRadarChart = (data) => {
// const indicators = [
// { name: "集成电路", max: 10 },
// { name: "能源领域", max: 10 },
// { name: "量子科技", max: 10 },
// { name: "通信网络", max: 10 },
// { name: "人工智能", max: 10 },
// { name: "生物科技", max: 10 }
// ];
const indicators = data.title.map(item => { const indicators = data.title.map(item => {
return { return {
name: item, max: data.maxNum name: item, 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 = { const option = {
color: ["rgba(5, 95, 194, 1)", "rgba(250, 140, 22, 1)", "rgba(146, 84, 222, 1)"], color: ["rgba(5, 95, 194, 1)", "rgba(250, 140, 22, 1)", "rgba(146, 84, 222, 1)"],
legend: { legend: {
top: 8, top: 8,
left: 30, left: 'center',
icon: "circle", icon: "circle",
itemWidth: 12, itemWidth: 12,
itemHeight: 12, itemHeight: 12,
......
...@@ -8,8 +8,7 @@ ...@@ -8,8 +8,7 @@
<div class="dropdown-filters"> <div class="dropdown-filters">
<el-select v-model="filterStage" placeholder="全部阶段" class="filter-select" clearable> <el-select v-model="filterStage" placeholder="全部阶段" class="filter-select" clearable>
<el-option label="全部阶段" value="" /> <el-option label="全部阶段" value="" />
<el-option label="调查中" value="1" /> <el-option v-for="item in stateList" :key="item.id" :label="item.name" :value="item.id" />
<el-option label="调查结束" value="0" />
</el-select> </el-select>
<!-- <el-select v-model="filterParty" placeholder="全部原告/被告" class="filter-select" clearable> <!-- <el-select v-model="filterParty" placeholder="全部原告/被告" class="filter-select" clearable>
<el-option label="全部原告/被告" value="" /> <el-option label="全部原告/被告" value="" />
...@@ -19,17 +18,7 @@ ...@@ -19,17 +18,7 @@
</el-select> --> </el-select> -->
</div> </div>
</div> </div>
<div class="select-box"> <TimeSortSelectBox @handle-px-change="handlePxChange"></TimeSortSelectBox>
<el-select v-model="isSort" placeholder="发布时间" style="width: 166px">
<template #prefix>
<div style="display: flex; align-items: center; height: 100%">
<img src="@/assets/icons/jiangxu1.png" style="width: 14px; height: 14px" />
</div>
</template>
<el-option label="按发布时间降序" value="desc" />
<el-option label="按发布时间升序" value="asc" />
</el-select>
</div>
</div> </div>
<div class="wrapper-main"> <div class="wrapper-main">
<div class="left"> <div class="left">
...@@ -89,25 +78,44 @@ ...@@ -89,25 +78,44 @@
<script setup> <script setup>
import { ref, onMounted, watch } from "vue"; import { ref, onMounted, watch } from "vue";
import { Search } from "@element-plus/icons-vue"; import { Search } from "@element-plus/icons-vue";
import { getSearchAllArea, getSearchAllYear, getSurveyList } from "@/api/marketAccessRestrictions"; import {
getHylyList,
getSearchAllYear,
getSurveyList,
getAllProgressStatus,
} from "@/api/marketAccessRestrictions";
import SurveyHistory from "@/views/marketAccessRestrictions/com/SurveyHistory.vue" import SurveyHistory from "@/views/marketAccessRestrictions/com/SurveyHistory.vue"
import TimeSortSelectBox from '@/components/base/TimeSortSelectBox/index.vue';
// 顶部过滤项 // 顶部过滤项
const searchText = ref(""); const searchText = ref("");
const filterStage = ref(""); const filterStage = ref("");
const filterParty = ref(""); const filterParty = ref("");
const filterReason = ref(""); const filterReason = ref("");
const isSort = ref('desc'); // 降序 const isSort = ref(true);
const handlePxChange = (event) => {
isSort.value = event == 1;
currentPage.value = 1;
handleFetchSurveyList();
};
// 获取阶段列表
const stateList = ref([]);
const onAllProgressStatus = async () => {
try {
const res = await getAllProgressStatus();
console.log("阶段列表", res)
if (res.code === 200) stateList.value = res.data;
} catch (error) {}
}
// 科技领域过滤 // 科技领域过滤
const surveyAreaList = ref([]); const surveyAreaList = ref([]);
const checkedAreaList = ref(['']); const checkedAreaList = ref(['']);
const handleGetSearchAllArea = async () => { const handleGetSearchAllArea = async () => {
try { try {
const res = await getSearchAllArea({ sortCode: "232" }); const res = await getHylyList();
if (res.code === 200) { if (res.code === 200) surveyAreaList.value = res.data;
surveyAreaList.value = res.data.map(item => ({ name: item.AREANAME, id: item.AREACODE }));
}
} catch (error) {} } catch (error) {}
surveyAreaList.value.unshift({ name: "全部领域", id: "" }); surveyAreaList.value.unshift({ name: "全部领域", id: "" });
}; };
...@@ -163,17 +171,23 @@ const handleFetchSurveyList = async () => { ...@@ -163,17 +171,23 @@ const handleFetchSurveyList = async () => {
sortCode: "232", sortCode: "232",
publishYear: checkedYearList.value.join(',') || null, publishYear: checkedYearList.value.join(',') || null,
Area: checkedAreaList.value.join(',') || null, Area: checkedAreaList.value.join(',') || null,
caseStatus: filterStage.value, caseStatus: filterStage.value || null,
keywords: searchText.value || null, keywords: searchText.value || null,
sortField: "date", sortField: "date",
sortOrder: isSort.value sortOrder: isSort.value ? "desc" : "asc"
}; };
const res = await getSurveyList(params); const res = await getSurveyList(params);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
surveyInfoList.value = res.data.content; surveyInfoList.value = res.data.content;
totalDiscussNum.value = res.data.totalElements || 0; totalDiscussNum.value = res.data.totalElements || 0;
} else {
surveyInfoList.value = []
totalDiscussNum.value = 0
}
} catch (error) {
surveyInfoList.value = []
totalDiscussNum.value = 0
} }
} catch (error) {}
listLoading.value = false; listLoading.value = false;
}; };
...@@ -188,14 +202,16 @@ const handleSearch = () => { ...@@ -188,14 +202,16 @@ const handleSearch = () => {
}; };
// 监听过滤条件 // 监听过滤条件
watch([isSort, filterStage, filterParty, filterReason], () => { watch([filterStage, filterParty, filterReason], () => {
if (isInitializing.value) return; if (isInitializing.value) return;
currentPage.value = 1; currentPage.value = 1;
handleFetchSurveyList(); handleFetchSurveyList();
}); });
onMounted(async () => { onMounted(() => {
await Promise.all([handleGetSearchAllArea(), handleGetSearchAllYear()]); onAllProgressStatus()
handleGetSearchAllArea()
handleGetSearchAllYear()
isInitializing.value = false; isInitializing.value = false;
handleFetchSurveyList(); handleFetchSurveyList();
}); });
...@@ -287,6 +303,7 @@ onMounted(async () => { ...@@ -287,6 +303,7 @@ onMounted(async () => {
font-family: Source Han Sans CN; font-family: Source Han Sans CN;
font-size: 16px; font-size: 16px;
color: var(--text-primary-65-color); color: var(--text-primary-65-color);
font-weight: 400;
} }
} }
} }
......
...@@ -5,19 +5,15 @@ ...@@ -5,19 +5,15 @@
<div class="search-box"> <div class="search-box">
<el-input v-model="searchText" style="width: 360px; height: 32px" placeholder="搜索调查案件" @keyup.enter="handleSearch" :suffix-icon="Search"></el-input> <el-input v-model="searchText" style="width: 360px; height: 32px" placeholder="搜索调查案件" @keyup.enter="handleSearch" :suffix-icon="Search"></el-input>
</div> </div>
</div> <div class="dropdown-filters">
<div class="select-box"> <el-select v-model="filterStage" placeholder="全部阶段" class="filter-select" clearable @change="handleSearch()">
<el-select v-model="isSort" placeholder="发布时间" style="width: 166px"> <el-option label="全部阶段" value="" />
<template #prefix> <el-option v-for="item in stateList" :key="item.id" :label="item.name" :value="item.id" />
<div style="display: flex; align-items: center; height: 100%">
<img src="@/assets/icons/jiangxu1.png" style="width: 14px; height: 14px" />
</div>
</template>
<el-option label="按发布时间降序" value="desc" />
<el-option label="按发布时间升序" value="asc" />
</el-select> </el-select>
</div> </div>
</div> </div>
<TimeSortSelectBox @handle-px-change="handlePxChange"></TimeSortSelectBox>
</div>
<div class="wrapper-main"> <div class="wrapper-main">
<div class="left"> <div class="left">
<!-- 科技领域 --> <!-- 科技领域 -->
...@@ -67,21 +63,41 @@ ...@@ -67,21 +63,41 @@
<script setup> <script setup>
import { ref, onMounted, watch } from "vue"; import { ref, onMounted, watch } from "vue";
import { Search } from "@element-plus/icons-vue"; import { Search } from "@element-plus/icons-vue";
import { getSearchAllArea, getSearchAllYear, getSurveyList } from "@/api/marketAccessRestrictions"; import {
getHylyList,
getSearchAllYear,
getSurveyList,
getAllProgressStatus,
} from "@/api/marketAccessRestrictions";
import SurveyHistory from "@/views/marketAccessRestrictions/com/SurveyHistory.vue" import SurveyHistory from "@/views/marketAccessRestrictions/com/SurveyHistory.vue"
import TimeSortSelectBox from '@/components/base/TimeSortSelectBox/index.vue';
const searchText = ref(''); // 搜索文本 const searchText = ref(''); // 搜索文本
const isSort = ref('desc'); // 降序 const filterStage = ref("");
const isSort = ref(true);
const handlePxChange = (event) => {
isSort.value = event == 1;
currentPage.value = 1;
handleFetchSurveyList();
};
// 获取阶段列表
const stateList = ref([]);
const onAllProgressStatus = async () => {
try {
const res = await getAllProgressStatus();
console.log("阶段列表", res)
if (res.code === 200) stateList.value = res.data;
} catch (error) {}
}
// 科技领域过滤 // 科技领域过滤
const surveyAreaList = ref([]); const surveyAreaList = ref([]);
const checkedAreaList = ref(['']); const checkedAreaList = ref(['']);
const handleGetSearchAllArea = async () => { const handleGetSearchAllArea = async () => {
try { try {
const res = await getSearchAllArea({ sortCode: "301" }); const res = await getHylyList();
if (res.code === 200) { if (res.code === 200) surveyAreaList.value = res.data;
surveyAreaList.value = res.data.map(item => ({ name: item.AREANAME, id: item.AREACODE }));
}
} catch (error) {} } catch (error) {}
surveyAreaList.value.unshift({ name: "全部领域", id: "" }); surveyAreaList.value.unshift({ name: "全部领域", id: "" });
}; };
...@@ -137,16 +153,23 @@ const handleFetchSurveyList = async () => { ...@@ -137,16 +153,23 @@ const handleFetchSurveyList = async () => {
sortCode: "301", sortCode: "301",
publishYear: checkedYearList.value.join(',') || null, publishYear: checkedYearList.value.join(',') || null,
Area: checkedAreaList.value.join(',') || null, Area: checkedAreaList.value.join(',') || null,
caseStatus: filterStage.value || null,
keywords: searchText.value || null, keywords: searchText.value || null,
sortField: "date", sortField: "date",
sortOrder: isSort.value sortOrder: isSort.value ? "desc" : "asc"
}; };
const res = await getSurveyList(params); const res = await getSurveyList(params);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
surveyInfoList.value = res.data.content; surveyInfoList.value = res.data.content;
totalDiscussNum.value = res.data.totalElements || 0; totalDiscussNum.value = res.data.totalElements || 0;
} else {
surveyInfoList.value = []
totalDiscussNum.value = 0
}
} catch (error) {
surveyInfoList.value = []
totalDiscussNum.value = 0
} }
} catch (error) {}
listLoading.value = false; listLoading.value = false;
}; };
...@@ -160,14 +183,10 @@ const handleSearch = () => { ...@@ -160,14 +183,10 @@ const handleSearch = () => {
handleFetchSurveyList(); handleFetchSurveyList();
}; };
watch([isSort], () => { onMounted(() => {
if (isInitializing.value) return; onAllProgressStatus()
currentPage.value = 1; handleGetSearchAllArea()
handleFetchSurveyList(); handleGetSearchAllYear()
});
onMounted(async () => {
await Promise.all([handleGetSearchAllArea(), handleGetSearchAllYear()]);
isInitializing.value = false; isInitializing.value = false;
handleFetchSurveyList(); handleFetchSurveyList();
}); });
...@@ -258,6 +277,7 @@ onMounted(async () => { ...@@ -258,6 +277,7 @@ onMounted(async () => {
font-family: Source Han Sans CN; font-family: Source Han Sans CN;
font-size: 16px; font-size: 16px;
color: var(--text-primary-65-color); color: var(--text-primary-65-color);
font-weight: 400;
} }
} }
} }
......
...@@ -8,8 +8,7 @@ ...@@ -8,8 +8,7 @@
<div class="dropdown-filters"> <div class="dropdown-filters">
<el-select v-model="filterStage" placeholder="全部阶段" class="filter-select" clearable> <el-select v-model="filterStage" placeholder="全部阶段" class="filter-select" clearable>
<el-option label="全部阶段" value="" /> <el-option label="全部阶段" value="" />
<el-option label="调查中" value="1" /> <el-option v-for="item in stateList" :key="item.id" :label="item.name" :value="item.id" />
<el-option label="调查结束" value="0" />
</el-select> </el-select>
<!-- <el-select v-model="filterParty" placeholder="全部原告/被告" class="filter-select" clearable> <!-- <el-select v-model="filterParty" placeholder="全部原告/被告" class="filter-select" clearable>
<el-option label="全部原告/被告" value="" /> <el-option label="全部原告/被告" value="" />
...@@ -19,17 +18,7 @@ ...@@ -19,17 +18,7 @@
</el-select> --> </el-select> -->
</div> </div>
</div> </div>
<div class="select-box"> <TimeSortSelectBox @handle-px-change="handlePxChange"></TimeSortSelectBox>
<el-select v-model="isSort" placeholder="发布时间" style="width: 166px">
<template #prefix>
<div style="display: flex; align-items: center; height: 100%">
<img src="@/assets/icons/jiangxu1.png" style="width: 14px; height: 14px" />
</div>
</template>
<el-option label="按发布时间降序" value="desc" />
<el-option label="按发布时间升序" value="asc" />
</el-select>
</div>
</div> </div>
<div class="wrapper-main"> <div class="wrapper-main">
<div class="left"> <div class="left">
...@@ -90,27 +79,47 @@ ...@@ -90,27 +79,47 @@
<script setup> <script setup>
import { ref, onMounted, watch } from "vue"; import { ref, onMounted, watch } from "vue";
import { Search } from "@element-plus/icons-vue"; import { Search } from "@element-plus/icons-vue";
import { getSearchAllArea, getSearchAllYear, getSurveyList, getSearchAllCountry } from "@/api/marketAccessRestrictions"; import {
getHylyList,
getSearchAllYear,
getSurveyList,
getSearchAllCountry,
getAllProgressStatus,
} from "@/api/marketAccessRestrictions";
import AnalysisBox from "@/components/base/boxBackground/analysisBox.vue" import AnalysisBox from "@/components/base/boxBackground/analysisBox.vue"
import SurveyHistory from "@/views/marketAccessRestrictions/com/SurveyHistory.vue" import SurveyHistory from "@/views/marketAccessRestrictions/com/SurveyHistory.vue"
import TimeSortSelectBox from '@/components/base/TimeSortSelectBox/index.vue';
// 顶部过滤项 // 顶部过滤项
const searchText = ref(""); const searchText = ref("");
const filterStage = ref(""); const filterStage = ref("");
const filterParty = ref(""); const filterParty = ref("");
const filterReason = ref(""); const filterReason = ref("");
const isSort = ref('desc'); // 降序 const isSort = ref(true);
const handlePxChange = (event) => {
isSort.value = event == 1;
currentPage.value = 1;
handleFetchSurveyList();
};
// 获取阶段列表
const stateList = ref([]);
const onAllProgressStatus = async () => {
try {
const res = await getAllProgressStatus();
console.log("阶段列表", res)
if (res.code === 200) stateList.value = res.data;
} catch (error) {}
}
// 科技领域过滤 // 科技领域过滤
const surveyAreaList = ref([]); const surveyAreaList = ref([]);
const checkedAreaList = ref(['']); const checkedAreaList = ref(['']);
const handleGetSearchAllArea = async () => { const handleGetSearchAllArea = async () => {
try { try {
const res = await getSearchAllArea({ sortCode: "337" }); const res = await getHylyList();
if (res.code === 200) { if (res.code === 200) surveyAreaList.value = res.data;
surveyAreaList.value = res.data.map(item => ({ name: item.AREANAME, id: item.AREACODE }));
}
} catch (error) {} } catch (error) {}
surveyAreaList.value.unshift({ name: "全部领域", id: "" }); surveyAreaList.value.unshift({ name: "全部领域", id: "" });
}; };
...@@ -192,14 +201,20 @@ const handleFetchSurveyList = async () => { ...@@ -192,14 +201,20 @@ const handleFetchSurveyList = async () => {
caseStatus: filterStage.value || null, caseStatus: filterStage.value || null,
keywords: searchText.value || null, keywords: searchText.value || null,
sortField: "date", sortField: "date",
sortOrder: isSort.value sortOrder: isSort.value ? "desc" : "asc"
}; };
const res = await getSurveyList(params); const res = await getSurveyList(params);
if (res.code === 200) { if (res.code === 200) {
surveyInfoList.value = res.data?.content || []; surveyInfoList.value = res.data?.content || [];
totalDiscussNum.value = res.data?.totalElements || 0; totalDiscussNum.value = res.data?.totalElements || 0;
} else {
surveyInfoList.value = []
totalDiscussNum.value = 0
}
} catch (error) {
surveyInfoList.value = []
totalDiscussNum.value = 0
} }
} catch (error) {}
listLoading.value = false; listLoading.value = false;
}; };
...@@ -214,14 +229,17 @@ const handleSearch = () => { ...@@ -214,14 +229,17 @@ const handleSearch = () => {
}; };
// 监听过滤条件 // 监听过滤条件
watch([isSort, filterStage, filterParty, filterReason], () => { watch([filterStage, filterParty, filterReason], () => {
if (isInitializing.value) return; if (isInitializing.value) return;
currentPage.value = 1; currentPage.value = 1;
handleFetchSurveyList(); handleFetchSurveyList();
}); });
onMounted(async () => { onMounted(() => {
await Promise.all([handleGetSearchAllArea(), handleGetSearchAllYear(), handleGetSearchAllCountry()]); onAllProgressStatus()
handleGetSearchAllArea()
handleGetSearchAllYear()
handleGetSearchAllCountry()
isInitializing.value = false; isInitializing.value = false;
handleFetchSurveyList(); handleFetchSurveyList();
}); });
...@@ -315,6 +333,7 @@ onMounted(async () => { ...@@ -315,6 +333,7 @@ onMounted(async () => {
font-family: Source Han Sans CN; font-family: Source Han Sans CN;
font-size: 16px; font-size: 16px;
color: var(--text-primary-65-color); color: var(--text-primary-65-color);
font-weight: 400;
} }
} }
} }
......
...@@ -92,7 +92,7 @@ const handleClickBtn = item => { ...@@ -92,7 +92,7 @@ const handleClickBtn = item => {
const codeInfo = reactive({ const codeInfo = reactive({
sortCode: route.query.id, sortCode: route.query.id,
sortName: "调查主页", sortName: "调查",
sortImageUrl: "", sortImageUrl: "",
sortDescription: "", sortDescription: "",
}) })
...@@ -102,7 +102,7 @@ const onSurvyInfo = async () => { ...@@ -102,7 +102,7 @@ const onSurvyInfo = async () => {
if (res.code == 200) { if (res.code == 200) {
Object.assign(codeInfo, res.data) Object.assign(codeInfo, res.data)
} }
document.title = codeInfo.sortName; document.title = codeInfo.sortName+'概览';
} }
onMounted(() => { onMounted(() => {
...@@ -119,9 +119,8 @@ onMounted(() => { ...@@ -119,9 +119,8 @@ onMounted(() => {
.page-box { .page-box {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex;
flex-direction: column;
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
overflow-y: auto;
.page-top { .page-top {
width: 1600px; width: 1600px;
margin: 0 auto; margin: 0 auto;
...@@ -241,8 +240,6 @@ onMounted(() => { ...@@ -241,8 +240,6 @@ onMounted(() => {
border-top: 1px solid rgba(230, 231, 232, 1); border-top: 1px solid rgba(230, 231, 232, 1);
background-color: #f7f8f9; background-color: #f7f8f9;
width: 100%; width: 100%;
height: 20px;
flex: auto;
} }
} }
</style> </style>
\ No newline at end of file
...@@ -32,11 +32,8 @@ ...@@ -32,11 +32,8 @@
</template> </template>
<div class="box-main"> <div class="box-main">
<div class="box-head" ref="chart1"></div> <div class="box-head" ref="chart1"></div>
<TipTab text="美对华232调查案件的数量变化趋势,数据来源:美国商务部官网" style="margin-top: 16px;" /> <TipTab text="数据来源:美国商务部官网" style="margin-top: 16px;" />
<div class="ai-pane"> <AiReport ref="refAiReport1"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content1" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -49,11 +46,8 @@ ...@@ -49,11 +46,8 @@
</template> </template>
<div class="box-main"> <div class="box-main">
<div class="box-head" ref="chart2"></div> <div class="box-head" ref="chart2"></div>
<TipTab text="美对华232调查案件的领域分布情况,数据来源:美国商务部官网" style="margin-top: -16px;" /> <TipTab text="数据来源:美国商务部官网" />
<div class="ai-pane"> <AiReport ref="refAiReport2"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content2" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -68,11 +62,8 @@ ...@@ -68,11 +62,8 @@
</template> </template>
<div class="box-main"> <div class="box-main">
<div class="box-head" ref="chart3"></div> <div class="box-head" ref="chart3"></div>
<TipTab text="美对华232调查案件导致的关税变化分布,数据来源:美国商务部官网" style="margin-top: -16px;" /> <TipTab text="数据来源:美国商务部官网" />
<div class="ai-pane"> <AiReport ref="refAiReport3"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content3" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -85,11 +76,8 @@ ...@@ -85,11 +76,8 @@
</template> </template>
<div class="box-main"> <div class="box-main">
<div class="box-head" ref="chart4"></div> <div class="box-head" ref="chart4"></div>
<TipTab text="美232调查所涉及的国家分布情况,数据来源:美国商务部官网" style="margin-top: -16px;" /> <TipTab text="数据来源:美国商务部官网" />
<div class="ai-pane"> <AiReport ref="refAiReport4"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content4" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -108,21 +96,15 @@ import { ...@@ -108,21 +96,15 @@ import {
import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChart"; import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChart";
import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js"; import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js";
import AiButton from '@/components/base/Ai/AiButton/index.vue'; import AiReport from '@/views/marketAccessRestrictions/marketAccessHome/com/AiReport.vue';
import AiPane from '@/components/base/Ai/AiPane/index.vue'; import { getNearYearList } from "@/views/marketAccessRestrictions/utils/index.ts";
import { getNearYearList, getAIReport } from "@/views/marketAccessRestrictions/utils/index.ts";
const yearList = getNearYearList(); const yearList = getNearYearList();
// 获取AI智能报告 // 获取AI智能报告
const aiContent = reactive({ const refAiReport1 = ref(null)
content1: "正在生成...", const refAiReport2 = ref(null)
content2: "正在生成...", const refAiReport3 = ref(null)
content3: "正在生成...", const refAiReport4 = ref(null)
content4: "正在生成...",
})
const onAIReport = (data, key) => {
getAIReport(data).then(res => { aiContent[key] = res })
}
// 数量统计 // 数量统计
const totalCaseNum = ref(0) const totalCaseNum = ref(0)
...@@ -163,7 +145,7 @@ const onStatNum = async (event) => { ...@@ -163,7 +145,7 @@ const onStatNum = async (event) => {
chartData.title = []; chartData.title = [];
chartData.list = []; chartData.list = [];
} }
onAIReport({ type: "折线图", name: "数量变化趋势", data: chartData }, "content1") refAiReport1.value?.onDataInfo({ type: "折线图", name: "数量变化趋势", data: chartData })
nextTick(() => { createLineChart(chart1, chartData) }); nextTick(() => { createLineChart(chart1, chartData) });
box1Loading.value = false; box1Loading.value = false;
} }
...@@ -188,7 +170,7 @@ const handleGetStatArea = async () => { ...@@ -188,7 +170,7 @@ const handleGetStatArea = async () => {
} catch (error) { } catch (error) {
chartData = []; chartData = [];
} }
onAIReport({ type: "环形图", name: "领域分布情况", data: chartData }, "content2") refAiReport2.value?.onDataInfo({ type: "环形图", name: "领域分布情况", data: chartData })
nextTick(() => { createPieChart(chart2, chartData) }); nextTick(() => { createPieChart(chart2, chartData) });
box2Loading.value = false; box2Loading.value = false;
}; };
...@@ -218,7 +200,7 @@ const onSearchTariff = async () => { ...@@ -218,7 +200,7 @@ const onSearchTariff = async () => {
}catch (error) { }catch (error) {
chartData = []; chartData = [];
} }
onAIReport({ type: "环形图", name: "关税变化分布", data: chartData }, "content3") refAiReport3.value?.onDataInfo({ type: "环形图", name: "关税变化分布", data: chartData })
nextTick(() => { createPieChart(chart3, chartData) }); nextTick(() => { createPieChart(chart3, chartData) });
box3Loading.value = false; box3Loading.value = false;
} }
...@@ -243,7 +225,7 @@ const handleGetSearchCountry = async () => { ...@@ -243,7 +225,7 @@ const handleGetSearchCountry = async () => {
} catch (error) { } catch (error) {
chartData = [] chartData = []
} }
onAIReport({ type: "环形图", name: "国家分布情况", data: chartData }, "content4") refAiReport4.value?.onDataInfo({ type: "环形图", name: "国家分布情况", data: chartData })
nextTick(() => { createPieChart(chart4, chartData) }); nextTick(() => { createPieChart(chart4, chartData) });
box4Loading.value = false; box4Loading.value = false;
}; };
...@@ -350,28 +332,6 @@ onMounted(() => { ...@@ -350,28 +332,6 @@ onMounted(() => {
height: 20px; height: 20px;
flex: auto; flex: auto;
} }
.ai-pane {
position: absolute;
right: 0px;
bottom: 15px;
z-index: 2;
:deep(.ai-pane-wrapper) {
display: none;
}
:deep(.ai-button-wrapper) {
display: flex;
}
&:hover {
width: 100%;
bottom: 0px;
:deep(.ai-pane-wrapper) {
display: block;
}
:deep(.ai-button-wrapper) {
display: none;
}
}
}
} }
} }
} }
......
...@@ -8,11 +8,8 @@ ...@@ -8,11 +8,8 @@
</template> </template>
<div class="box-main"> <div class="box-main">
<div class="box-head" ref="box1Chart"></div> <div class="box-head" ref="box1Chart"></div>
<TipTab text="美对华301调查案件的数量变化趋势,数据来源:美国贸易代表办公室官网" style="margin-top: 16px" /> <TipTab text="数据来源:美国贸易代表办公室官网" style="margin-top: 16px" />
<div class="ai-pane"> <AiReport ref="refAiReport1"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content1" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -25,11 +22,8 @@ ...@@ -25,11 +22,8 @@
</template> </template>
<div class="box-main"> <div class="box-main">
<div class="box-head" id="box2Chart"></div> <div class="box-head" id="box2Chart"></div>
<TipTab text="美301调查所涉及的国家分布情况,数据来源:美国贸易代表办公室官网" style="margin-top: 16px" /> <TipTab text="数据来源:美国贸易代表办公室官网" style="margin-top: 16px" />
<div class="ai-pane"> <AiReport ref="refAiReport2"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content2" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -39,11 +33,8 @@ ...@@ -39,11 +33,8 @@
<AnalysisBox title="调查方向及结果分布"> <AnalysisBox title="调查方向及结果分布">
<div class="box-main"> <div class="box-main">
<div class="box-head" id="box3Chart"></div> <div class="box-head" id="box3Chart"></div>
<TipTab text="美301调查方向及结果分布情况,数据来源:美国贸易代表办公室官网" style="margin-top: 16px;" /> <TipTab text="数据来源:美国贸易代表办公室官网" style="margin-top: 16px;" />
<div class="ai-pane"> <AiReport ref="refAiReport3"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content3" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -56,11 +47,8 @@ ...@@ -56,11 +47,8 @@
</template> </template>
<div class="box-main"> <div class="box-main">
<div class="box-head" ref="box4Chart"></div> <div class="box-head" ref="box4Chart"></div>
<TipTab text="美对华301调查案件的领域分布情况,数据来源:美国贸易代表办公室官网" style="margin-top: -16px;" /> <TipTab text="数据来源:美国贸易代表办公室官网" />
<div class="ai-pane"> <AiReport ref="refAiReport4"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content4" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -71,7 +59,7 @@ ...@@ -71,7 +59,7 @@
<script setup> <script setup>
import { ref, onMounted, nextTick, reactive } from "vue"; import { ref, onMounted, nextTick, reactive } from "vue";
import setChart from "@/utils/setChart"; import setChart from "@/utils/setChart";
import getBarChart from "./utils/barChart"; import getBarChart from "@/views/marketAccessRestrictions/marketAccessHome/utils/barChart1.js";
import getSankeyChart from "./utils/sankey"; import getSankeyChart from "./utils/sankey";
import { import {
getSearchCountry, getSearchCountry,
...@@ -81,21 +69,15 @@ import { ...@@ -81,21 +69,15 @@ import {
} from "@/api/marketAccessRestrictions"; } from "@/api/marketAccessRestrictions";
import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChart"; import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChart";
import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js"; import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js";
import AiButton from '@/components/base/Ai/AiButton/index.vue'; import AiReport from '@/views/marketAccessRestrictions/marketAccessHome/com/AiReport.vue';
import AiPane from '@/components/base/Ai/AiPane/index.vue'; import { getNearYearList } from "@/views/marketAccessRestrictions/utils/index.ts";
import { getNearYearList, getAIReport } from "@/views/marketAccessRestrictions/utils/index.ts";
const yearList = getNearYearList(); const yearList = getNearYearList();
// 获取AI智能报告 // 获取AI智能报告
const aiContent = reactive({ const refAiReport1 = ref(null)
content1: "正在生成...", const refAiReport2 = ref(null)
content2: "正在生成...", const refAiReport3 = ref(null)
content3: "正在生成...", const refAiReport4 = ref(null)
content4: "正在生成...",
})
const onAIReport = (data, key) => {
getAIReport(data).then(res => { aiContent[key] = res })
}
const inProgressCount = ref(0); const inProgressCount = ref(0);
...@@ -122,7 +104,7 @@ const handleGetStatNum = async () => { ...@@ -122,7 +104,7 @@ const handleGetStatNum = async () => {
chartData.list = [] chartData.list = []
inProgressCount.value = 0 inProgressCount.value = 0
} }
onAIReport({ type: "折线图", name: "数量变化趋势", data: chartData }, "content1") refAiReport1.value?.onDataInfo({ type: "折线图", name: "数量变化趋势", data: chartData })
nextTick(() => { createLineChart(box1Chart, chartData) }) nextTick(() => { createLineChart(box1Chart, chartData) })
box1Loading.value = false; box1Loading.value = false;
}; };
...@@ -153,7 +135,7 @@ const handleGetSearchCountry = async () => { ...@@ -153,7 +135,7 @@ const handleGetSearchCountry = async () => {
chartData.title = [] chartData.title = []
chartData.data = [] chartData.data = []
} }
onAIReport({ type: "柱状图", name: "国家分布情况", data: chartData }, "content2") refAiReport2.value?.onDataInfo({ type: "柱状图", name: "国家分布情况", data: chartData })
nextTick(() => { nextTick(() => {
const box2Chart = getBarChart(chartData.title, chartData.data); const box2Chart = getBarChart(chartData.title, chartData.data);
setChart(box2Chart, "box2Chart"); setChart(box2Chart, "box2Chart");
...@@ -190,7 +172,7 @@ const handleGetSearchDirection = async () => { ...@@ -190,7 +172,7 @@ const handleGetSearchDirection = async () => {
chartData.nodes = []; chartData.nodes = [];
chartData.links = []; chartData.links = [];
} }
onAIReport({ type: "桑基图", name: "调查方向及结果分布", data: chartData }, "content3") refAiReport3.value?.onDataInfo({ type: "桑基图", name: "调查方向及结果分布", data: chartData })
nextTick(() => { nextTick(() => {
const box3Chart = getSankeyChart(chartData.nodes, chartData.links); const box3Chart = getSankeyChart(chartData.nodes, chartData.links);
setChart(box3Chart, "box3Chart"); setChart(box3Chart, "box3Chart");
...@@ -218,7 +200,7 @@ const handleGetStatArea = async () => { ...@@ -218,7 +200,7 @@ const handleGetStatArea = async () => {
} catch (error) { } catch (error) {
chartData = [] chartData = []
} }
onAIReport({ type: "环形图", name: "领域分布情况", data: chartData }, "content4") refAiReport4.value?.onDataInfo({ type: "环形图", name: "领域分布情况", data: chartData })
nextTick(() => { createPieChart(box4Chart, chartData) }) nextTick(() => { createPieChart(box4Chart, chartData) })
box4Loading.value = false; box4Loading.value = false;
}; };
...@@ -260,28 +242,6 @@ onMounted(() => { ...@@ -260,28 +242,6 @@ onMounted(() => {
height: 20px; height: 20px;
flex: auto; flex: auto;
} }
.ai-pane {
position: absolute;
right: 0px;
bottom: 15px;
z-index: 2;
:deep(.ai-pane-wrapper) {
display: none;
}
:deep(.ai-button-wrapper) {
display: flex;
}
&:hover {
width: 100%;
bottom: 0px;
:deep(.ai-pane-wrapper) {
display: block;
}
:deep(.ai-button-wrapper) {
display: none;
}
}
}
} }
} }
} }
......
...@@ -32,11 +32,8 @@ ...@@ -32,11 +32,8 @@
</template> </template>
<div class="box-main"> <div class="box-main">
<div class="box-head" ref="chart1"></div> <div class="box-head" ref="chart1"></div>
<TipTab text="美对华337调查案件的数量变化趋势,数据来源:美国国际贸易委员会官网" style="margin-top: 16px;" /> <TipTab text="数据来源:美国国际贸易委员会官网" style="margin-top: 16px;" />
<div class="ai-pane"> <AiReport ref="refAiReport1"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content1" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -49,11 +46,8 @@ ...@@ -49,11 +46,8 @@
</template> </template>
<div class="box-main"> <div class="box-main">
<div class="box-head" ref="chart2"></div> <div class="box-head" ref="chart2"></div>
<TipTab text="美对华337调查案件的领域分布情况,数据来源:美国国际贸易委员会官网" style="margin-top: -16px;" /> <TipTab text="数据来源:美国国际贸易委员会官网" />
<div class="ai-pane"> <AiReport ref="refAiReport2"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content2" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -84,11 +78,8 @@ ...@@ -84,11 +78,8 @@
</div> </div>
<div class="map-box-right" id="chartMap"></div> <div class="map-box-right" id="chartMap"></div>
</div> </div>
<TipTab text="美对华337调查案件的中国实体分布情况,数据来源:美国国际贸易委员会官网" /> <TipTab text="数据来源:美国国际贸易委员会官网" />
<div class="ai-pane"> <AiReport ref="refAiReport3"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content3" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -101,11 +92,8 @@ ...@@ -101,11 +92,8 @@
</template> </template>
<div class="box-main"> <div class="box-main">
<div class="box-head" ref="chart4"></div> <div class="box-head" ref="chart4"></div>
<TipTab text="美对华337调查案件的调查结果分布情况,数据来源:美国国际贸易委员会官网" style="margin-top: -16px;" /> <TipTab text="数据来源:美国国际贸易委员会官网" />
<div class="ai-pane"> <AiReport ref="refAiReport4"></AiReport>
<AiButton />
<AiPane :aiContent="aiContent.content4" />
</div>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -129,21 +117,15 @@ import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChar ...@@ -129,21 +117,15 @@ import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChar
import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js"; import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js";
import getBarChart from "./utils/barChart"; import getBarChart from "./utils/barChart";
import getMapChart from "./utils/mapChart"; import getMapChart from "./utils/mapChart";
import AiButton from '@/components/base/Ai/AiButton/index.vue'; import AiReport from '@/views/marketAccessRestrictions/marketAccessHome/com/AiReport.vue';
import AiPane from '@/components/base/Ai/AiPane/index.vue'; import { getNearYearList } from "@/views/marketAccessRestrictions/utils/index.ts";
import { getNearYearList, getAIReport } from "@/views/marketAccessRestrictions/utils/index.ts";
const yearList = getNearYearList(); const yearList = getNearYearList();
// 获取AI智能报告 // 获取AI智能报告
const aiContent = reactive({ const refAiReport1 = ref(null)
content1: "正在生成...", const refAiReport2 = ref(null)
content2: "正在生成...", const refAiReport3 = ref(null)
content3: "正在生成...", const refAiReport4 = ref(null)
content4: "正在生成...",
})
const onAIReport = (data, key) => {
getAIReport(data).then(res => { aiContent[key] = res })
}
const provinceCoords = { const provinceCoords = {
"北京": [116.46, 39.92], "北京": [116.46, 39.92],
...@@ -227,7 +209,7 @@ const handleGetStatNum = async (type) => { ...@@ -227,7 +209,7 @@ const handleGetStatNum = async (type) => {
chartData.title = []; chartData.title = [];
chartData.list = []; chartData.list = [];
} }
onAIReport({ type: "折线图", name: "数量变化趋势", data: chartData }, "content1") refAiReport1.value?.onDataInfo({ type: "折线图", name: "数量变化趋势", data: chartData })
nextTick(() => { createLineChart(chart1, chartData) }); nextTick(() => { createLineChart(chart1, chartData) });
box1Loading.value = false; box1Loading.value = false;
}; };
...@@ -252,7 +234,7 @@ const handleGetStatArea = async () => { ...@@ -252,7 +234,7 @@ const handleGetStatArea = async () => {
} catch (error) { } catch (error) {
chartData = []; chartData = [];
} }
onAIReport({ type: "环形图", name: "领域分布情况", data: chartData }, "content2") refAiReport2.value?.onDataInfo({ type: "环形图", name: "领域分布情况", data: chartData })
nextTick(() => { createPieChart(chart2, chartData) }); nextTick(() => { createPieChart(chart2, chartData) });
box2Loading.value = false; box2Loading.value = false;
}; };
...@@ -282,7 +264,7 @@ const handleGetStatcnOrgCount = async () => { ...@@ -282,7 +264,7 @@ const handleGetStatcnOrgCount = async () => {
chartData.name = []; chartData.name = [];
chartData.value = []; chartData.value = [];
} }
onAIReport({ type: "柱状图", name: "中国实体分布情况", data: chartData }, "content3") refAiReport3.value?.onDataInfo({ type: "柱状图", name: "中国实体分布情况", data: chartData })
nextTick(() => { nextTick(() => {
let chart3 = getBarChart(chartData.name, chartData.value); let chart3 = getBarChart(chartData.name, chartData.value);
setChart(chart3, "chart3"); setChart(chart3, "chart3");
...@@ -305,7 +287,7 @@ const handleGetStatcnOrgCount = async () => { ...@@ -305,7 +287,7 @@ const handleGetStatcnOrgCount = async () => {
} catch (error) { } catch (error) {
mapData.value = []; mapData.value = [];
} }
onAIReport({ type: "地图", name: "中国实体分布情况", data: mapData.value }, "content3") refAiReport3.value?.onDataInfo({ type: "地图", name: "中国实体分布情况", data: mapData.value })
nextTick(() => { nextTick(() => {
let chartMap = getMapChart(mapData.value); let chartMap = getMapChart(mapData.value);
setChart(chartMap, "chartMap"); setChart(chartMap, "chartMap");
...@@ -334,7 +316,7 @@ const handleGetSearchResult = async () => { ...@@ -334,7 +316,7 @@ const handleGetSearchResult = async () => {
} catch (error) { } catch (error) {
chartData = []; chartData = [];
} }
onAIReport({ type: "环形图", name: "调查结果分布", data: chartData }, "content4") refAiReport4.value?.onDataInfo({ type: "环形图", name: "调查结果分布", data: chartData })
nextTick(() => { createPieChart(chart4, chartData) }); nextTick(() => { createPieChart(chart4, chartData) });
box4Loading.value = false; box4Loading.value = false;
}; };
...@@ -441,28 +423,6 @@ onMounted(() => { ...@@ -441,28 +423,6 @@ onMounted(() => {
height: 20px; height: 20px;
flex: auto; flex: auto;
} }
.ai-pane {
position: absolute;
right: 0px;
bottom: 15px;
z-index: 2;
:deep(.ai-pane-wrapper) {
display: none;
}
:deep(.ai-button-wrapper) {
display: flex;
}
&:hover {
width: 100%;
bottom: 0px;
:deep(.ai-pane-wrapper) {
display: block;
}
:deep(.ai-button-wrapper) {
display: none;
}
}
}
} }
} }
} }
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
<img class="translate-icon" src="@/views/thinkTank/ReportDetail/images/image-translate.png" alt="" <img class="translate-icon" src="@/views/thinkTank/ReportDetail/images/image-translate.png" alt=""
style="width: 16px; height: 16px; max-width: 16px; max-height: 16px; display: block; object-fit: contain;" /> style="width: 16px; height: 16px; max-width: 16px; max-height: 16px; display: block; object-fit: contain;" />
</div> </div>
<div class="translate-text">{{ "显示文" }}</div> <div class="translate-text">{{ "显示文" }}</div>
</div> </div>
<div class="btn" @click="handleDownload"> <div class="btn" @click="handleDownload">
<div class="icon"> <div class="icon">
...@@ -53,8 +53,7 @@ ...@@ -53,8 +53,7 @@
<pdf ref="leftPdfRef" :pdfUrl="reportUrlEnWithPage" class="pdf-pane-inner" /> <pdf ref="leftPdfRef" :pdfUrl="reportUrlEnWithPage" class="pdf-pane-inner" />
</div> </div>
<div class="pdf-pane-wrap" :class="{ 'is-full': !valueSwitch }" v-if="reportUrlWithPage"> <div class="pdf-pane-wrap" :class="{ 'is-full': !valueSwitch }" v-if="reportUrlWithPage">
<pdf :key="`right-pdf-${valueSwitch ? 'split' : 'full'}`" ref="rightPdfRef" :pdfUrl="reportUrlWithPage" <pdf :key="`right-pdf-${valueSwitch ? 'split' : 'full'}`" ref="rightPdfRef" :pdfUrl="reportUrlWithPage" class="pdf-pane-inner" />
class="pdf-pane-inner" />
</div> </div>
</div> </div>
</div> </div>
...@@ -371,15 +370,15 @@ onMounted(() => { ...@@ -371,15 +370,15 @@ onMounted(() => {
margin: 0 auto; margin: 0 auto;
background: rgb(255, 255, 255); background: rgb(255, 255, 255);
width: 1600px; width: 1600px;
height: 20px; height: 948px;
flex: auto; margin-bottom: 86px;
border: 1px, solid, rgb(234, 236, 238); border: 1px, solid, rgb(234, 236, 238);
box-shadow: 0 0 20px 0 rgba(25, 69, 130, 0.1); box-shadow: 0 0 20px 0 rgba(25, 69, 130, 0.1);
display: flex;
flex-direction: column;
.main-header { .main-header {
height: 64px; height: 64px;
/* box-sizing: border-box; */
border-bottom: 1px solid rgb(234, 236, 238); border-bottom: 1px solid rgb(234, 236, 238);
background: rgb(255, 255, 255); background: rgb(255, 255, 255);
margin: 0 70px; margin: 0 70px;
...@@ -463,6 +462,8 @@ onMounted(() => { ...@@ -463,6 +462,8 @@ onMounted(() => {
.btn { .btn {
width: 88px; width: 88px;
height: 32px; height: 32px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1); border: 1px solid rgba(230, 231, 232, 1);
border-radius: 6px; border-radius: 6px;
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
...@@ -516,6 +517,7 @@ onMounted(() => { ...@@ -516,6 +517,7 @@ onMounted(() => {
.search-input { .search-input {
width: 160px; width: 160px;
height: 24px; height: 24px;
box-sizing: border-box;
border: 1px solid rgba(231, 243, 255, 1); border: 1px solid rgba(231, 243, 255, 1);
background: rgba(246, 250, 255, 1); background: rgba(246, 250, 255, 1);
border-radius: 4px; border-radius: 4px;
...@@ -543,6 +545,7 @@ onMounted(() => { ...@@ -543,6 +545,7 @@ onMounted(() => {
.search-nav-btn { .search-nav-btn {
width: 68px; width: 68px;
height: 24px; height: 24px;
box-sizing: border-box;
border: 1px solid rgba(231, 243, 255, 1); border: 1px solid rgba(231, 243, 255, 1);
background: rgba(246, 250, 255, 1); background: rgba(246, 250, 255, 1);
border-radius: 4px; border-radius: 4px;
...@@ -565,13 +568,11 @@ onMounted(() => { ...@@ -565,13 +568,11 @@ onMounted(() => {
} }
.report-box { .report-box {
height: 20px;
flex: auto;
margin-left: 70px; margin-left: 70px;
width: 1456px; width: 1456px;
height: 881px;
display: flex; display: flex;
overflow-y: auto; overflow-y: auto;
/* 右侧统一滚动条,控制两侧原文+译文一起滚动 */
overflow-x: hidden; overflow-x: hidden;
} }
......
...@@ -155,7 +155,7 @@ onMounted(() => { ...@@ -155,7 +155,7 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.wrapper { .wrapper {
width: 1600px; width: 1600px;
margin: 20px auto; margin: 16px auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="deep-dig-container"> <div class="deep-dig-container">
<div class="left-section"> <div class="left-section">
<!-- Module 1: 被诉企业列表 --> <!-- Module 1: 被诉企业列表 -->
<div class="box company-list-box"> <div class="box company-list-box" v-loading="box1loading">
<div class="box-header"> <div class="box-header">
<div class="header-left-bar"></div> <div class="header-left-bar"></div>
<div class="title">被诉企业列表</div> <div class="title">被诉企业列表</div>
...@@ -14,27 +14,23 @@ ...@@ -14,27 +14,23 @@
</div> </div>
<div class="box-content"> <div class="box-content">
<div class="filter-row"> <div class="filter-row">
<el-select v-model="selectedArea" placeholder="全部领域" class="area-select" clearable @change="onEnterpriseList()"> <el-select v-model="areaInfo.id" :empty-values="[null, undefined]" class="area-select" @change="onEnterpriseList()">
<el-option label="全部领域" value="" /> <el-option label="全部领域" value="" />
<el-option v-for="item in areaOptions" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in areaInfo.list" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
<el-input v-model="searchText" placeholder="搜索实体" class="search-input" :suffix-icon="Search" clearable @keyup.enter="onEnterpriseList()" /> <el-input v-model="searchText" placeholder="搜索实体" class="search-input" :prefix-icon="Search" clearable @clear="onEnterpriseList()" @keyup.enter="onEnterpriseList()" />
</div> </div>
<div class="enterprise-list" v-loading="listLoading"> <div class="enterprise-list">
<div class="list-label">企业名称</div> <div class="list-label">企业名称</div>
<div <div v-for="item in enterpriseList" :key="item.ORGID" class="enterprise-item"
v-for="(item, index) in enterpriseList" :class="{ active: activeOrg === item.ORGID }" @click="handleEnterpriseClick(item)"
:key="item.ORGID || index"
class="enterprise-item"
:class="{ active: activeIndex === index }"
@click="handleEnterpriseClick(item, index)"
> >
<div class="icon"> <div class="icon">
<img src="@/assets/icons/default-icon1.png" alt="" /> <img src="@/assets/icons/default-icon1.png" alt="" />
</div> </div>
<div class="name">{{ item.ORGNAME }}</div> <div class="name">{{ item.ORGNAME }}</div>
</div> </div>
<el-empty v-if="!enterpriseList.length && !listLoading" description="暂无数据" /> <el-empty v-if="!enterpriseList.length" style="height: 100%;" description="暂无数据" />
</div> </div>
</div> </div>
</div> </div>
...@@ -42,7 +38,7 @@ ...@@ -42,7 +38,7 @@
<div class="right-section"> <div class="right-section">
<!-- Module 2: 进出口数据 --> <!-- Module 2: 进出口数据 -->
<div class="box chart-box"> <div class="box chart-box" v-loading="box2loading">
<div class="box-header"> <div class="box-header">
<div class="header-left-bar"></div> <div class="header-left-bar"></div>
<div class="title">进出口数据</div> <div class="title">进出口数据</div>
...@@ -57,24 +53,15 @@ ...@@ -57,24 +53,15 @@
</div> </div>
</div> </div>
</div> </div>
<div class="box-content chart-content"> <div class="chart-wrapper" v-show="chartLabels.length">
<div class="chart-wrapper" v-loading="exportLoading">
<div ref="exportChartRef" class="echarts-container"></div> <div ref="exportChartRef" class="echarts-container"></div>
</div> </div>
<div class="footer-msg"> <el-empty v-if="!chartLabels.length" style="height:20px; flex:auto;" description="暂无数据" />
<div class="msg-left"> <AiReport ref="refAiReport2"></AiReport>
<img src="@/assets/icons/box-footer-left-icon.png" alt="" />
</div>
<div class="msg-center">列入实体清单后企业营收初期下降,后基本趋于稳定。</div>
<div class="msg-right">
<img src="@/assets/icons/box-footer-right-icon.png" alt="" />
</div>
</div>
</div>
</div> </div>
<!-- Module 3: 企业经营情况 --> <!-- Module 3: 企业经营情况 -->
<div class="box chart-box"> <div class="box chart-box" v-loading="box3loading">
<div class="box-header"> <div class="box-header">
<div class="header-left-bar"></div> <div class="header-left-bar"></div>
<div class="title">企业经营情况</div> <div class="title">企业经营情况</div>
...@@ -98,64 +85,52 @@ ...@@ -98,64 +85,52 @@
</div> </div>
</div> </div>
</div> </div>
<div class="box-content chart-content"> <div class="chart-wrapper" v-show="businessLabels.length">
<div class="chart-wrapper" v-loading="businessLoading">
<div ref="businessChartRef" class="echarts-container"></div> <div ref="businessChartRef" class="echarts-container"></div>
</div> </div>
<div class="footer-msg"> <el-empty v-if="!businessLabels.length" style="height:20px; flex:auto;" description="暂无数据" />
<div class="msg-left"> <AiReport ref="refAiReport3"></AiReport>
<img src="@/assets/icons/box-footer-left-icon.png" alt="" />
</div>
<div class="msg-center">列入实体清单后企业研发资金投入逐渐提高。</div>
<div class="msg-right">
<img src="@/assets/icons/box-footer-right-icon.png" alt="" />
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted, nextTick } from 'vue'; import { ref, onMounted, reactive, nextTick } from 'vue';
import { Search } from '@element-plus/icons-vue'; import { Search } from '@element-plus/icons-vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import { getSuedOrg, getOrgImportAndExport, getRevenue, getNetProfit } from '@/api/marketAccessRestrictions'; import { getSuedOrg, getOrgImportAndExport, getRevenue, getNetProfit } from '@/api/marketAccessRestrictions';
import { getDecreehylyList } from "@/api/decree/influence";
import AiReport from '@/views/marketAccessRestrictions/marketAccessHome/com/AiReport.vue';
const route = useRoute(); const route = useRoute();
const selectedArea = ref('');
const searchText = ref(''); const searchText = ref('');
const activeIndex = ref(0); const activeOrg = ref('');
const businessActiveBtn = ref('营收'); const businessActiveBtn = ref('营收');
const listLoading = ref(false); const box1loading = ref(false);
const exportLoading = ref(false); const box2loading = ref(false);
const businessLoading = ref(false); const box3loading = ref(false);
const areaOptions = [ const refAiReport2 = ref(null)
{ label: '人工智能', value: '1' }, const refAiReport3 = ref(null)
{ label: '生物科技', value: '2' },
{ label: '新一代通信技术', value: '3' }, // 行业领域
{ label: '量子科技', value: '4' }, const areaInfo = reactive({
{ label: '新能源', value: '5' }, list: [],
{ label: '集成电路', value: '6' }, id: "",
{ label: '海洋', value: '7' }, })
{ label: '先进制造', value: '8' }, const handleGetHylyList = async () => {
{ label: '新材料', value: '9' }, try {
{ label: '航空航天', value: '10' }, const res = await getDecreehylyList();
{ label: '太空', value: '13' }, console.log("行业领域:", res);
{ label: '深海', value: '11' }, if (res.code === 200) {
{ label: '极地', value: '12' }, areaInfo.list = res.data || [];
{ label: '核', value: '14' }, }
{ label: '政治', value: '20' }, } catch (error) {}
{ label: '外交', value: '21' }, };
{ label: '经济', value: '22' },
{ label: '军事', value: '23' },
{ label: '科技', value: '24' },
{ label: '安全', value: '25' },
{ label: '其他', value: '99' },
];
const enterpriseList = ref([]); const enterpriseList = ref([]);
...@@ -173,44 +148,46 @@ const businessData = ref([]); ...@@ -173,44 +148,46 @@ const businessData = ref([]);
// 获取企业列表 // 获取企业列表
const onEnterpriseList = async () => { const onEnterpriseList = async () => {
listLoading.value = true; box1loading.value = true;
try { try {
const params = { const res = await getSuedOrg({
searchId: route.query.searchId, searchId: route.query.searchId,
orgName: searchText.value orgName: searchText.value,
area: areaInfo.id || null,
});
if (res.code==200 && res.data) {
enterpriseList.value = res.data || [];
} else {
enterpriseList.value = [];
} }
if (selectedArea.value) { } catch (error) {
params.area = selectedArea.value; enterpriseList.value = [];
} }
const res = await getSuedOrg(params);
if (res.code === 200) {
enterpriseList.value = res.data || [];
// 默认选中第一个并加载其进出口数据 // 默认选中第一个并加载其进出口数据
if (enterpriseList.value.length > 0) { if (enterpriseList.value.length > 0) {
handleEnterpriseClick(enterpriseList.value[0], 0); handleEnterpriseClick(enterpriseList.value[0]);
} } else {
} chartLabels.value = [];
} catch (error) { chartData.value = [];
console.error('获取被诉企业列表失败:', error); businessLabels.value = [];
} finally { businessData.value = [];
listLoading.value = false; refAiReport2.value?.onDataInfo({ type: "折线图", name: "进出口数据", data: {label: [], data: []} })
refAiReport3.value?.onDataInfo({ type: "折线图", name: "企业经营情况", data: {label: [], data: []} })
} }
box1loading.value = false;
}; };
// 获取进出口数据 // 进出口数据
const fetchExportData = async (orgId) => { const fetchExportData = async (orgId) => {
exportLoading.value = true; box2loading.value = true;
chartLabels.value = [];
chartData.value = [];
try { try {
const res = await getOrgImportAndExport({ id: orgId }); const res = await getOrgImportAndExport({ id: orgId });
if (res.code === 200 && res.data && res.data.length > 0) { chartLabels.value = [];
// 对数据按年份排序 chartData.value = [];
if (res.code === 200 && res.data?.length) {
const sortedData = res.data.sort((a, b) => a.year - b.year); const sortedData = res.data.sort((a, b) => a.year - b.year);
const labels = []; const labels = [];
const values = []; const values = [];
sortedData.forEach(item => { sortedData.forEach(item => {
['q1', 'q2', 'q3', 'q4'].forEach(q => { ['q1', 'q2', 'q3', 'q4'].forEach(q => {
if (item[q] !== undefined && item[q] !== null) { if (item[q] !== undefined && item[q] !== null) {
...@@ -219,40 +196,33 @@ const fetchExportData = async (orgId) => { ...@@ -219,40 +196,33 @@ const fetchExportData = async (orgId) => {
} }
}); });
}); });
// 更新图表 // 更新图表
chartLabels.value = labels; chartLabels.value = labels;
chartData.value = values; chartData.value = values;
} }
} catch (error) {}
updateExportChart(); updateExportChart();
} catch (error) { refAiReport2.value?.onDataInfo({ type: "折线图", name: "进出口数据", data: {label: chartLabels.value, data: chartData.value} })
console.error('获取进出口数据失败:', error); box2loading.value = false;
updateExportChart();
} finally {
exportLoading.value = false;
}
}; };
// 获取经营情况数据 // 企业经营情况
const fetchBusinessData = async (orgId) => { const fetchBusinessData = async (orgId) => {
businessLoading.value = true; box3loading.value = true;
businessLabels.value = [];
businessData.value = [];
try { try {
const api = businessActiveBtn.value === '营收' ? getRevenue : getNetProfit; const api = businessActiveBtn.value === '营收' ? getRevenue : getNetProfit;
const res = await api({ id: orgId }); const res = await api({ id: orgId });
if (res.code === 200 && res.data && res.data.length > 0) { businessLabels.value = [];
businessData.value = [];
if (res.code === 200 && res.data?.length) {
const sortedData = res.data.sort((a, b) => a.year - b.year); const sortedData = res.data.sort((a, b) => a.year - b.year);
businessLabels.value = sortedData.map(item => item.year + '年'); businessLabels.value = sortedData.map(item => item.year + '年');
businessData.value = sortedData.map(item => item.count); businessData.value = sortedData.map(item => item.count);
} }
} catch (error) {}
updateBusinessChart(); updateBusinessChart();
} catch (error) { refAiReport3.value?.onDataInfo({ type: "折线图", name: "企业经营情况", data: {label: businessLabels.value, data: businessData.value} })
console.error(`获取企业${businessActiveBtn.value}数据失败:`, error); box3loading.value = false;
updateBusinessChart();
} finally {
businessLoading.value = false;
}
}; };
const updateExportChart = () => { const updateExportChart = () => {
...@@ -260,6 +230,7 @@ const updateExportChart = () => { ...@@ -260,6 +230,7 @@ const updateExportChart = () => {
const lastValue = chartData.value[chartData.value.length - 1]; const lastValue = chartData.value[chartData.value.length - 1];
const lastLabel = chartLabels.value[chartLabels.value.length - 1]; const lastLabel = chartLabels.value[chartLabels.value.length - 1];
exportChart.setOption(getOption(chartData.value, lastValue, chartLabels.value, lastLabel)); exportChart.setOption(getOption(chartData.value, lastValue, chartLabels.value, lastLabel));
nextTick(() => exportChart.resize() )
} }
}; };
...@@ -268,11 +239,12 @@ const updateBusinessChart = () => { ...@@ -268,11 +239,12 @@ const updateBusinessChart = () => {
const lastValue = businessData.value[businessData.value.length - 1]; const lastValue = businessData.value[businessData.value.length - 1];
const lastLabel = businessLabels.value[businessLabels.value.length - 1]; const lastLabel = businessLabels.value[businessLabels.value.length - 1];
businessChart.setOption(getOption(businessData.value, lastValue, businessLabels.value, lastLabel)); businessChart.setOption(getOption(businessData.value, lastValue, businessLabels.value, lastLabel));
nextTick(() => businessChart.resize() )
} }
}; };
const handleEnterpriseClick = (item, index) => { const handleEnterpriseClick = (item) => {
activeIndex.value = index; activeOrg.value = item.ORGID;
if (item.ORGID) { if (item.ORGID) {
fetchExportData(item.ORGID); fetchExportData(item.ORGID);
fetchBusinessData(item.ORGID); fetchBusinessData(item.ORGID);
...@@ -410,29 +382,25 @@ const initCharts = () => { ...@@ -410,29 +382,25 @@ const initCharts = () => {
const handleBusinessToggle = (type) => { const handleBusinessToggle = (type) => {
businessActiveBtn.value = type; businessActiveBtn.value = type;
const currentOrg = enterpriseList.value[activeIndex.value]; const currentOrg = enterpriseList.value.find(item => item.ORGID === activeOrg.value);
if (currentOrg && currentOrg.ORGID) { if (currentOrg) fetchBusinessData(currentOrg.ORGID);
fetchBusinessData(currentOrg.ORGID);
}
}; };
onMounted(() => { onMounted(() => {
handleGetHylyList();
onEnterpriseList(); onEnterpriseList();
nextTick(() => {
initCharts(); initCharts();
window.addEventListener('resize', () => {
exportChart && exportChart.resize();
businessChart && businessChart.resize();
});
});
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.deep-dig-container { .deep-dig-container {
display: flex;
width: 1600px; width: 1600px;
margin: 20px auto; height: calc(100vh - 146px);
margin: 0 auto;
padding: 16px 0;
overflow: hidden;
display: flex;
gap: 16px; gap: 16px;
.box { .box {
...@@ -533,16 +501,20 @@ onMounted(() => { ...@@ -533,16 +501,20 @@ onMounted(() => {
.box-content { .box-content {
padding: 16px; padding: 16px;
flex: 1; height: 20px;
flex: auto;
display: flex;
flex-direction: column;
} }
} }
.left-section { .left-section {
width: 480px; width: 480px;
flex-shrink: 0; height: 100%;
.company-list-box { .company-list-box {
height: 100%; height: 100%;
display: flex;
.filter-row { .filter-row {
display: flex; display: flex;
...@@ -563,6 +535,8 @@ onMounted(() => { ...@@ -563,6 +535,8 @@ onMounted(() => {
} }
.enterprise-list { .enterprise-list {
height: 20px;
flex: auto;
.list-label { .list-label {
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
...@@ -620,56 +594,19 @@ onMounted(() => { ...@@ -620,56 +594,19 @@ onMounted(() => {
gap: 16px; gap: 16px;
.chart-box { .chart-box {
height: 400px; height: 20px;
flex: auto;
.chart-content { position: relative;
display: flex;
flex-direction: column;
padding-bottom: 12px;
.chart-wrapper { .chart-wrapper {
flex: 1; padding-bottom: 12px;
height: 20px;
flex: auto;
position: relative; position: relative;
.echarts-container { .echarts-container {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
.footer-msg {
margin-top: 12px;
background: #f6fbff;
border: 1px solid #e7f3ff;
border-radius: 4px;
padding: 8px 12px;
display: flex;
align-items: center;
.msg-left {
width: 18px;
height: 18px;
margin-right: 8px;
img {
width: 100%;
}
}
.msg-center {
flex: 1;
font-size: 14px;
color: #176bf0;
}
.msg-right {
width: 16px;
height: 16px;
cursor: pointer;
img {
width: 100%;
}
}
}
}
} }
} }
} }
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
</div> </div>
<div style="width:20px; flex:auto;"></div> <div style="width:20px; flex:auto;"></div>
<div class="head-button"> <div class="head-button" @click="handleAnalysisClick()">
<div class="button-icon"> <div class="button-icon">
<img src="./assets/images/btn-icon2.png" alt="" /> <img src="./assets/images/btn-icon2.png" alt="" />
</div> </div>
...@@ -42,13 +42,15 @@ ...@@ -42,13 +42,15 @@
<script setup> <script setup>
import { ref, onMounted, reactive } from "vue"; import { ref, onMounted, reactive } from "vue";
import { ElMessage } from "element-plus";
import { getSurvyInfo, getSearchBlurb } from "@/api/marketAccessRestrictions/index.js"
import router from "@/router"; import router from "@/router";
import NavIcon1 from "./assets/images/nav-icon1.png"; import NavIcon1 from "./assets/images/nav-icon1.png";
import NavIcon1Active from "./assets/images/nav-icon1-active.png"; import NavIcon1Active from "./assets/images/nav-icon1-active.png";
import NavIcon3 from "./assets/images/nav-icon2.png"; import NavIcon3 from "./assets/images/nav-icon2.png";
import NavIcon3Active from "./assets/images/nav-icon2-active.png"; import NavIcon3Active from "./assets/images/nav-icon2-active.png";
import Img337 from "./assets/images/337.png"; import Img337 from "./assets/images/337.png";
import { getSurvyInfo, getSearchBlurb } from "@/api/marketAccessRestrictions/index.js"
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
const route = useRoute(); const route = useRoute();
...@@ -62,6 +64,18 @@ const handleClickBtn = index => { ...@@ -62,6 +64,18 @@ const handleClickBtn = index => {
}); });
}; };
// 分析报告
const handleAnalysisClick = () => {
ElMessage.warning("当前功能正在开发中,敬请期待!");
// router.push({
// path: "/writtingAsstaint",
// query: {
// topic: "市场准入限制",
// fileId: route.query.id
// }
// });
};
const codeInfo = reactive({ const codeInfo = reactive({
sortCode: route.query.id, sortCode: route.query.id,
sortName: "", sortName: "",
...@@ -104,8 +118,7 @@ onMounted(() => { ...@@ -104,8 +118,7 @@ onMounted(() => {
.page-box { .page-box {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; overflow-y: auto;
flex-direction: column;
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
.page-top { .page-top {
width: 1600px; width: 1600px;
...@@ -279,8 +292,6 @@ onMounted(() => { ...@@ -279,8 +292,6 @@ onMounted(() => {
border-top: 1px solid rgba(230, 231, 232, 1); border-top: 1px solid rgba(230, 231, 232, 1);
background-color: #f7f8f9; background-color: #f7f8f9;
width: 100%; width: 100%;
height: 20px;
flex: auto;
} }
} }
</style> </style>
\ No newline at end of file
...@@ -204,7 +204,7 @@ onMounted(() => { ...@@ -204,7 +204,7 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.wrapper { .wrapper {
width: 1600px; width: 1600px;
margin: 20px auto; margin: 16px auto;
display: flex; display: flex;
gap: 16px; gap: 16px;
.left { .left {
......
...@@ -215,7 +215,7 @@ onMounted(() => { ...@@ -215,7 +215,7 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.wrapper { .wrapper {
width: 1600px; width: 1600px;
margin: 20px auto; margin: 16px auto;
display: flex; display: flex;
.page-left { .page-left {
width: 520px; width: 520px;
......
...@@ -45,7 +45,9 @@ ...@@ -45,7 +45,9 @@
<div class="data-icon">{{ baseInfo.orgAbb }}</div> <div class="data-icon">{{ baseInfo.orgAbb }}</div>
<div class="data-right"> <div class="data-right">
<div class="data-name">{{ baseInfo.orgNameEn }}</div> <div class="data-name">{{ baseInfo.orgNameEn }}</div>
<div class="data-desc">{{ baseInfo.ORGNAME }}</div> <div class="data-desc">
<span class="text-click-hover" @click="handleToInstitution(baseInfo)">{{ baseInfo.ORGNAME }}</span>
</div>
</div> </div>
</div> </div>
<div class="data-text">{{ baseInfo.ORGBLURB || '-' }}</div> <div class="data-text">{{ baseInfo.ORGBLURB || '-' }}</div>
...@@ -54,17 +56,19 @@ ...@@ -54,17 +56,19 @@
</AnalysisBox> </AnalysisBox>
<AnalysisBox title="被告信息" :showAllBtn="false" height="auto"> <AnalysisBox title="被告信息" :showAllBtn="false" height="auto">
<div class="box3-main"> <div class="box3-main">
<div class="data-item" v-for="(item, index) in caseList" :key="index"> <div class="data-item">
<div class="data-head">{{ item.title }}</div> <div class="info-list" v-if="caseList.length">
<div class="info-list"> <div class="info-item" v-for="(item, index) in caseList" :key="index">
<div class="info-item" v-for="(val, idx) in item.companyList" :key="idx">
<div class="icon"> <div class="icon">
<img :src="val.logo" alt="" v-if="val.logo"> <img :src="item.logo" alt="" v-if="item.logo">
<div class="default-logo" v-else>{{ val.name ? val.name.substring(0, 1) : '' }}</div> <div class="default-logo" v-else>{{ item.COMNAM?.substring(0, 1) || '' }}</div>
</div>
<div class="text" >
<span class="text-click-hover" @click="handleToInstitution(item)">{{ item.COMNAM }}</span>
</div> </div>
<div class="text">{{ val.name }}</div>
</div> </div>
</div> </div>
<el-empty v-else description="暂无数据" :image-size="100" />
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
...@@ -77,12 +81,10 @@ import { ref, onMounted } from "vue"; ...@@ -77,12 +81,10 @@ import { ref, onMounted } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { getSearchBlurb , getRelatedEvents} from "@/api/marketAccessRestrictions"; import { getSearchBlurb , getRelatedEvents} from "@/api/marketAccessRestrictions";
import AiTips from "@/views/marketAccessRestrictions/com/AiTips.vue"; import router from "@/router";
import RelatedEvent from "@/views/marketAccessRestrictions/com/RelatedEvent.vue"; import RelatedEvent from "@/views/marketAccessRestrictions/com/RelatedEvent.vue";
import SurveyAffiche from "@/views/marketAccessRestrictions/com/SurveyAffiche.vue"; import SurveyAffiche from "@/views/marketAccessRestrictions/com/SurveyAffiche.vue";
const tips = `Pantech是韩国的一家通信设备公司,曾经是手机制造商,但现在可能已转型为专利持有实体。这类公司常被称为"非执业实体"(NPE)或"专利断言实体"(PAE),通过专利授权和诉讼获取收益。这些企业曾经是行业龙头,但因科技和市场形态巨变,加上自身改革步伐缓慢,经营状况每况愈下。卖掉实体业务部门后,留下来的是高达几万件的专利。`
const route = useRoute(); const route = useRoute();
const loading = ref(false); const loading = ref(false);
const baseInfo = ref({}); const baseInfo = ref({});
...@@ -96,7 +98,7 @@ const handleGetSearchBlurb = async () => { ...@@ -96,7 +98,7 @@ const handleGetSearchBlurb = async () => {
searchId: route.query.searchId, searchId: route.query.searchId,
sortCode: "337" sortCode: "337"
}); });
console.log("调查概况", res) console.log("调查概况/原告信息/被告信息", res)
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const data = res.data; const data = res.data;
baseInfo.value = data; baseInfo.value = data;
...@@ -107,29 +109,33 @@ const handleGetSearchBlurb = async () => { ...@@ -107,29 +109,33 @@ const handleGetSearchBlurb = async () => {
} }
// 被告信息分组 // 被告信息分组
if (data.defendantOrg) { // if (data.defendantOrg) {
const groups = {}; // const groups = {};
data.defendantOrg.forEach(item => { // data.defendantOrg.forEach(item => {
const companyName = item.COMPANYNAM || "其他相关企业"; // const companyName = item.COMPANYNAM || "其他相关企业";
if (!groups[companyName]) { // if (!groups[companyName]) {
groups[companyName] = { // groups[companyName] = {
title: companyName + (companyName !== "其他" ? "及相关企业" : ""), // title: companyName + (companyName !== "其他" ? "及相关企业" : ""),
companyList: [] // companyList: []
}; // };
} // }
groups[companyName].companyList.push({ // groups[companyName].companyList.push(item);
name: item.COMNAM, // });
logo: "" // API 不提供 logo // }
}); caseList.value = data.defendantOrg || [];
}); }
caseList.value = Object.values(groups); } catch (error) {}
}
}
} catch (error) {
console.log("获取调查概况失败", error);
}
loading.value = false; loading.value = false;
}; };
// 跳转行政机构主页
const handleToInstitution = item => {
window.sessionStorage.setItem("curTabName", item.ORGNAME|| item.COMNAM);
const curRoute = router.resolve({
path: "/institution",
query: { id: item.ORGID|| item.OMID }
});
window.open(curRoute.href, "_blank");
};
// 相关事件 // 相关事件
const eventList = ref([]) const eventList = ref([])
...@@ -153,7 +159,7 @@ onMounted(() => { ...@@ -153,7 +159,7 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.wrapper { .wrapper {
width: 1600px; width: 1600px;
margin: 20px auto; margin: 16px auto;
display: flex; display: flex;
.box-header { .box-header {
height: 56px; height: 56px;
......
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { MUTICHARTCOLORS } from '@/common/constant' import { MUTICHARTCOLORS } from '@/common/constant'
import { hexToRgba } from '@/views/marketAccessRestrictions/utils/index.ts'
// 十六进制颜色转 rgba 的工具函数
function hexToRgba(hex, alpha) {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
const getSerie = (data, index) => { const getSerie = (data, index) => {
return { return {
...@@ -38,8 +31,8 @@ const createLineChart = (chartDom, data, option={}) => { ...@@ -38,8 +31,8 @@ const createLineChart = (chartDom, data, option={}) => {
if (existingChart) existingChart.dispose(); if (existingChart) existingChart.dispose();
// 获取容器宽度/高度 // 获取容器宽度/高度
const containerWidth = chartDom.value.clientWidth; // const containerWidth = chartDom.value.clientWidth;
const containerHeight = chartDom.value.clientHeight; // const containerHeight = chartDom.value.clientHeight;
const myChart = echarts.init(chartDom.value); const myChart = echarts.init(chartDom.value);
myChart.setOption({ myChart.setOption({
......
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { MUTICHARTCOLORS } from '@/common/constant' import { MUTICHARTCOLORS } from '@/common/constant'
const truncateLabel = (value, maxLen = 6) => {
if (value === null || value === undefined) return ''
const str = String(value)
const chars = Array.from(str)
if (chars.length <= maxLen) return str
return `${chars.slice(0, maxLen).join('')}...`
}
const formatLabel = (node, type) => {
if (type==1) {
const name = truncateLabel(node.name, 6)
return `{name|${name}}\n{time|${ node.percent||0}%}`
}
return `{name|${node.name}} {time| ${node.value}${ node.percent||0}%}\n`
}
const createPieChart = (chartDom, data=[], option={}) => { const createPieChart = (chartDom, data=[], option={}) => {
if (!chartDom.value) return; if (!chartDom.value) return;
...@@ -46,21 +30,21 @@ const createPieChart = (chartDom, data=[], option={}) => { ...@@ -46,21 +30,21 @@ const createPieChart = (chartDom, data=[], option={}) => {
}, },
label: { label: {
alignTo: 'edge', alignTo: 'edge',
formatter: (node) => formatLabel(node, option.labelType), formatter: (node) => `{name|${node.name}}\n{time|${node.value}${ node.percent||0}%}`,
minMargin: 5, minMargin: 5,
edgeDistance: 10, edgeDistance: 10,
lineHeight: 22, lineHeight: 26,
rich: { rich: {
name: { name: {
color: 'rgba(59, 65, 75, 1)', color: 'rgba(59, 65, 75, 1)',
fontFamily: 'Microsoft YaHei', fontFamily: 'Source Han Sans CN',
fontSize: 16, fontSize: 16,
fontWeight: 'bold', fontWeight: 'bold',
padding: [10, 0, 10, 0] padding: [10, 0, 10, 0]
}, },
time: { time: {
color: 'rgba(95, 101, 108, 1)', color: 'rgba(95, 101, 108, 1)',
fontFamily: 'Microsoft YaHei', fontFamily: 'Source Han Sans CN',
fontSize: 16, fontSize: 16,
padding: [10, 0, 10, 0] padding: [10, 0, 10, 0]
} }
......
...@@ -26,7 +26,6 @@ export const onNumToChinese = (num:number) => { ...@@ -26,7 +26,6 @@ export const onNumToChinese = (num:number) => {
} }
} }
/** /**
* 获取 n 天前的日期,格式:YYYY-MM-DD * 获取 n 天前的日期,格式:YYYY-MM-DD
* @param num 往前推的天数 * @param num 往前推的天数
...@@ -57,55 +56,10 @@ export const getNearYearList = (num=6) => { ...@@ -57,55 +56,10 @@ export const getNearYearList = (num=6) => {
return yearOptions; return yearOptions;
}; };
/** // 十六进制颜色转 rgba 的工具函数
* AI智能总结 export const hexToRgba = (hex:any, alpha:number) => {
* @param data 需要分析的数据 const r = parseInt(hex.slice(1, 3), 16);
*/ const g = parseInt(hex.slice(3, 5), 16);
export const getAIReport = async (data:any) => { const b = parseInt(hex.slice(5, 7), 16);
let word = "" return `rgba(${r}, ${g}, ${b}, ${alpha})`;
// 👇 新增:超时 + 终止请求(只加这一段)
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10*1000); // 10秒超时
try {
const res = await fetch('/aiAnalysis/chart_interpretation', {
method: 'POST',
headers: {
"X-API-Key": "aircasKEY19491001",
'Content-Type': 'application/json',
},
body: JSON.stringify({text: JSON.stringify(data)}),
signal: controller.signal // 👇 新增:绑定中断信号
});
clearTimeout(timeout); // 👇 新增:请求成功清除定时器
if (!res.ok) throw new Error(`HTTP 错误 ${res.status}`);
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
let summarize = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.startsWith('data: ')) {
const content = line.substring(6);
const textMatch = content.match(/"解读":\s*"([^"]*)"/);
if (textMatch && textMatch[1]) summarize = textMatch[1];
}
}
}
word = summarize
} catch (err) {
word = "系统异常,生成失败";
}
return word
} }
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论