提交 a2fb3164 authored 作者: caijian's avatar caijian

Merge branch 'cj_dev'

......@@ -20,7 +20,10 @@ export function getAllDomainCount(params) {
/**
* @header token
* @param {Object} params
* @param {String} params.byYOrM - 按月统计或按年统计
* @param {String} params.startDate - 开始日期
* @param {String} params.endDate - 结束日期
* @param {String} params.org - 机构
* @param {String} params.sanMeasures - 制裁手段
*/
export function getDomainContainmentTrend(params) {
return request({
......
......@@ -39,13 +39,26 @@
</div>
<div class="title-right">
<el-select
v-model="select1"
placeholder="按月统计"
v-model="deptValue"
placeholder="全部部门"
class="custom-select"
@change="handleGetDomainContainmentTrend"
>
<el-option label="按月统计" value="按月统计" />
<el-option label="按年统计" value="按年统计" />
<el-option label="全部部门" value="" />
<el-option
v-for="item in departmentList"
:key="item.departId"
:label="item.departName"
:value="item.departId"
/>
</el-select>
<el-select
v-model="methodValue"
placeholder="全部制裁手段"
class="custom-select"
@change="handleGetDomainContainmentTrend"
>
<el-option v-for="item in methodOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
......@@ -114,7 +127,7 @@
<el-option v-for="item in fieldOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<div class="main-box">
<div class="main-box" v-loading="rankLoading" element-loading-background="rgba(255, 255, 255, 0.5)">
<!-- 机构排行的原有样式 -->
<template v-if="rankType === 'institution'">
<div v-for="(item, index) in rankList" :key="index" class="rank-item">
......@@ -264,13 +277,45 @@ import {
getDomainContainmentRanking,
getDomainContainmentTimeline
} from "@/api/zmOverview/allDomains";
import { getUSGovernmentLatestDynamic } from "@/api/allGovernment.js";
import { getUSGovernmentLatestDynamic, getDepartmentList } from "@/api/allGovernment.js";
const router = useRouter();
const activeDate = inject("activeDate");
const select1 = ref("按月统计");
const deptValue = ref("");
const methodValue = ref("");
const departmentList = ref([]);
const methodOptions = ref([
{ label: "全部制裁手段", value: "" },
{ label: "法案", value: "-1" },
{ label: "政令", value: "-2" },
{ label: "实体清单", value: "1" },
{ label: "特别国民指定清单", value: "2" },
{ label: "涉军企业", value: "3" },
{ label: "行业制裁识别清单", value: "4" },
{ label: "无法核实清单", value: "5" },
{ label: "军事最终用户清单", value: "6" },
{ label: "非SDN中国军工企业名单", value: "7" },
{ label: "拒绝往来人员清单", value: "8" },
{ label: "军事最终用途与最终用户规则", value: "9" },
{ label: "欧盟合并制裁清单", value: "10" },
{ label: "英国制裁清单", value: "11" },
{ label: "加拿大合并自主制裁清单", value: "12" },
{ label: "商业管制清单", value: "13" }
]);
const getDepartmentListData = async () => {
try {
const res = await getDepartmentList();
if (res.code === 200 && res.data) {
departmentList.value = res.data;
}
} catch (error) {
console.error("获取部门数据失败:", error);
}
};
const rankType = ref("institution");
const rankLoading = ref(false);
const selectedField = ref("");
const selectedFieldTimeline = ref("");
const timelineContainerWidth = 1700;
......@@ -722,9 +767,18 @@ const box5Data = ref({});
const handleGetDomainContainmentTrend = async () => {
try {
const res = await getDomainContainmentTrend({
byYOrM: select1.value
});
const { startDate, endDate } = getCalculatedDate(activeDate.value);
const params = {
startDate,
endDate
};
if (deptValue.value) {
params.org = deptValue.value;
}
if (methodValue.value) {
params.sanMeasures = methodValue.value;
}
const res = await getDomainContainmentTrend(params);
console.log("美对华领域打压遏制数量趋势", res);
if (res.code === 200 && res.data) {
......@@ -847,6 +901,7 @@ const rankTypeMap = {
// 获取领域遏制排名数据
const handleGetDomainContainmentRanking = async () => {
rankLoading.value = true;
rankList.value = [];
try {
const res = await getDomainContainmentRanking(
......@@ -863,6 +918,8 @@ const handleGetDomainContainmentRanking = async () => {
console.error("获取美对华领域打压遏制排行失败:", error);
// 设置默认空数组
rankList.value = [];
} finally {
rankLoading.value = false;
}
};
......@@ -918,6 +975,7 @@ onMounted(() => {
// let Chart = getMultiLineChart(box5Data.value);
// setChart(Chart, "chartRef");
handleGetDomainContainmentTrend();
getDepartmentListData();
handleGetAllDomainCount();
handleGetDomainContainmentRanking();
......@@ -932,6 +990,7 @@ onUnmounted(() => {
watch(activeDate, () => {
handleGetAllDomainCount();
handleGetDomainContainmentTrend();
});
</script>
......
......@@ -310,6 +310,189 @@ const countryNameMap = {
Jamaica: "Jamaica"
};
const nameMap = {
Afghanistan: "阿富汗",
Angola: "安哥拉",
Albania: "阿尔巴尼亚",
"United Arab Emirates": "阿联酋",
Argentina: "阿根廷",
Armenia: "亚美尼亚",
"French Southern and Antarctic Lands": "法属南半球和南极领地",
Australia: "澳大利亚",
Austria: "奥地利",
Azerbaijan: "阿塞拜疆",
Burundi: "布隆迪",
Belgium: "比利时",
Benin: "贝宁",
"Burkina Faso": "布基纳法索",
Bangladesh: "孟加拉国",
Bulgaria: "保加利亚",
"The Bahamas": "巴哈马",
"Bosnia and Herzegovina": "波斯尼亚和黑塞哥维那",
Belarus: "白俄罗斯",
Belize: "伯利兹",
Bermuda: "百慕大",
Bolivia: "玻利维亚",
Brazil: "巴西",
Brunei: "文莱",
Bhutan: "不丹",
Botswana: "博茨瓦纳",
"Central African Republic": "中非共和国",
Canada: "加拿大",
Switzerland: "瑞士",
Chile: "智利",
China: "中国",
"Ivory Coast": "科特迪瓦",
Cameroon: "喀麦隆",
"Democratic Republic of the Congo": "刚果民主共和国",
"Republic of the Congo": "刚果共和国",
Colombia: "哥伦比亚",
"Costa Rica": "哥斯达黎加",
Cuba: "古巴",
"Northern Cyprus": "北塞浦路斯",
Cyprus: "塞浦路斯",
"Czech Republic": "捷克",
Germany: "德国",
Djibouti: "吉布提",
Denmark: "丹麦",
"Dominican Republic": "多米尼加共和国",
Algeria: "阿尔及利亚",
Ecuador: "厄瓜多尔",
Egypt: "埃及",
Eritrea: "厄立特里亚",
Spain: "西班牙",
Estonia: "爱沙尼亚",
Ethiopia: "埃塞俄比亚",
Finland: "芬兰",
Fiji: "斐济",
"Falkland Islands": "福克兰群岛",
France: "法国",
Gabon: "加蓬",
"United Kingdom": "英国",
Georgia: "格鲁吉亚",
Ghana: "加纳",
Guinea: "几内亚",
Gambia: "冈比亚",
"Guinea Bissau": "几内亚比绍",
"Equatorial Guinea": "赤道几内亚",
Greece: "希腊",
Greenland: "格陵兰",
Guatemala: "危地马拉",
"French Guiana": "法属圭亚那",
Guyana: "圭亚那",
Honduras: "洪都拉斯",
Croatia: "克罗地亚",
Haiti: "海地",
Hungary: "匈牙利",
Indonesia: "印度尼西亚",
India: "印度",
Ireland: "爱尔兰",
Iran: "伊朗",
Iraq: "伊拉克",
Iceland: "冰岛",
Israel: "以色列",
Italy: "意大利",
Jamaica: "牙买加",
Jordan: "约旦",
Japan: "日本",
Kazakhstan: "哈萨克斯坦",
Kenya: "肯尼亚",
Kyrgyzstan: "吉尔吉斯斯坦",
Cambodia: "柬埔寨",
"South Korea": "韩国",
Korea: "韩国",
Kosovo: "科索沃",
Kuwait: "科威特",
Laos: "老挝",
Lebanon: "黎巴嫩",
Liberia: "利比里亚",
Libya: "利比亚",
"Sri Lanka": "斯里兰卡",
Lesotho: "莱索托",
Lithuania: "立陶宛",
Luxembourg: "卢森堡",
Latvia: "拉脱维亚",
Morocco: "摩洛哥",
Moldova: "摩尔多瓦",
Madagascar: "马达加斯加",
Mexico: "墨西哥",
Macedonia: "马其顿",
Mali: "马里",
Myanmar: "缅甸",
Montenegro: "黑山",
Mongolia: "蒙古",
Mozambique: "莫桑比克",
Mauritania: "毛里塔尼亚",
Malawi: "马拉维",
Malaysia: "马来西亚",
Namibia: "纳米比亚",
"New Caledonia": "新喀里多尼亚",
Niger: "尼日尔",
Nigeria: "尼日利亚",
Nicaragua: "尼加拉瓜",
Netherlands: "荷兰",
Norway: "挪威",
Nepal: "尼泊尔",
"New Zealand": "新西兰",
Oman: "阿曼",
Pakistan: "巴基斯坦",
Panama: "巴拿马",
Peru: "秘鲁",
Philippines: "菲律宾",
"Papua New Guinea": "巴布亚新几内亚",
Poland: "波兰",
"Puerto Rico": "波多黎各",
"North Korea": "朝鲜",
Portugal: "葡萄牙",
Paraguay: "巴拉圭",
Qatar: "卡塔尔",
Romania: "罗马尼亚",
Russia: "俄罗斯",
Rwanda: "卢旺达",
"Western Sahara": "西撒哈拉",
"Saudi Arabia": "沙特阿拉伯",
Sudan: "苏丹",
"South Sudan": "南苏丹",
Senegal: "塞内加尔",
"Solomon Islands": "所罗门群岛",
"Sierra Leone": "塞拉利昂",
"El Salvador": "萨尔瓦多",
"Somaliland": "索马里兰",
Somalia: "索马里",
"Republic of Serbia": "塞尔维亚",
Suriname: "苏里南",
Slovakia: "斯洛伐克",
Slovenia: "斯洛文尼亚",
Sweden: "瑞典",
Swaziland: "斯威士兰",
Syria: "叙利亚",
Chad: "乍得",
Togo: "多哥",
Thailand: "泰国",
Tajikistan: "塔吉克斯坦",
Turkmenistan: "土库曼斯坦",
"East Timor": "东帝汶",
"Trinidad and Tobago": "特立尼达和多巴哥",
Tunisia: "突尼斯",
Turkey: "土耳其",
Tanzania: "坦桑尼亚",
"United Republic of Tanzania": "坦桑尼亚",
Uganda: "乌干达",
Ukraine: "乌克兰",
Uruguay: "乌拉圭",
"United States": "美国",
Uzbekistan: "乌兹别克斯坦",
Venezuela: "委内瑞拉",
Vietnam: "越南",
Vanuatu: "瓦努阿图",
"West Bank": "西岸",
Yemen: "也门",
"South Africa": "南非",
Zambia: "赞比亚",
Zimbabwe: "津巴布韦",
Singapore: "新加坡"
};
const next = () => {
let arr = [...carouselList.value];
if (startIndex.value < carouselList.value.length - 5) {
......@@ -392,6 +575,55 @@ const getColorByValue = (value, maxValue) => {
return `rgb(${r}, ${g}, ${b})`;
};
/**
* 根据 value 和 maxValue 生成高饱和度但不刺眼的 RGB 颜色
* @param {number} value - 当前值(0 到 maxValue)
* @param {number} maxValue - 最大值
* @returns {string} RGB 颜色字符串,如 "rgb(255, 0, 0)"
*/
const getColorByValueRandom = (value, maxValue) => {
const ratio = Math.min(Math.max(value / maxValue, 0), 1);
// HSL 参数:高饱和度,中等偏暗亮度,避免太亮或黑色
let h = ratio * 360; // 色相:0°(红) 到 360°(循环)
h = h % 360; // 修复:确保 h=360 映射回 0,避免黑色
const s = 100; // 饱和度 100%
const l = 40; // 亮度 40%(不亮不暗)
// HSL 到 RGB 转换
const hslToRgb = (h, s, l) => {
s /= 100;
l /= 100;
const c = (1 - Math.abs(2 * l - 1)) * s;
const x = c * (1 - Math.abs((h / 60) % 2 - 1));
const m = l - c / 2;
let r = 0, g = 0, b = 0;
if (0 <= h && h < 60) {
r = c; g = x; b = 0;
} else if (60 <= h && h < 120) {
r = x; g = c; b = 0;
} else if (120 <= h && h < 180) {
r = 0; g = c; b = x;
} else if (180 <= h && h < 240) {
r = 0; g = x; b = c;
} else if (240 <= h && h < 300) {
r = x; g = 0; b = c;
} else if (300 <= h && h < 360) {
r = c; g = 0; b = x;
}
// 移除 else 分支(修复后无需,h 已 %360)
r = Math.round((r + m) * 255);
g = Math.round((g + m) * 255);
b = Math.round((b + m) * 255);
return `rgb(${r}, ${g}, ${b})`;
};
return hslToRgb(h, s, l);
}
const chartDom = ref();
const myChart = ref();
function createChart() {
......@@ -400,12 +632,21 @@ function createChart() {
const maxValue = Math.max(...countList.value.map(item => item.value));
// 为每个数据项计算颜色
const processedData = countList.value.map(item => ({
...item,
itemStyle: {
color: getColorByValue(item.value, maxValue)
}
}));
const processedData = countList.value.map(item => {
const color = getColorByValueRandom(item.value, maxValue);
return {
...item,
name: nameMap[item.name] || item.name, // 将英文名转换为中文名以匹配地图区域
itemStyle: {
color: color
},
emphasis: {
itemStyle: {
areaColor: color // 高亮时保持原色
}
}
};
});
const option = {
// geo: {
......@@ -424,14 +665,9 @@ function createChart() {
trigger: "item",
formatter: function (params) {
if (params.data) {
// 从数据中查找对应的中文名称
const item = countList.value.find(item => item.name === params.name);
console.log(item);
if (item) {
return `${item.zhName}: ${params.data.value || 0}`;
} else {
return `${params.name}: ${params.data.value || 0}`;
}
// 既然 processedData 已经匹配上了,params.data 就是正确的数据项
// 包含 value 和 zhName
return `${params.data.zhName || params.name}: ${params.data.value || 0}`;
}
return params.name;
}
......@@ -454,16 +690,17 @@ function createChart() {
{
name: "数据值",
type: "map",
roam: true, // 允许缩放和平移
roam: "move", // 允许平移,禁止缩放
zoom: 1.2, // 初始缩放级别
map: "world",
nameMap: nameMap,
emphasis: {
label: {
show: true,
color: "#fff"
},
itemStyle: {
areaColor: null,
areaColor: "#aaa", // 无数据区域高亮颜色(灰色,避免白色看不清文字)
borderWidth: 1,
borderColor: "#fff"
}
......@@ -637,7 +874,11 @@ const initRightDonut = async () => {
let item = {
name: res.data[i].country,
x: Math.random() * 10,
y: Math.random() * 10
y: Math.random() * 10,
// 节点颜色
itemStyle: {
color: `rgba(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, 1)`
}
};
let item1 = {
name: res.data[i].relationCountry,
......@@ -652,7 +893,7 @@ const initRightDonut = async () => {
if (index === -1) {
data.push(item);
}
if (index1 === -1) {
data.push(item1);
}
......@@ -694,7 +935,7 @@ const initRightDonut = async () => {
series: [
{
type: "graph",
layout: "none",
layout: "circular",
symbolSize: 50,
roam: true,
label: {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论