提交 2289e9a2 authored 作者: 闫鹏's avatar 闫鹏

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

Yp dev 查看合并请求 !276
流水线 #199 已失败 于阶段
in 4 分 22 秒
...@@ -14,9 +14,7 @@ build_pre: ...@@ -14,9 +14,7 @@ build_pre:
stage: build stage: build
image: node:20-bullseye image: node:20-bullseye
tags: tags:
- docker - risk-monitor-frontend
- frontend
- linux
only: only:
- pre - pre
script: script:
...@@ -39,17 +37,39 @@ deploy_pre: ...@@ -39,17 +37,39 @@ deploy_pre:
stage: deploy stage: deploy
image: alpine:3.20 image: alpine:3.20
tags: tags:
- docker - risk-monitor-frontend
- frontend
- linux
only: only:
- pre - pre
dependencies: dependencies:
- build_pre - build_pre
script: script:
- apk add --no-cache rsync - apk add --no-cache rsync curl jq
- test -d dist || (echo "dist not found" && exit 1) # 只允许“最新一次 pre pipeline”部署到 nginx(加二次确认,避免短时间多次推送导致重复 rsync)
- test -d /nas/kjb_service/zm/pre-project/html || (echo "deploy target path not found" && exit 1) - >
LATEST_PIPELINE_ID="$(
curl --silent --show-error --fail
--header "JOB-TOKEN: $CI_JOB_TOKEN"
"$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/pipelines?ref=pre&order_by=id&sort=desc&per_page=1"
| jq -r '.[0].id'
)"
- >
if [ -z "$LATEST_PIPELINE_ID" ] || [ "$LATEST_PIPELINE_ID" != "$CI_PIPELINE_ID" ]; then
echo "skip deploy: not latest pipeline (latest=$LATEST_PIPELINE_ID current=$CI_PIPELINE_ID)";
exit 0;
fi
- sleep 20
- >
LATEST_PIPELINE_ID="$(
curl --silent --show-error --fail
--header "JOB-TOKEN: $CI_JOB_TOKEN"
"$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/pipelines?ref=pre&order_by=id&sort=desc&per_page=1"
| jq -r '.[0].id'
)"
- >
if [ -z "$LATEST_PIPELINE_ID" ] || [ "$LATEST_PIPELINE_ID" != "$CI_PIPELINE_ID" ]; then
echo "skip deploy: not latest pipeline after debounce (latest=$LATEST_PIPELINE_ID current=$CI_PIPELINE_ID)";
exit 0;
fi
- rsync -avz --delete dist/ /nas/kjb_service/zm/pre-project/html/ - rsync -avz --delete dist/ /nas/kjb_service/zm/pre-project/html/
# 非 protected 分支:push 时先做 build 校验(避免合并 pre 时出现 build 报错) # 非 protected 分支:push 时先做 build 校验(避免合并 pre 时出现 build 报错)
...@@ -57,9 +77,7 @@ build_check: ...@@ -57,9 +77,7 @@ build_check:
stage: build stage: build
image: node:20-bullseye image: node:20-bullseye
tags: tags:
- docker - risk-monitor-frontend
- frontend
- linux
# 只在 push 时做构建校验,且排除 protected 分支与目标分支 pre # 只在 push 时做构建校验,且排除 protected 分支与目标分支 pre
only: only:
- pushes - pushes
......
差异被折叠。
...@@ -3,66 +3,64 @@ import request from "@/api/request.js"; ...@@ -3,66 +3,64 @@ import request from "@/api/request.js";
// 中美博弈概览V2:最新风险动态统计 // 中美博弈概览V2:最新风险动态统计
export function getLatestRiskUpdates(params) { export function getLatestRiskUpdates(params) {
return request({ return request({
method: 'GET', method: "GET",
url: `/api/rivalryIndexV2/LatestRiskUpdates`, url: `/api/rivalryIndexV2/LatestRiskUpdates`,
params: params params: params
}) });
} }
// 中美博弈概览V2:最新风险信号 // 中美博弈概览V2:最新风险信号
export function getLatestRisks() { export function getLatestRisks() {
return request({ return request({
method: 'GET', method: "GET",
url: `/api/rivalryIndexV2/LatestRisks`, url: `/api/rivalryIndexV2/LatestRisks`
});
})
} }
// 中美博弈概览V2:美对华制裁措施数量趋势 // 中美博弈概览V2:美对华制裁措施数量趋势
export function geDomainContainmentTrend(params) { export function geDomainContainmentTrend(params) {
return request({ return request({
method: 'GET', method: "GET",
url: `/api/rivalryIndexV2/DomainContainmentTrend`, url: `/api/rivalryIndexV2/DomainContainmentTrend`,
params: params params: params
}) });
} }
// 中美博弈概况:获取榜单字典 // 中美博弈概况:获取榜单字典
export function getChartDict() { export function getChartDict() {
return request({ return request({
method: 'GET', method: "GET",
url: `/api/union/summary/chartDict`, url: `/api/union/summary/chartDict`
}) });
}
// 中美博弈概况:获取年份
export function getYear(id) {
return request({
method: "GET",
url: `/api/union/summary/chartYear/${id}`
});
} }
// 中美博弈概况:中美科技实力对比 // 中美博弈概况:中美科技实力对比
export function getCompare(id) { export function getCompare(id, year) {
return request({ return request({
method: 'GET', method: "GET",
url: `/api/union/summary/compare/${id}`, url: `/api/union/summary/compare/${id}/${year}`
}) });
} }
// 中美博弈分析 // 中美博弈分析
export function getTechnologyGameAnalysis() { export function getTechnologyGameAnalysis() {
return request({ return request({
method: 'GET', method: "GET",
url: `/api/rivalryIndexV2/TechnologyGameAnalysis`, url: `/api/rivalryIndexV2/TechnologyGameAnalysis`
});
})
} }
//中美博弈概览V7:美国政府部门对华制裁最新动态 //中美博弈概览V7:美国政府部门对华制裁最新动态
export function getGovernmentSanctionsDynamics() { export function getGovernmentSanctionsDynamics() {
return request({ return request({
method: 'GET', method: "GET",
url: `/api/rivalryIndex/governmentSanctionsDynamics`, url: `/api/rivalryIndex/governmentSanctionsDynamics`
});
})
} }
...@@ -14,10 +14,20 @@ ...@@ -14,10 +14,20 @@
size="default" size="default"
style="margin-left: 15px; width: 240px; height: 32px" style="margin-left: 15px; width: 240px; height: 32px"
v-model="origin" v-model="origin"
@change="handleGetCompare()" @change="handleOriginChange()"
> >
<el-option :value="value.id" :label="value.name" v-for="(value, index) in originList" :key="index" /> <el-option :value="value.id" :label="value.name" v-for="(value, index) in originList" :key="index" />
</el-select> </el-select>
<el-select
class="select-item"
size="default"
style="margin-left: 15px; width: 200px; height: 32px"
v-model="year"
@change="handleGetCompare()"
>
<el-option :value="value" :label="value" v-for="(value, index) in yearList" :key="index" />
</el-select>
</div> </div>
</div> </div>
<div style="display: flex; height: 650px; width: 100%; padding-top: 12px"> <div style="display: flex; height: 650px; width: 100%; padding-top: 12px">
...@@ -237,7 +247,7 @@ import Echarts from "@/components/Chart/index.vue"; ...@@ -237,7 +247,7 @@ import Echarts from "@/components/Chart/index.vue";
import mockData from "./mock.json"; import mockData from "./mock.json";
import radarChart from "./radarChart3.js"; import radarChart from "./radarChart3.js";
import { getCompare, getChartDict, getTechnologyGameAnalysis } from "@/api/zmOverview/risk/index.js"; import { getCompare, getChartDict, getYear, getTechnologyGameAnalysis } from "@/api/zmOverview/risk/index.js";
import icon1 from "./icon/btn-icon-0.png"; import icon1 from "./icon/btn-icon-0.png";
import icon2 from "./icon/btn-icon-1.png"; import icon2 from "./icon/btn-icon-1.png";
import icon3 from "./icon/btn-icon-2.png"; import icon3 from "./icon/btn-icon-2.png";
...@@ -351,10 +361,32 @@ const handleGetChartDict = async () => { ...@@ -351,10 +361,32 @@ const handleGetChartDict = async () => {
console.error("获取数据来源error", error); console.error("获取数据来源error", error);
} }
}; };
const yearList = ref([]);
const year = ref("");
//年份
const handleGetYear = async () => {
try {
const res = await getYear(origin.value);
console.log("年份", res);
if (res.code === 200 && res.data) {
yearList.value = res.data;
year.value = res.data[0];
}
} catch (error) {
console.error("获取年份error", error);
}
};
// 数据来源改变时,年份列表也会改变
const handleOriginChange = async () => {
await handleGetYear();
};
//中美科技实力对比 //中美科技实力对比
const handleGetCompare = async () => { const handleGetCompare = async () => {
try { try {
const res = await getCompare(origin.value); const res = await getCompare(origin.value, year.value);
console.log("中美科技实力对比", res); console.log("中美科技实力对比", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
tableData.value = res.data[0].children; tableData.value = res.data[0].children;
...@@ -392,6 +424,7 @@ const handlegetTechnologyGameAnalysis = async () => { ...@@ -392,6 +424,7 @@ const handlegetTechnologyGameAnalysis = async () => {
}; };
onMounted(async () => { onMounted(async () => {
await handleGetChartDict(); await handleGetChartDict();
await handleGetYear();
await handleGetCompare(); await handleGetCompare();
await handlegetTechnologyGameAnalysis(); await handlegetTechnologyGameAnalysis();
// const dom = document.getElementById("char"); // const dom = document.getElementById("char");
...@@ -463,7 +496,13 @@ const handleIndicatorChange = indicator => { ...@@ -463,7 +496,13 @@ const handleIndicatorChange = indicator => {
const years = chinaData.map(item => item.year.toString()); const years = chinaData.map(item => item.year.toString());
const chinaValues = chinaData.map(item => item.value); const chinaValues = chinaData.map(item => item.value);
const usaValues = usaData.map(item => item.value); const usaValues = usaData.map(item => item.value);
console.log("中国", chinaValues);
console.log("美国", usaValues);
// chinaValues和usaValues的最小值和最大值
const min = Math.min(...chinaValues, ...usaValues);
const max = Math.max(...chinaValues, ...usaValues);
lineOption.value.yAxis.min = Math.floor(min - 1);
lineOption.value.yAxis.max = Math.ceil(max + 1);
lineOption.value.xAxis.data = years; lineOption.value.xAxis.data = years;
lineOption.value.series = [ lineOption.value.series = [
{ {
...@@ -566,9 +605,11 @@ const lineOption = ref({ ...@@ -566,9 +605,11 @@ const lineOption = ref({
}, },
yAxis: { yAxis: {
type: "value", type: "value",
// name: "指数", min: 77,
nameLocation: "top", name: "指数",
nameGap: 35, nameLocation: "end",
nameGap: 1,
padding: [0, -50, 0, 0],
nameTextStyle: { nameTextStyle: {
color: "#666", color: "#666",
fontSize: 13, fontSize: 13,
...@@ -589,7 +630,7 @@ const lineOption = ref({ ...@@ -589,7 +630,7 @@ const lineOption = ref({
} }
}, },
axisLabel: { axisLabel: {
color: "#ccc", color: "#666",
fontSize: 14, fontSize: 14,
fontWeight: 400, fontWeight: 400,
formatter: value => { formatter: value => {
......
...@@ -384,7 +384,7 @@ ...@@ -384,7 +384,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="radarChart.loading ? '解读生成中...' : radarChart.interpretation" /> <AiPane :aiContent="radarChart.interpretation" />
</div> </div>
</template> </template>
</custom-container> </custom-container>
...@@ -409,7 +409,7 @@ ...@@ -409,7 +409,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="trendChart.loading ? '解读生成中...' : trendChart.interpretation" /> <AiPane :aiContent="trendChart.interpretation" />
</div> </div>
</template> </template>
</custom-container> </custom-container>
...@@ -830,7 +830,6 @@ const handleToRiskSignalDetail = item => { ...@@ -830,7 +830,6 @@ const handleToRiskSignalDetail = item => {
}); });
// 打开新页面 // 打开新页面
window.open(routeData.href, "_blank"); window.open(routeData.href, "_blank");
}; };
const sanctionList = ref([]); const sanctionList = ref([]);
...@@ -1042,7 +1041,6 @@ const handleToSocialDetail = item => { ...@@ -1042,7 +1041,6 @@ const handleToSocialDetail = item => {
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
// 获取趋势图数据 // 获取趋势图数据
const fetchTrendData = async () => { const fetchTrendData = async () => {
...@@ -1180,7 +1178,6 @@ const handleToEntityListNoId = item => { ...@@ -1180,7 +1178,6 @@ const handleToEntityListNoId = item => {
}); });
// 打开一个新页面 // 打开一个新页面
window.open(routeData.href, "_blank"); window.open(routeData.href, "_blank");
} else if (item.nameZh == "商业管制清单") { } else if (item.nameZh == "商业管制清单") {
const routeData = router.resolve({ const routeData = router.resolve({
path: "/exportControl/commercialControlList", path: "/exportControl/commercialControlList",
...@@ -1195,8 +1192,8 @@ const handleToEntityListNoId = item => { ...@@ -1195,8 +1192,8 @@ const handleToEntityListNoId = item => {
} }
}; };
const billList = ref([]); // const billList = ref([]);
const curBillListIndex = ref(0); // const curBillListIndex = ref(0);
const searchExportControlText = ref(""); const searchExportControlText = ref("");
const infoListColor = ref(["rgba(206, 79, 81, 1)", "rgba(114, 46, 209, 1)", "rgba(132, 136, 142, 1)", "rgba(132, 136, 142, 1)"]); const infoListColor = ref(["rgba(206, 79, 81, 1)", "rgba(114, 46, 209, 1)", "rgba(132, 136, 142, 1)", "rgba(132, 136, 142, 1)"]);
...@@ -1666,12 +1663,11 @@ const handlePerClick = item => { ...@@ -1666,12 +1663,11 @@ const handlePerClick = item => {
const route = router.resolve({ const route = router.resolve({
path: "/characterPage", path: "/characterPage",
query: { query: {
type: item.type || [1, 2, 3][Math.floor(Math.random() * 3)], type: item.personType || [1, 2, 3][Math.floor(Math.random() * 3)],
personId: item.personId personId: item.personId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
// 处理点击社交媒体消息的方法 // 处理点击社交媒体消息的方法
// const handleInfoClick = item => { // const handleInfoClick = item => {
...@@ -1751,17 +1747,16 @@ const chart1Data = ref({ ...@@ -1751,17 +1747,16 @@ const chart1Data = ref({
}); });
const handleSanc = item => { const handleSanc = item => {
console.log(item); console.log("activeResourceTabItem.value.id", activeResourceTabItem.value.id);
window.sessionStorage.setItem("curTabName", `${item.postDate}${item.title}》`); window.sessionStorage.setItem("curTabName", `${item.postDate}${item.title}》`);
const route = router.resolve({ const route = router.resolve({
path: "/exportControl/singleSanction", path: "/exportControl/singleSanction",
query: { query: {
id: item.id, id: item.id,
sanTypeId: activeResourceTabItem.value.id sanTypeId: activeResourceTabItem.value.id.join(",")
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
// 查看更多风险信号 // 查看更多风险信号
...@@ -2368,8 +2363,7 @@ const handleMediaClick = item => { ...@@ -2368,8 +2363,7 @@ const handleMediaClick = item => {
overflow-y: auto; overflow-y: auto;
.home-top-bg { .home-top-bg {
background: background: url("./assets/images/background.png"),
url("./assets/images/background.png"),
linear-gradient(180deg, rgba(229, 241, 254, 1) 0%, rgba(246, 251, 255, 0) 30%); linear-gradient(180deg, rgba(229, 241, 254, 1) 0%, rgba(246, 251, 255, 0) 30%);
background-size: 100% 100%; background-size: 100% 100%;
position: absolute; position: absolute;
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
<div class="list-content" v-for="(ele, j) in element.cclChildren" :key="j"> <div class="list-content" v-for="(ele, j) in element.cclChildren" :key="j">
<div class="content-title" @click="ele.isExpand = !ele.isExpand"> <div class="content-title" @click="ele.isExpand = !ele.isExpand">
<div class="code-zone"> <div class="code-zone">
<!-- <div class="dot" v-if="ele.isDot"></div> --> <div class="dot" v-if="ele.changeFlag"></div>
<span class="code">{{ ele.cclCode }}</span> <span class="code">{{ ele.cclCode }}</span>
</div> </div>
<span class="name">{{ ele.cclTitleZh }}</span> <span class="name">{{ ele.cclTitleZh }}</span>
...@@ -121,9 +121,9 @@ const getTechFields = async () => { ...@@ -121,9 +121,9 @@ const getTechFields = async () => {
const res = await getAreaType(); const res = await getAreaType();
if (res && res.code === 200) { if (res && res.code === 200) {
console.log("-----getTechFields", res.data); console.log("-----getTechFields", res.data);
techFields.value = res.data; techFields.value = [{ id: "all", name: "全部领域", checked: true }].concat(res.data);
// 默认选中第一个 // 默认选中第一个
techFields.value[0].checked = true; // techFields.value[0].checked = true;
} }
} catch (error) { } catch (error) {
console.error("获取科技领域字典失败:", error); console.error("获取科技领域字典失败:", error);
...@@ -136,9 +136,9 @@ const getControlReasonList = async () => { ...@@ -136,9 +136,9 @@ const getControlReasonList = async () => {
const res = await getControlReason(); const res = await getControlReason();
if (res && res.code === 200) { if (res && res.code === 200) {
console.log("-----getControlReasonList", res.data); console.log("-----getControlReasonList", res.data);
controlReason.value = res.data; controlReason.value = [{ id: "all", name: "全部", checked: true }].concat(res.data);
// 默认选中第一个 // 默认选中第一个
controlReason.value[0].checked = true; // controlReason.value[0].checked = true;
} }
} catch (error) { } catch (error) {
console.error("获取管控原因字典失败:", error); console.error("获取管控原因字典失败:", error);
...@@ -151,8 +151,19 @@ const viewNew = ref(true); ...@@ -151,8 +151,19 @@ const viewNew = ref(true);
// 获取ccl清单列表 // 获取ccl清单列表
const getCclList = async () => { const getCclList = async () => {
let techDomains = techFields.value.filter(item => item.checked).map(item => +item.id); let techDomains = [];
let controls = controlReason.value.filter(item => item.checked).map(item => +item.id); const allTech = techFields.value.find(item => item.id === "all"); // ✅ 修正点1
if (!allTech || !allTech.checked) {
techDomains = techFields.value.filter(item => item.checked && item.id !== "all").map(item => item.id); // 注意:这里 map 的是 value,假设后端需要的是 value 字段
}
let controls = [];
const allReason = controlReason.value.find(item => item.id === "all"); // ✅ 修正点2
if (!allReason || !allReason.checked) {
controls = controlReason.value.filter(item => item.checked && item.id !== "all").map(item => item.id);
}
// let techDomains = techFields.value.filter(item => item.checked).map(item => +item.id);
// let controls = controlReason.value.filter(item => item.checked).map(item => +item.id);
const params = { const params = {
categoryCode: currentCCLType.value, categoryCode: currentCCLType.value,
techDomainIds: techDomains, techDomainIds: techDomains,
...@@ -161,7 +172,7 @@ const getCclList = async () => { ...@@ -161,7 +172,7 @@ const getCclList = async () => {
isLatest: viewNew.value, isLatest: viewNew.value,
recordId: currentCCLVersion.value || "" recordId: currentCCLVersion.value || ""
}; };
console.log(JSON.stringify(params)); console.log("cclList参数:", params);
try { try {
// const res = await getCclQuery(null); // const res = await getCclQuery(null);
const res = await getCclQuery(params); const res = await getCclQuery(params);
...@@ -272,8 +283,34 @@ const getCCLVersionListApi = async () => { ...@@ -272,8 +283,34 @@ const getCCLVersionListApi = async () => {
}; };
// 筛选逻辑处理 // 筛选逻辑处理
const handleFilterChange = (item, list, type) => { const handleFilterChange = (item, listRef, type) => {
console.log(item, list, type); const list = listRef;
const allItem = list.find(i => i.id === "all"); // ✅ 关键修正
if (!allItem) return;
if (item.id === "all") {
if (item.checked) {
list.forEach(i => {
if (i.id !== "all") i.checked = false;
});
} else {
const hasOtherChecked = list.some(i => i.id !== "all" && i.checked);
if (!hasOtherChecked && list.length > 1) {
const firstNonAll = list.find(i => i.id !== "all");
if (firstNonAll) firstNonAll.checked = true;
}
}
} else {
if (item.checked) {
allItem.checked = false;
} else {
const hasAnyChecked = list.some(i => i.id !== "all" && i.checked);
if (!hasAnyChecked) {
allItem.checked = true;
}
}
}
getCclList(); getCclList();
}; };
...@@ -373,6 +410,9 @@ onMounted(async () => { ...@@ -373,6 +410,9 @@ onMounted(async () => {
:deep(.el-input__wrapper) { :deep(.el-input__wrapper) {
padding: 0 11px; padding: 0 11px;
border: 1px solid rgba(0, 0, 0, 0.1);
background-color: #fff;
border-radius: 3px;
} }
:deep(.el-input__inner) { :deep(.el-input__inner) {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
</div> </div>
<div class="department">{{ headerTitle.department }}</div> <div class="department">{{ headerTitle.department }}</div>
</div> </div>
<div class="btn"><img :src="icon01" alt />切换</div> <!-- <div class="btn"><img :src="icon01" alt />切换</div> -->
</div> </div>
<div class="header-nav"> <div class="header-nav">
<div <div
......
...@@ -125,7 +125,7 @@ ...@@ -125,7 +125,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="sanctionCountChart.loading ? '解读生成中...' : sanctionCountChart.interpretation" /> <AiPane :aiContent="sanctionCountChart.interpretation" />
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -174,7 +174,7 @@ ...@@ -174,7 +174,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="rankChart.loading ? '解读生成中...' : rankChart.interpretation" /> <AiPane :aiContent="rankChart.interpretation" />
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -206,7 +206,7 @@ ...@@ -206,7 +206,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="domainChart.loading ? '解读生成中...' : domainChart.interpretation" /> <AiPane :aiContent="domainChart.interpretation" />
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -238,7 +238,7 @@ ...@@ -238,7 +238,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="typeChart.loading ? '解读生成中...' : typeChart.interpretation" /> <AiPane :aiContent="typeChart.interpretation" />
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
......
...@@ -532,6 +532,7 @@ watch(customDateRange, () => { ...@@ -532,6 +532,7 @@ watch(customDateRange, () => {
padding: 0 11px; padding: 0 11px;
border: 1px solid rgba(170, 173, 177, 1); border: 1px solid rgba(170, 173, 177, 1);
background-color: #fff; background-color: #fff;
border-radius: 3px;
} }
:deep(.el-input__inner) { :deep(.el-input__inner) {
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="domainChart.loading ? '解读生成中...' : domainChart.interpretation" /> <AiPane :aiContent="domainChart.interpretation" />
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -113,7 +113,7 @@ ...@@ -113,7 +113,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="typeChart.loading ? '解读生成中...' : typeChart.interpretation" /> <AiPane :aiContent="typeChart.interpretation" />
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -154,11 +154,7 @@ ...@@ -154,11 +154,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane <AiPane :aiContent="countryDistributionChart.interpretation" />
:aiContent="
countryDistributionChart.loading ? '解读生成中...' : countryDistributionChart.interpretation
"
/>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
...@@ -202,11 +198,7 @@ ...@@ -202,11 +198,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane <AiPane :aiContent="regionDistributionChart.interpretation" />
:aiContent="
regionDistributionChart.loading ? '解读生成中...' : regionDistributionChart.interpretation
"
/>
</div> </div>
</AnalysisBox> </AnalysisBox>
</div> </div>
......
...@@ -146,7 +146,7 @@ ...@@ -146,7 +146,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="revenueChart.loading ? '解读生成中...' : revenueChart.interpretation" /> <AiPane :aiContent="revenueChart.interpretation" />
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
...@@ -188,7 +188,7 @@ ...@@ -188,7 +188,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="marketChart.loading ? '解读生成中...' : marketChart.interpretation" /> <AiPane :aiContent="marketChart.interpretation" />
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
...@@ -249,7 +249,7 @@ ...@@ -249,7 +249,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="rdChart.loading ? '解读生成中...' : rdChart.interpretation" /> <AiPane :aiContent="rdChart.interpretation" />
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
...@@ -310,7 +310,7 @@ ...@@ -310,7 +310,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane :aiContent="shareChart.loading ? '解读生成中...' : shareChart.interpretation" /> <AiPane :aiContent="shareChart.interpretation" />
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
......
...@@ -60,13 +60,7 @@ ...@@ -60,13 +60,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane <AiPane :aiContent="rdInstrumentDependencyChart.interpretation" />
:aiContent="
rdInstrumentDependencyChart.loading
? '解读生成中...'
: rdInstrumentDependencyChart.interpretation
"
/>
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
...@@ -102,13 +96,7 @@ ...@@ -102,13 +96,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane <AiPane :aiContent="rdInstrumentImportCountryChart.interpretation" />
:aiContent="
rdInstrumentImportCountryChart.loading
? '解读生成中...'
: rdInstrumentImportCountryChart.interpretation
"
/>
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
...@@ -177,13 +165,7 @@ ...@@ -177,13 +165,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane <AiPane :aiContent="internationalCooperationChart.interpretation" />
:aiContent="
internationalCooperationChart.loading
? '解读生成中...'
: internationalCooperationChart.interpretation
"
/>
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
...@@ -252,11 +234,7 @@ ...@@ -252,11 +234,7 @@
</div> </div>
<div class="ai-pane"> <div class="ai-pane">
<AiButton /> <AiButton />
<AiPane <AiPane :aiContent="internationalPaperChart.interpretation" />
:aiContent="
internationalPaperChart.loading ? '解读生成中...' : internationalPaperChart.interpretation
"
/>
</div> </div>
</div> </div>
</AnalysisBox> </AnalysisBox>
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<div class="info-row"> <div class="info-row">
<div class="label">发布人:</div> <div class="label">发布人:</div>
<div class="value link"> <div class="value link">
<img :src="defaultTitle" alt="" class="icon avatar" /> <img :src="formattedData.avartar || defaultTitle" alt="" class="icon avatar" />
<span @click="handleClick">{{ formattedData.postPersonName }} ></span> <span @click="handleClick">{{ formattedData.postPersonName }} ></span>
</div> </div>
</div> </div>
...@@ -46,13 +46,16 @@ ...@@ -46,13 +46,16 @@
<div class="content-title">制裁实体分布:</div> <div class="content-title">制裁实体分布:</div>
<div class="distribution-list"> <div class="distribution-list">
<div class="list-item" v-for="(item, index) in entityDistribution" :key="index"> <div class="list-item" v-for="(item, index) in entityDistribution" :key="index">
<img :src="flag" alt="" class="flag" /> <img :src="item.imageUrl || flag" alt="" class="flag" />
<div class="country-name">{{ item.name }}</div> <div class="country-name">{{ item.name }}</div>
<div class="progress-bar-container"> <div class="progress-bar-container">
<div class="progress-bar" :style="{ <div
class="progress-bar"
:style="{
width: item.width, width: item.width,
background: item.gradient background: item.gradient
}"></div> }"
></div>
</div> </div>
<div class="count" :class="{ highlight: index === 0 }">{{ item.count }}</div> <div class="count" :class="{ highlight: index === 0 }">{{ item.count }}</div>
</div> </div>
...@@ -95,13 +98,25 @@ ...@@ -95,13 +98,25 @@
</div> </div>
<div class="filter-right"> <div class="filter-right">
<el-checkbox v-model="onlyChina" label="只看中国实体" /> <el-checkbox v-model="onlyChina" label="只看中国实体" />
<el-select v-model="filterField" placeholder="全部领域" style="width: 150px; margin: 0 12px 0 16px"> <el-select
v-model="filterField"
placeholder="全部领域"
style="width: 150px; margin: 0 12px 0 16px"
>
<el-option label="全部领域" value="" /> <el-option label="全部领域" value="" />
<el-option v-for="item in domainOptions" :key="item.value" :label="item.label" :value="item.value" /> <el-option
v-for="item in domainOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<el-input v-model="searchKeyword" placeholder="搜索实体" <el-input
v-model="searchKeyword"
placeholder="搜索实体"
style="width: 150px; border: 1px solid rgba(170, 173, 177, 0.4); border-radius: 5px" style="width: 150px; border: 1px solid rgba(170, 173, 177, 0.4); border-radius: 5px"
:suffix-icon="Search" /> :suffix-icon="Search"
/>
</div> </div>
</div> </div>
<div class="stats-row"> <div class="stats-row">
...@@ -116,20 +131,28 @@ ...@@ -116,20 +131,28 @@
<div class="stats-info"> <div class="stats-info">
<div class="stat-item"> <div class="stat-item">
<span class="dot red"></span> <span class="dot red"></span>
<span class="text">新增 <span class="num red">{{ addCount }}</span> 家 (50%规则涉及<span class="num red">{{ <span class="text"
>新增 <span class="num red">{{ addCount }}</span> 家 (50%规则涉及<span class="num red">{{
addRuleCount addRuleCount
}}</span>家)</span> }}</span
>家)</span
>
</div> </div>
<div class="stat-item"> <div class="stat-item">
<span class="dot green"></span> <span class="dot green"></span>
<span class="text">移除 <span class="num green">{{ removeCount }}</span> 家 (50%规则涉及<span <span class="text"
class="num green">{{ removeRuleCount }}</span>家)</span> >移除 <span class="num green">{{ removeCount }}</span> 家 (50%规则涉及<span
class="num green"
>{{ removeRuleCount }}</span
>家)</span
>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="right-content"> <div class="right-content">
<div class="sanction-group-list"> <div class="sanction-group-list">
<el-empty v-if="sanctionList.length === 0" description="暂无制裁清单" />
<div class="sanction-group" v-for="(group, index) in sanctionList" :key="index"> <div class="sanction-group" v-for="(group, index) in sanctionList" :key="index">
<el-table :data="group.entities" style="width: 100%"> <el-table :data="group.entities" style="width: 100%">
<el-table-column label="实体名称" min-width="280"> <el-table-column label="实体名称" min-width="280">
...@@ -145,8 +168,14 @@ ...@@ -145,8 +168,14 @@
</el-table-column> </el-table-column>
<el-table-column label="涉及领域" width="180" align="center"> <el-table-column label="涉及领域" width="180" align="center">
<template #default="scope"> <template #default="scope">
<span v-for="(item, index) in scope.row.fields" :key="index" class="tag" <span
:style="getTagStyle(item)" style="margin: 0 2px">{{ item }}</span> v-for="(item, index) in scope.row.fields"
:key="index"
class="tag"
:style="getTagStyle(item)"
style="margin: 0 2px"
>{{ item }}</span
>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="location" label="上市地点" width="90" align="center" /> <el-table-column prop="location" label="上市地点" width="90" align="center" />
...@@ -154,8 +183,11 @@ ...@@ -154,8 +183,11 @@
<el-table-column prop="revenue" label="营收(亿元)" width="110" align="center" /> <el-table-column prop="revenue" label="营收(亿元)" width="110" align="center" />
<el-table-column label="50%规则子企业" width="180" align="center"> <el-table-column label="50%规则子企业" width="180" align="center">
<template #default="scope"> <template #default="scope">
<span v-if="scope.row.subsidiaryCount" class="subsidiary-link" <span
@click="handleSubsidiaryClick(scope.row)"> v-if="scope.row.subsidiaryCount"
class="subsidiary-link"
@click="handleSubsidiaryClick(scope.row)"
>
{{ scope.row.subsidiaryText }} {{ scope.row.subsidiaryText }}
<span class="blue-text">{{ scope.row.subsidiaryCount }}家 ></span> <span class="blue-text">{{ scope.row.subsidiaryCount }}家 ></span>
</span> </span>
...@@ -173,8 +205,12 @@ ...@@ -173,8 +205,12 @@
</div> </div>
</div> </div>
<!-- 50%规则子企业弹框 --> <!-- 50%规则子企业弹框 -->
<RuleSubsidiaryDialog v-model="subsidiaryDialogVisible" :company-name="currentSubsidiaryCompanyName" <RuleSubsidiaryDialog
:total-count="currentSubsidiaryCount" :data-list="currentSubsidiaryList" /> v-model="subsidiaryDialogVisible"
:company-name="currentSubsidiaryCompanyName"
:total-count="currentSubsidiaryCount"
:data-list="currentSubsidiaryList"
/>
</div> </div>
</template> </template>
...@@ -267,7 +303,7 @@ const getSanctionOverviewList = async () => { ...@@ -267,7 +303,7 @@ const getSanctionOverviewList = async () => {
removeCount.value = data.removeCount || 0; removeCount.value = data.removeCount || 0;
removeRuleCount.value = data.removeRuleCount || 0; removeRuleCount.value = data.removeRuleCount || 0;
const list = data.sanList || []; const list = activeTab.value === "add" ? data.sanList : data.removeList || [];
sanctionList.value = list.map(item => ({ sanctionList.value = list.map(item => ({
reason: item.sanReason, reason: item.sanReason,
entities: (item.orgList || []).map(org => ({ entities: (item.orgList || []).map(org => ({
...@@ -342,10 +378,12 @@ const getUrlParams = () => { ...@@ -342,10 +378,12 @@ const getUrlParams = () => {
// 单次制裁-制裁概况-制裁实体国家分布 // 单次制裁-制裁概况-制裁实体国家分布
const getEntityCountry = async () => { const getEntityCountry = async () => {
try { try {
const res = await getSingleSanctionEntityCountry({ const params = {
sanRecordId: sanRecordId.value, sanRecordId: sanRecordId.value,
sanTypeId: sanTypeId.value || 1 // 实体清单固定1 sanTypeId: sanTypeId.value || 1 // 默认为1
}); };
console.log("params --:", params);
const res = await getSingleSanctionEntityCountry(params);
if (res.code === 200) { if (res.code === 200) {
const rawData = res.data || []; const rawData = res.data || [];
const maxCount = Math.max(...rawData.map(item => item.count || 0), 1); const maxCount = Math.max(...rawData.map(item => item.count || 0), 1);
...@@ -413,7 +451,8 @@ const formattedData = computed(() => { ...@@ -413,7 +451,8 @@ const formattedData = computed(() => {
fileCode: info.fileCode ? `${info.fileCode} ` : "", fileCode: info.fileCode ? `${info.fileCode} ` : "",
administrativeOrderId: info.administrativeOrderId ? `No. ${info.administrativeOrderId}` : "", administrativeOrderId: info.administrativeOrderId ? `No. ${info.administrativeOrderId}` : "",
postPersonName: info.postPersonName, postPersonName: info.postPersonName,
domains: info.domainNames domains: info.domainNames,
avartar: info.postPersonAvatarUrl
}; };
}); });
...@@ -510,6 +549,7 @@ const entityDistribution = ref([ ...@@ -510,6 +549,7 @@ const entityDistribution = ref([
const sanTypeId = ref(""); const sanTypeId = ref("");
onMounted(() => { onMounted(() => {
// 获取路由参数中的sanTypeId // 获取路由参数中的sanTypeId
console.log("route.query.sanTypeId --:", route.query.sanTypeId);
sanTypeId.value = route.query.sanTypeId || "1"; sanTypeId.value = route.query.sanTypeId || "1";
// 获取URL参数 // 获取URL参数
getUrlParams(); getUrlParams();
......
...@@ -239,8 +239,6 @@ const handlePageChange = async newPage => { ...@@ -239,8 +239,6 @@ const handlePageChange = async newPage => {
// ========== 选择某项 ========== // ========== 选择某项 ==========
const selectSanction = item => { const selectSanction = item => {
selectedSanctionId.value = item.id; selectedSanctionId.value = item.id;
// 可在此处触发其他逻辑,如查看详情
// 替换当前路由参数,并重新加载数据
router.replace({ router.replace({
path: window.location.pathname, path: window.location.pathname,
query: { query: {
...@@ -248,11 +246,8 @@ const selectSanction = item => { ...@@ -248,11 +246,8 @@ const selectSanction = item => {
sanTypeId: item.sanTypeId sanTypeId: item.sanTypeId
} }
}); });
// 3. 立即重新加载数据(关键!)
getSingleSanctionOverviewData();
// 4. 可选:关闭弹窗
sanctionModalVisible.value = false; sanctionModalVisible.value = false;
window.location.reload();
}; };
// ========== 关闭弹窗时重置 ========== // ========== 关闭弹窗时重置 ==========
...@@ -278,6 +273,7 @@ onMounted(() => { ...@@ -278,6 +273,7 @@ onMounted(() => {
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow-y: auto; overflow-y: auto;
padding-bottom: 50px;
.header { .header {
width: 100%; width: 100%;
height: 148px; height: 148px;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论