提交 3c267bc1 authored 作者: 朱亚刚's avatar 朱亚刚
...@@ -20,7 +20,10 @@ export function getAllDomainCount(params) { ...@@ -20,7 +20,10 @@ export function getAllDomainCount(params) {
/** /**
* @header token * @header token
* @param {Object} params * @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) { export function getDomainContainmentTrend(params) {
return request({ return request({
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import WrittingAsstaint from "@/views/writtingAsstaint/index.vue"; import WrittingAsstaint from "@/views/writtingAsstaint/index.vue";
const writtingRoutes = [ const writtingRoutes = [
// 法案系统路由 // 智能写报路由
{ {
path: "/writtingAsstaint", path: "/writtingAsstaint",
name: "writtingAsstaint", name: "writtingAsstaint",
......
...@@ -39,13 +39,26 @@ ...@@ -39,13 +39,26 @@
</div> </div>
<div class="title-right"> <div class="title-right">
<el-select <el-select
v-model="select1" v-model="deptValue"
placeholder="按月统计" placeholder="全部部门"
class="custom-select" class="custom-select"
@change="handleGetDomainContainmentTrend" @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> </el-select>
</div> </div>
</div> </div>
...@@ -114,7 +127,7 @@ ...@@ -114,7 +127,7 @@
<el-option v-for="item in fieldOptions" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in fieldOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</div> </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'"> <template v-if="rankType === 'institution'">
<div v-for="(item, index) in rankList" :key="index" class="rank-item"> <div v-for="(item, index) in rankList" :key="index" class="rank-item">
...@@ -264,13 +277,45 @@ import { ...@@ -264,13 +277,45 @@ import {
getDomainContainmentRanking, getDomainContainmentRanking,
getDomainContainmentTimeline getDomainContainmentTimeline
} from "@/api/zmOverview/allDomains"; } from "@/api/zmOverview/allDomains";
import { getUSGovernmentLatestDynamic } from "@/api/allGovernment.js"; import { getUSGovernmentLatestDynamic, getDepartmentList } from "@/api/allGovernment.js";
const router = useRouter(); const router = useRouter();
const activeDate = inject("activeDate"); 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 rankType = ref("institution");
const rankLoading = ref(false);
const selectedField = ref(""); const selectedField = ref("");
const selectedFieldTimeline = ref(""); const selectedFieldTimeline = ref("");
const timelineContainerWidth = 1700; const timelineContainerWidth = 1700;
...@@ -722,9 +767,18 @@ const box5Data = ref({}); ...@@ -722,9 +767,18 @@ const box5Data = ref({});
const handleGetDomainContainmentTrend = async () => { const handleGetDomainContainmentTrend = async () => {
try { try {
const res = await getDomainContainmentTrend({ const { startDate, endDate } = getCalculatedDate(activeDate.value);
byYOrM: select1.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); console.log("美对华领域打压遏制数量趋势", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
...@@ -847,6 +901,7 @@ const rankTypeMap = { ...@@ -847,6 +901,7 @@ const rankTypeMap = {
// 获取领域遏制排名数据 // 获取领域遏制排名数据
const handleGetDomainContainmentRanking = async () => { const handleGetDomainContainmentRanking = async () => {
rankLoading.value = true;
rankList.value = []; rankList.value = [];
try { try {
const res = await getDomainContainmentRanking( const res = await getDomainContainmentRanking(
...@@ -863,6 +918,8 @@ const handleGetDomainContainmentRanking = async () => { ...@@ -863,6 +918,8 @@ const handleGetDomainContainmentRanking = async () => {
console.error("获取美对华领域打压遏制排行失败:", error); console.error("获取美对华领域打压遏制排行失败:", error);
// 设置默认空数组 // 设置默认空数组
rankList.value = []; rankList.value = [];
} finally {
rankLoading.value = false;
} }
}; };
...@@ -918,6 +975,7 @@ onMounted(() => { ...@@ -918,6 +975,7 @@ onMounted(() => {
// let Chart = getMultiLineChart(box5Data.value); // let Chart = getMultiLineChart(box5Data.value);
// setChart(Chart, "chartRef"); // setChart(Chart, "chartRef");
handleGetDomainContainmentTrend(); handleGetDomainContainmentTrend();
getDepartmentListData();
handleGetAllDomainCount(); handleGetAllDomainCount();
handleGetDomainContainmentRanking(); handleGetDomainContainmentRanking();
...@@ -932,6 +990,7 @@ onUnmounted(() => { ...@@ -932,6 +990,7 @@ onUnmounted(() => {
watch(activeDate, () => { watch(activeDate, () => {
handleGetAllDomainCount(); handleGetAllDomainCount();
handleGetDomainContainmentTrend();
}); });
</script> </script>
......
...@@ -310,6 +310,189 @@ const countryNameMap = { ...@@ -310,6 +310,189 @@ const countryNameMap = {
Jamaica: "Jamaica" 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 = () => { const next = () => {
let arr = [...carouselList.value]; let arr = [...carouselList.value];
if (startIndex.value < carouselList.value.length - 5) { if (startIndex.value < carouselList.value.length - 5) {
...@@ -392,6 +575,55 @@ const getColorByValue = (value, maxValue) => { ...@@ -392,6 +575,55 @@ const getColorByValue = (value, maxValue) => {
return `rgb(${r}, ${g}, ${b})`; 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 chartDom = ref();
const myChart = ref(); const myChart = ref();
function createChart() { function createChart() {
...@@ -400,12 +632,21 @@ function createChart() { ...@@ -400,12 +632,21 @@ function createChart() {
const maxValue = Math.max(...countList.value.map(item => item.value)); const maxValue = Math.max(...countList.value.map(item => item.value));
// 为每个数据项计算颜色 // 为每个数据项计算颜色
const processedData = countList.value.map(item => ({ const processedData = countList.value.map(item => {
...item, const color = getColorByValueRandom(item.value, maxValue);
itemStyle: { return {
color: getColorByValue(item.value, maxValue) ...item,
} name: nameMap[item.name] || item.name, // 将英文名转换为中文名以匹配地图区域
})); itemStyle: {
color: color
},
emphasis: {
itemStyle: {
areaColor: color // 高亮时保持原色
}
}
};
});
const option = { const option = {
// geo: { // geo: {
...@@ -424,14 +665,9 @@ function createChart() { ...@@ -424,14 +665,9 @@ function createChart() {
trigger: "item", trigger: "item",
formatter: function (params) { formatter: function (params) {
if (params.data) { if (params.data) {
// 从数据中查找对应的中文名称 // 既然 processedData 已经匹配上了,params.data 就是正确的数据项
const item = countList.value.find(item => item.name === params.name); // 包含 value 和 zhName
console.log(item); return `${params.data.zhName || params.name}: ${params.data.value || 0}`;
if (item) {
return `${item.zhName}: ${params.data.value || 0}`;
} else {
return `${params.name}: ${params.data.value || 0}`;
}
} }
return params.name; return params.name;
} }
...@@ -454,16 +690,17 @@ function createChart() { ...@@ -454,16 +690,17 @@ function createChart() {
{ {
name: "数据值", name: "数据值",
type: "map", type: "map",
roam: true, // 允许缩放和平移 roam: "move", // 允许平移,禁止缩放
zoom: 1.2, // 初始缩放级别 zoom: 1.2, // 初始缩放级别
map: "world", map: "world",
nameMap: nameMap,
emphasis: { emphasis: {
label: { label: {
show: true, show: true,
color: "#fff" color: "#fff"
}, },
itemStyle: { itemStyle: {
areaColor: null, areaColor: "#aaa", // 无数据区域高亮颜色(灰色,避免白色看不清文字)
borderWidth: 1, borderWidth: 1,
borderColor: "#fff" borderColor: "#fff"
} }
...@@ -637,7 +874,11 @@ const initRightDonut = async () => { ...@@ -637,7 +874,11 @@ const initRightDonut = async () => {
let item = { let item = {
name: res.data[i].country, name: res.data[i].country,
x: Math.random() * 10, 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 = { let item1 = {
name: res.data[i].relationCountry, name: res.data[i].relationCountry,
...@@ -652,7 +893,7 @@ const initRightDonut = async () => { ...@@ -652,7 +893,7 @@ const initRightDonut = async () => {
if (index === -1) { if (index === -1) {
data.push(item); data.push(item);
} }
if (index1 === -1) { if (index1 === -1) {
data.push(item1); data.push(item1);
} }
...@@ -694,7 +935,7 @@ const initRightDonut = async () => { ...@@ -694,7 +935,7 @@ const initRightDonut = async () => {
series: [ series: [
{ {
type: "graph", type: "graph",
layout: "none", layout: "circular",
symbolSize: 50, symbolSize: 50,
roam: true, roam: true,
label: { label: {
......
...@@ -14,7 +14,12 @@ ...@@ -14,7 +14,12 @@
> >
<img class="section-title" :src="section.title" /> <img class="section-title" :src="section.title" />
<div class="stats"> <div class="stats">
<div class="ball-item" v-for="value,idx in sections[index].waveBall" :key="idx" @click="highLight(value.type)"> <div
class="ball-item"
v-for="(value, idx) in sections[index].waveBall"
:key="idx"
@click="highLight(value.type)"
>
<WaveBall :percent="value.percent" :data="value" :color="section.waterColor" :size="128" /> <WaveBall :percent="value.percent" :data="value" :color="section.waterColor" :size="128" />
<div class="text-box"> <div class="text-box">
<div class="waveBall-text"> <div class="waveBall-text">
...@@ -24,16 +29,20 @@ ...@@ -24,16 +29,20 @@
</div> </div>
</div> </div>
</div> </div>
<div class="bottm-box" :style="sections[index].waveBall.length === 2 ? 'width: 350px' : 'width:503px'"> <div
class="bottm-box"
:style="sections[index].waveBall.length === 2 ? 'width: 350px' : 'width:503px'"
@click="handleClickCardBottomInfo(cardBottomInfo[index])"
>
<img src="./icon/title-icon-1.png" /> <img src="./icon/title-icon-1.png" />
<div <div
class="bottm-box-text" class="bottm-box-text"
:style="sections[index].waveBall.length === 2 ? 'width: 225px' : 'width:378px'" :style="sections[index].waveBall.length === 2 ? 'width: 225px' : 'width:378px'"
> >
{{ sections[index].title }} {{ cardBottomInfo[index]?.title || "暂无新增数据" }}
</div> </div>
<div style="width: 50px; color: #ffffff"> <div style="width: 115px; color: #ffffff">
{{ sections[index].date }} {{ cardBottomInfo[index]?.date }}
</div> </div>
</div> </div>
</div> </div>
...@@ -54,12 +63,9 @@ ...@@ -54,12 +63,9 @@
v-for="(item, index) in warningList" v-for="(item, index) in warningList"
:key="index" :key="index"
@click="handleClickToDetailO(item)" @click="handleClickToDetailO(item)"
@mouseenter="onMouseEnter(item.signalId)" @mouseenter="onMouseEnter(item, index)"
@mouseleave="onMouseLeave" @mouseleave="onMouseLeave"
:class="[ :class="['risk-signals-item', { 'risk-signals-item-hightLight': riskSignalActiveIndex === index }]"
'risk-signals-item',
{ 'risk-signals-item-hightLight': item.eventType === highlightedEventType }
]"
> >
<div <div
class="item-left" class="item-left"
...@@ -79,10 +85,20 @@ ...@@ -79,10 +85,20 @@
</div> </div>
</div> </div>
<div class="news"> <div class="news">
<div class="box1-left" @click="handleSwithCurNews('left')"> <div
class="box1-left"
@click="handleSwithCurNews('left')"
@mouseenter="handleInBtn"
@mouseleave="handleOutBtn"
>
<img :src="leftBtn" alt="" /> <img :src="leftBtn" alt="" />
</div> </div>
<div class="box1-right" @click="handleSwithCurNews('right')"> <div
class="box1-right"
@click="handleSwithCurNews('right')"
@mouseenter="handleInBtn"
@mouseleave="handleOutBtn"
>
<img :src="rightBtn" alt="" /> <img :src="rightBtn" alt="" />
</div> </div>
<el-carousel <el-carousel
...@@ -118,7 +134,9 @@ ...@@ -118,7 +134,9 @@
<div class="carousel-bottom"> <div class="carousel-bottom">
<div class="left"> <div class="left">
{{ {{
News.hotspotDate + ' ' + (News.hotspotOrgName ? News.hotspotOrgName : "暂无发布机构数据") News.hotspotDate +
" " +
(News.hotspotOrgName ? News.hotspotOrgName : "暂无发布机构数据")
}} }}
</div> </div>
<div class="right"> <div class="right">
...@@ -283,6 +301,43 @@ const sections = ref([ ...@@ -283,6 +301,43 @@ const sections = ref([
} }
]); ]);
const cardList1 = ref([]);
const cardList2 = ref([]);
const cardList3 = ref([]);
const cardList4 = ref([]);
const cardBottomInfo = ref([
{
type: "",
id: "",
title: "",
date: ""
},
{
type: "",
id: "",
title: "",
date: ""
},
{
type: "",
id: "",
title: "",
date: ""
},
{
type: "",
id: "",
title: "",
date: ""
}
]);
const cardShowIndex1 = ref(0);
const cardShowIndex2 = ref(0);
const cardShowIndex3 = ref(0);
const cardShowIndex4 = ref(0);
// 最新风险动态统计 // 最新风险动态统计
const handleGetLatestRiskUpdates = async () => { const handleGetLatestRiskUpdates = async () => {
try { try {
...@@ -431,6 +486,56 @@ const handleGetLatestRisks = async () => { ...@@ -431,6 +486,56 @@ const handleGetLatestRisks = async () => {
warningList.value = res.data.riskVOS; warningList.value = res.data.riskVOS;
hotNewsList.value = res.data.hotspotVOS; hotNewsList.value = res.data.hotspotVOS;
riskTotal.value = res.data.riskCount; riskTotal.value = res.data.riskCount;
cardList1.value = warningList.value
.filter(item => {
return item.eventType === "法案" || item.eventType === "行政令";
})
.map(val => {
return {
type: val.eventType,
id: val.signalId,
title: val.eventType + ":" + val.signalTitle,
date: val.signalTime
};
});
console.log("cardList1", cardList1.value);
cardList2.value = hotNewsList.value
.filter(item => {
return item.eventType === "实体清单" || item.eventType === "CCL";
})
.map(val => {
return {
type: val.eventType,
id: val.signalId,
title: val.eventType + ":" + val.signalTitle,
date: val.signalTime
};
});
cardList3.value = hotNewsList.value
.filter(item => {
return item.eventType === "SDN" || item.eventType === "涉军企业";
})
.map(val => {
return {
type: val.eventType,
id: val.signalId,
title: val.eventType + ":" + val.signalTitle,
date: val.signalTime
};
});
cardList4.value = hotNewsList.value
.filter(item => {
return item.eventType === "337调查" || item.eventType === "232调查" || item.eventType === "301调查";
})
.map(val => {
return {
type: val.eventType,
id: val.signalId,
title: val.eventType + ":" + val.signalTitle,
date: val.signalTime
};
});
console.log(hotNewsList.value, "hotNewsList.value"); console.log(hotNewsList.value, "hotNewsList.value");
} }
} catch (error) { } catch (error) {
...@@ -464,20 +569,111 @@ const handleClickToDetail = () => { ...@@ -464,20 +569,111 @@ const handleClickToDetail = () => {
}; };
// 查看详情 传递参数 // 查看详情 传递参数
const handleClickToDetailO = item => { const handleClickToDetailO = item => {
window.sessionStorage.setItem("billId", item.billId); // window.sessionStorage.setItem("billId", item.billId);
window.sessionStorage.setItem("curTabName", item.name || item.signalTitle); // window.sessionStorage.setItem("curTabName", item.name || item.signalTitle);
const route = router.resolve("/billLayout?billId=" + item.billId); // const route = router.resolve("/billLayout?billId=" + item.billId);
window.open(route.href, "_blank"); // window.open(route.href, "_blank");
window.sessionStorage.setItem("curTabName", item.signalTitle);
// console.log("item", item);
let curRoute;
switch (item.eventType) {
case "法案":
curRoute = router.resolve({
path: "/billLayout",
query: {
billId: item.signalId
}
});
break;
case "行政令":
curRoute = router.resolve({
path: "/decreeLayout",
query: {
id: item.signalId
}
});
break;
case "实体清单":
curRoute = router.resolve({
path: "/exportControl/singleSanction",
query: {
id: item.signalId
}
});
break;
case "CCL":
curRoute = router.resolve({
path: "/exportControl/singleSanction",
query: {
id: item.signalId
}
});
break;
case "SDN":
curRoute = router.resolve({
path: "/billLayout",
query: {
billId: item.signalId
}
});
break;
case "涉军企业":
curRoute = router.resolve({
name: "companyPages",
params: {
id: item.signalId
}
});
break;
case "337调查":
curRoute = router.resolve({
path: "/marketSingleCaseLayout/overview",
query: {
id: "337",
searchId: item.signalId + ""
}
});
break;
case "232调查":
curRoute = router.resolve({
path: "/marketSingleCaseLayout/overview",
query: {
id: "232",
searchId: item.signalId + ""
}
});
break;
case "301调查":
curRoute = router.resolve({
path: "/marketSingleCaseLayout/overview",
query: {
id: "301",
searchId: item.signalId + ""
}
});
break;
}
window.open(curRoute.href, "_blank");
}; };
const currentHoveredSignalId = ref(null); const currentHoveredSignalId = ref(null);
const onMouseEnter = signalId => { const onMouseEnter = (item, index) => {
currentHoveredSignalId.value = signalId; currentHoveredSignalId.value = item.signalId;
riskSignalActiveIndex.value = index;
clearInterval(timer2);
}; };
const onMouseLeave = () => { const onMouseLeave = () => {
currentHoveredSignalId.value = null; currentHoveredSignalId.value = null;
timer2 = setInterval(() => {
if (riskSignalActiveIndex.value < warningList.value.length - 1) {
riskSignalActiveIndex.value++;
} else {
riskSignalActiveIndex.value = 0;
}
currentHoveredSignalId.value = warningList.value[riskSignalActiveIndex.value].signalId;
}, 3000);
}; };
// 计算属性或使用 watchEffect 来动态计算 filteredHotNewsList // 计算属性或使用 watchEffect 来动态计算 filteredHotNewsList
...@@ -559,19 +755,214 @@ const toDetaile = (id, type) => { ...@@ -559,19 +755,214 @@ const toDetaile = (id, type) => {
}; };
const handleSwithCurNews = name => { const handleSwithCurNews = name => {
if (name === "left") { if (name === "left") {
carouselRef.value.prev(); // carouselRef.value.prev();
if (riskSignalActiveIndex.value > 0) {
riskSignalActiveIndex.value--;
} else {
riskSignalActiveIndex.value = warningList.value.length - 1;
}
} else { } else {
carouselRef.value.next(); // carouselRef.value.next();
if (riskSignalActiveIndex.value < warningList.value.length - 1) {
riskSignalActiveIndex.value++;
} else {
riskSignalActiveIndex.value = 0;
}
}
currentHoveredSignalId.value = warningList.value[riskSignalActiveIndex.value].signalId;
};
const handleInBtn = () => {
clearInterval(timer2);
};
const handleOutBtn = () => {
currentHoveredSignalId.value = null;
timer2 = setInterval(() => {
if (riskSignalActiveIndex.value < warningList.value.length - 1) {
riskSignalActiveIndex.value++;
} else {
riskSignalActiveIndex.value = 0;
}
currentHoveredSignalId.value = warningList.value[riskSignalActiveIndex.value].signalId;
}, 3000);
};
// 实体清单,CCL,SDN,涉军企业,337调查,232调查,301调查
const handleClickCardBottomInfo = item => {
window.sessionStorage.setItem("curTabName", item.title);
console.log("item", item);
let curRoute;
switch (item.type) {
case "法案":
curRoute = router.resolve({
path: "/billLayout",
query: {
billId: item.id
}
});
break;
case "行政令":
curRoute = router.resolve({
path: "/decreeLayout",
query: {
id: item.id
}
});
break;
case "实体清单":
curRoute = router.resolve({
path: "/exportControl/singleSanction",
query: {
id: item.id
}
});
break;
case "CCL":
curRoute = router.resolve({
path: "/exportControl/singleSanction",
query: {
id: item.id
}
});
break;
case "SDN":
curRoute = router.resolve({
path: "/billLayout",
query: {
billId: item.id
}
});
break;
case "涉军企业":
curRoute = router.resolve({
name: "companyPages",
params: {
id: item.id
}
});
break;
case "337调查":
curRoute = router.resolve({
path: "/marketSingleCaseLayout/overview",
query: {
id: "337",
searchId: item.id + ""
}
});
break;
case "232调查":
curRoute = router.resolve({
path: "/marketSingleCaseLayout/overview",
query: {
id: "232",
searchId: item.id + ""
}
});
break;
case "301调查":
curRoute = router.resolve({
path: "/marketSingleCaseLayout/overview",
query: {
id: "301",
searchId: item.id + ""
}
});
break;
} }
window.open(curRoute.href, "_blank");
}; };
const riskSignalActiveIndex = ref(0);
const riskSignalsRef = ref(null); // 引用risk-signals容器 const riskSignalsRef = ref(null); // 引用risk-signals容器
let intervalId; let intervalId;
let timer1;
let timer2;
onMounted(async () => { onMounted(async () => {
await handleGetLatestRiskUpdates(); await handleGetLatestRiskUpdates();
await handleGetLatestRisks(); await handleGetLatestRisks();
// console.log("cardList1111111", cardList1.value);
timer1 = setInterval(() => {
if (cardList1.value.length) {
if (cardShowIndex1.value < cardList1.value.length - 1) {
cardShowIndex1.value++;
cardBottomInfo.value[0].type = cardList1.value[cardShowIndex1.value].type;
cardBottomInfo.value[0].id = cardList1.value[cardShowIndex1.value].id;
cardBottomInfo.value[0].title = cardList1.value[cardShowIndex1.value].title;
cardBottomInfo.value[0].date = cardList1.value[cardShowIndex1.value].date;
} else {
cardShowIndex1.value = 0;
cardBottomInfo.value[0].type = cardList1.value[cardShowIndex1.value].type;
cardBottomInfo.value[0].id = cardList1.value[cardShowIndex1.value].id;
cardBottomInfo.value[0].title = cardList1.value[cardShowIndex1.value].title;
cardBottomInfo.value[0].date = cardList1.value[cardShowIndex1.value].date;
}
}
if (cardList2.value.length) {
if (cardShowIndex2.value < cardList2.value.length - 1) {
cardShowIndex2.value++;
cardBottomInfo.value[1].type = cardList2.value[cardShowIndex2.value].type;
cardBottomInfo.value[1].id = cardList2.value[cardShowIndex2.value].id;
cardBottomInfo.value[1].title = cardList2.value[cardShowIndex2.value].title;
cardBottomInfo.value[1].date = cardList2.value[cardShowIndex2.value].date;
} else {
cardShowIndex2.value = 0;
cardBottomInfo.value[1].id = cardList2.value[0].id;
cardBottomInfo.value[1].type = cardList2.value[0].type;
cardBottomInfo.value[1].title = cardList2.value[0].title;
cardBottomInfo.value[1].date = cardList2.value[0].date;
}
}
if (cardList3.value.length) {
if (cardShowIndex3.value < cardList3.value.length - 1) {
cardShowIndex3.value++;
cardBottomInfo.value[2].type = cardList3.value[cardShowIndex3.value].type;
cardBottomInfo.value[2].id = cardList3.value[cardShowIndex3.value].id;
cardBottomInfo.value[2].title = cardList3.value[cardShowIndex3.value].title;
cardBottomInfo.value[2].date = cardList3.value[cardShowIndex3.value].date;
} else {
cardShowIndex3.value = 0;
cardBottomInfo.value[2].type = cardList3.value[0].type;
cardBottomInfo.value[2].id = cardList3.value[0].id;
cardBottomInfo.value[2].title = cardList3.value[0].title;
cardBottomInfo.value[2].date = cardList3.value[0].date;
}
}
if (cardList4.value.length) {
if (cardShowIndex4.value < cardList4.value.length - 1) {
cardShowIndex4.value++;
cardBottomInfo.value[3].type = cardList4.value[cardShowIndex4.value].type;
cardBottomInfo.value[3].id = cardList4.value[cardShowIndex4.value].id;
cardBottomInfo.value[3].title = cardList4.value[cardShowIndex4.value].title;
cardBottomInfo.value[3].date = cardList4.value[cardShowIndex4.value].date;
} else {
cardShowIndex4.value = 0;
cardBottomInfo.value[3].type = cardList4.value[0].type;
cardBottomInfo.value[3].id = cardList4.value[0].id;
cardBottomInfo.value[3].title = cardList4.value[0].title;
cardBottomInfo.value[3].date = cardList4.value[0].date;
}
}
// console.log('cardBottomInfo',cardBottomInfo.value[0].title);
}, 3000);
timer2 = setInterval(() => {
if (riskSignalActiveIndex.value < warningList.value.length - 1) {
riskSignalActiveIndex.value++;
} else {
riskSignalActiveIndex.value = 0;
}
currentHoveredSignalId.value = warningList.value[riskSignalActiveIndex.value].signalId;
}, 3000);
const scrollInterval = 2000; // 每隔2秒滚动一次 const scrollInterval = 2000; // 每隔2秒滚动一次
let currentScroll = 0; let currentScroll = 0;
...@@ -593,6 +984,8 @@ onMounted(async () => { ...@@ -593,6 +984,8 @@ onMounted(async () => {
}); });
onUnmounted(() => { onUnmounted(() => {
clearInterval(intervalId); // 清除定时器 clearInterval(intervalId); // 清除定时器
clearInterval(timer1); // 清除定时器
clearInterval(timer2); // 清除定时器
}); });
// onBeforeUnmount(() => { // onBeforeUnmount(() => {
// andleGetLatestRiskUpdates() // andleGetLatestRiskUpdates()
...@@ -788,6 +1181,7 @@ onUnmounted(() => { ...@@ -788,6 +1181,7 @@ onUnmounted(() => {
line-height: 24px; line-height: 24px;
letter-spacing: 0px; letter-spacing: 0px;
text-align: left; text-align: left;
cursor: pointer;
.bottm-box-text { .bottm-box-text {
white-space: nowrap; white-space: nowrap;
...@@ -991,6 +1385,7 @@ onUnmounted(() => { ...@@ -991,6 +1385,7 @@ onUnmounted(() => {
top: 200px; top: 200px;
width: 24px; width: 24px;
height: 48px; height: 48px;
cursor: pointer;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
...@@ -1003,6 +1398,7 @@ onUnmounted(() => { ...@@ -1003,6 +1398,7 @@ onUnmounted(() => {
top: 200px; top: 200px;
width: 24px; width: 24px;
height: 48px; height: 48px;
cursor: pointer;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
......
...@@ -26,119 +26,54 @@ ...@@ -26,119 +26,54 @@
<div class="page-content"> <div class="page-content">
<div class="left"> <div class="left">
<custom-container style="margin-bottom: 16px" block title="新闻内容" :titleIcon="houseIcon" height="1180px"> <div class="box1">
<template #header-right> <div class="box-header">
<div class="page-content-right-switch"> <div class="icon"></div>
<div class="title">{{ "新闻内容" }}</div>
<div class="header-right">
<el-switch v-model="highlightEntities" /> <el-switch v-model="highlightEntities" />
高亮实体 高亮实体
</div> </div>
<el-button type="primary" @click="handleToDetail"> 译文 </el-button> </div>
</template> <div class="box1-main">
<div class="main-header">
<template #default> <div class="main-header-left">{{ "原文" }}</div>
<!-- 内容区域 - 分三块--> <div class="main-header-center"></div>
<!-- <div class="page-content-news-abstract"> <div class="main-header-right">
<div class="news-abstract-header"> <div class="text">{{ "展开" }}</div>
<img src="./assets/images/abstract-header.png" alt="" /> <div class="icon">
</div> <img src="./assets/images/arrow-down.png" alt="" />
<div class="news-abstract-content"> </div>
{{
" 美国众议院共和党人正在起草一项新提案,以限制美国对中国的投资。此前,参议院已将其纳入国防政策立法中。知情人士向Semafor透露,众议院工作人员希望在11月7日前就该提案达成共识,并将财政部的反馈纳入由肯塔基州共和党众议员安迪·巴尔提出的配套提案中(尽管政府停摆可能推迟这一时间表)。随后,众议员将利用该文本与参议员就最终《国防授权法案》的内容进行协商。此前一届国会中,类似的尝试因北卡罗来纳州前众议员帕特里克·麦克亨利的反对而失败,但本届国会中,“所有人都在共同努力”。知情人士补充说,领导人并不担心此举会剥夺特朗普在周四与中国领导人习近平会谈时的谈判筹码,因为财政部已开始实施类似的指导方针。"
}}
</div>
</div> -->
<div class="page-content-news-artical">
<div class="page-content-news-artical-zn">
{{ newsContentInfo.newsContent }}
<!-- <p>
<span class="highlight">华盛顿邮报</span>报道,了解谈判情况的知情人士透露,<span
class="highlight"
>美国众议院</span
><span class="highlight">共和党人</span
>正在起草一项新的提案,以限制美国对华投资。目前<span class="highlight">参议院</span
>已将其相关法案作为国防政策立法的一部分通过。
</p>
<p>
谈判各方希望能在11月7日前就这项措施的文本达成共识(尽管政府停摆、可能推迟这一日期)。该措施已将财政部的反馈意见纳入<span
class="highlight"
>肯塔基州</span
><span class="highlight">共和党众议员</span
><span class="highlight">安迪·巴尔</span><span class="highlight">配套提案中</span>
</p>
<p>
此后,<span class="highlight">国会议员</span
>们将利用这份文本来与参议员进行协商,以决定哪些内容能最终纳入定版的《国防授权法案》中。
</p>
<p>
在上届国会期间,类似的立法尝试曾因<span class="highlight">北卡罗来纳州</span><span
class="highlight"
>共和党前众议员</span
><span class="highlight">帕特里克·麦克亨利</span>的反对而失败。但在本届国会中,<span
class="highlight"
>一位知情人士</span
>表示,"现在所有人实际上都在共同努力"。
</p>
<p>
该人士还补充说,领导层并不担心此举会剥夺<span class="highlight">特朗普</span
><span class="highlight">总统</span>的一个谈判工具。
</p> -->
</div>
<div class="page-content-news-artical-en">
<!-- <p class="indented-paragraph">
<span class="highlight">House Republicans</span> are drafting a fresh proposal to curb US
investments in China after the <span class="highlight">Senate</span> passed its bill as
part of defense policy legislation, people familiar with the talks told Semafor.
</p>
<p class="indented-paragraph">
Staff hope to reach consensus on the measure, which incorporates
<span class="highlight">Treasury Department</span> feedback into a companion proposal from
Rep. <span class="highlight">Andy Barr</span>, R-Ky., by
<span class="highlight">Nov. 7</span> (though the shutdown could delay that date).
</p>
<p class="indented-paragraph">
Members will then use that text to negotiate with senators over what makes it into the
final <span class="highlight">National Defense Authorization Act</span>.
</p>
<p class="indented-paragraph">
Last Congress, similar attempts to add language implored amid pushback from former Rep.
<span class="highlight">Patrick McHenry</span>, R-N.C.; this Congress, "everyone's
actually working together" now, one of the people said.
</p>
<p class="indented-paragraph">
They added that leaders are unconcerned about depriving
<span class="highlight">Trump</span> of a negotiating tool in talks with Chinese leader
<span class="highlight">Xi Jinping</span> on Thursday because
<span class="highlight">Treasury</span> is already implementing parallel guidance.
</p> -->
</div> </div>
</div> </div>
<div class="main-content">
<div class="page-content-news-img"> <!-- {{ newsContentInfo.newsContent }} -->
<img :src="newsContentInfo.newsImage" alt="新闻图片"> {{
<!-- <el-image :src="newsContentInfo.newsImage" alt="新闻图片" fit="contain" /> --> ` 据华盛顿邮报报道,了解谈判情况的知情人士透露,美国众议院 共和党人正在起草一项新的提案,以限制美国对华投资。目前参议院 已将其相关法案作为国防政策立法的一部分通过。
<!-- <el-image :src="newsImg2" alt="新闻图片" fit="contain" /> 谈判各方希望能在11月7日前就这项措施的文本达成共识(尽管政府停摆 可能推迟这一日期)。该措施已将财政部的反馈意见纳入肯塔基州 共和党众议员安迪·巴尔 的配套提案中。
<el-image :src="newsImg3" alt="新闻图片" fit="contain" /> --> 此后,议员们将利用这份文本来与参议员进行协商,以决定哪些内容能最终纳入定版的《国防授权法案》 中。
在上届国会期间,类似的立法尝试曾因北卡罗来纳州 共和党前众议员帕特里克·麦克亨利 的反对而失败。但在本届国会中,一位知情人士表示,“现在所有人实际上都在共同努力”。
该人士还补充说,领导层并不担心此举会剥夺特朗普 总统的一个谈判工具。`
}}
</div> </div>
</template> <div class="main-img-box">
</custom-container> <img :src="newsContentInfo.newsImage" alt="新闻图片" />
</div>
</div>
</div>
</div> </div>
<div class="right"> <div class="right">
<custom-container block title="相关新闻" :titleIcon="houseIcon" height="400px"> <div class="box2">
<template #default> <div class="box-header">
<div class="icon"></div>
<div class="title">{{ "相关新闻" }}</div>
</div>
<div class="box2-main">
<div class="news-list"> <div class="news-list">
<NewsList :list-data="customNewsData" /> <NewsList :list-data="customNewsData" />
</div> </div>
</template> </div>
</custom-container> </div>
</div> </div>
</div> </div>
</div> </div>
...@@ -150,16 +85,10 @@ import { useRoute } from "vue-router"; ...@@ -150,16 +85,10 @@ import { useRoute } from "vue-router";
import { getNewsSummary, getNewsContent, getNewsEvent, getRelationNews } from "@/api/news/newsDetail"; import { getNewsSummary, getNewsContent, getNewsEvent, getRelationNews } from "@/api/news/newsDetail";
import CustomContainer from "@/components/Container/index.vue"; import CustomContainer from "@/components/Container/index.vue";
import NewsList from "@/views/exportControl/components/news.vue"; import NewsList from "@/views/exportControl/components/news.vue";
import Graph from "./relation.vue";
import newsImg from "@/assets/images/img-news.png"; import newsImg from "@/assets/images/img-news.png";
import openIcon from "@/assets/images/icon-open.png"; import openIcon from "@/assets/images/icon-open.png";
import dotIcon from "@/assets/images/dot.png"; import dotIcon from "@/assets/images/dot.png";
import newsImg1 from "@/assets/images/news-image-1.png";
import newsImg2 from "@/assets/images/news-image-2.png";
import newsImg3 from "@/assets/images/news-image-3.png";
import newsImg4 from "@/assets/images/news-img.png";
const route = useRoute(); const route = useRoute();
const summaryInfo = ref({ const summaryInfo = ref({
...@@ -258,36 +187,7 @@ const handleGetNewsEvent = async () => { ...@@ -258,36 +187,7 @@ const handleGetNewsEvent = async () => {
}; };
// 相关新闻 // 相关新闻
const customNewsData = ref([ const customNewsData = ref([]);
{
image: newsImg4,
title: "市场因结束美国政府关门协议的希望而提振",
time: "",
source: "",
description: "2017-08-30 · Channel NewsAsia..."
},
{
image: newsImg4,
title: "市场因结束美国政府关门协议的希望而提振",
time: "",
source: "",
description: "2017-08-30 · Channel NewsAsia..."
},
{
image: newsImg4,
title: "市场因结束美国政府关门协议的希望而提振",
time: "",
source: "",
description: "2017-08-30 · Channel NewsAsia..."
},
{
image: newsImg4,
title: "市场因结束美国政府关门协议的希望而提振",
time: "",
source: "",
description: "2017-08-30 · Channel NewsAsia..."
}
]);
const handleGetRelationNews = async () => { const handleGetRelationNews = async () => {
const params = { const params = {
newsId: route.query.newsId newsId: route.query.newsId
...@@ -314,7 +214,6 @@ onMounted(() => { ...@@ -314,7 +214,6 @@ onMounted(() => {
<style scoped lang="scss"> <style scoped lang="scss">
.page-container { .page-container {
/* padding: 20px; */
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
...@@ -322,7 +221,10 @@ onMounted(() => { ...@@ -322,7 +221,10 @@ onMounted(() => {
} }
.page-header { .page-header {
position: sticky;
top: 0;
display: flex; display: flex;
z-index: 9999;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 120px; height: 120px;
...@@ -416,155 +318,130 @@ onMounted(() => { ...@@ -416,155 +318,130 @@ onMounted(() => {
padding: 20px 160px; padding: 20px 160px;
display: flex; display: flex;
gap: 17px; gap: 17px;
.left { .box-header {
width: 1063px; height: 50px;
} display: flex;
.right { position: relative;
width: 520px; .icon {
} margin-top: 18px;
&-news-abstract { width: 8px;
height: 260px; height: 20px;
width: 100%; border-radius: 0 4px 4px 0;
padding: 10px; background: var(--color-main-active);
background: linear-gradient(to bottom, rgba(246, 250, 255, 1), rgba(246, 250, 255, 0));
font-size: 16px;
font-weight: 400;
line-height: 30px;
border-radius: 4px;
border: 1px solid rgba(246, 250, 255, 1);
text-indent: 2em;
.news-abstract-header {
margin-top: 6px;
width: 135px;
height: 32px;
img {
width: 100%;
height: 100%;
}
} }
.news-abstract-content { .title {
margin-top: 16px; margin-top: 14px;
font-family: Microsoft YaHei; margin-left: 14px;
font-style: Regular; height: 26px;
font-size: 16px; color: var(--color-main-active);
font-weight: 400; font-family: Source Han Sans CN;
line-height: 30px; font-style: Bold;
font-size: 20px;
font-weight: 700;
line-height: 26px;
letter-spacing: 0px; letter-spacing: 0px;
text-align: justify; text-align: left;
}
}
&-news-artical {
// height: 480px;
margin-top: 16px;
line-height: 1.8;
color: #303133;
// display: flex;
// align-items: flex-start;
// justify-content: space-between;
gap: 25px;
&-zn,
&-en {
width: 100%;
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
}
p {
text-align: justify;
text-indent: 2em; /* 段落开头缩进2个字符 */
margin-bottom: -1px;
line-height: 28px;
} }
.highlight { .header-right {
color: rgba(5, 95, 194, 1); /* 指定的蓝色高亮 */ position: absolute;
font-weight: 500; top: 18px;
right: 37px;
} }
} }
.left {
&-news-img { width: 1063px;
height: 370px; .box1 {
// border-top: 1px solid rgba(234, 236, 238, 1); width: 1063px;
padding: 15px 10px; height: 865px;
display: flex; border: 1px solid rgba(234, 236, 238, 1);
align-items: center; border-radius: 10px;
justify-content: center; background: rgba(255, 255, 255, 1);
gap: 20px; .box1-main {
overflow: hidden; width: 992px;
overflow-y: auto; margin: 0 auto;
img{ .main-header {
height: 100%; width: 992px;
width: auto; margin-top: 22px;
}
}
.box4 {
.box4-item {
display: flex;
gap: 10px;
align-items: flex-start;
padding-bottom: 30px;
.box4-item-left {
display: flex;
flex-direction: column;
align-items: center;
padding-top: 8px;
position: relative;
.box4-item-left-icon {
width: 10px;
height: 10px;
}
.box4-item-left-line {
width: 1px;
height: 120px;
position: absolute;
top: 15px;
border-left: 1px solid rgba(10, 87, 166, 0.3);
}
}
.box4-item-right {
display: flex;
flex-direction: column;
gap: 5px;
.box4-item-right-header {
display: flex; display: flex;
justify-content: space-between;
align-items: center; align-items: center;
padding-bottom: 12px; height: 24px;
border-bottom: 1px solid rgba(234, 236, 238, 1); .main-header-left {
&-title { width: 36px;
width: 60%; height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 16px;
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
font-family: Source Han Sans CN;
font-style: Bold;
font-size: 18px;
font-weight: 700; font-weight: 700;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
} }
&-desc { .main-header-center {
font-size: 14px; margin-left: 12px;
font-weight: 400; width: 878px;
color: rgba(95, 101, 108, 1); height: 1px;
background: rgba(234, 236, 238, 1);
}
.main-header-right {
display: flex;
gap: 12px;
margin-left: 12px;
.text {
width: 32px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Source Han Sans CN;
font-style: Regular;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
.icon {
width: 10px;
height: 5px;
img {
width: 100%;
height: 100%;
}
}
} }
} }
.box4-item-right-content { .main-content {
// margin-top: 10px; margin-top: 22px;
font-family: Source Han Sans CN;
font-style: Regular;
font-size: 16px; font-size: 16px;
color: rgb(59, 65, 75);
font-weight: 400; font-weight: 400;
color: rgba(95, 101, 108, 1); line-height: 30px;
overflow: hidden; letter-spacing: 0px;
display: -webkit-box; text-align: justify;
-webkit-line-clamp: 2; }
-webkit-box-orient: vertical; .main-img-box {
text-overflow: ellipsis; margin-top: 30px;
height: 48px; display: flex;
line-height: 24px; justify-content: center;
flex-wrap: wrap;
img {
height: 240px;
width: auto;
}
} }
} }
} }
} }
.right {
width: 520px;
.box2 {
width: 520px;
height: 400px;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
background: rgba(255, 255, 255, 1);
}
}
} }
</style> </style>
<!-- src/components/HuaweiSupplyChainChart.vue -->
<template>
<div class="chart-container" ref="chartRef"></div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import * as echarts from "echarts";
// import { graphData } from "./mockData";
import Img from "./assets/images/img.png";
import Img1 from "./assets/images/img1.png";
import Img2 from "./assets/images/img2.png";
import Img3 from "./assets/images/img3.png";
import Img4 from "./assets/images/img4.png";
import Img5 from "./assets/images/img5.png";
import Img6 from "./assets/images/img6.png";
import Img7 from "./assets/images/img7.png";
import Img8 from "./assets/images/img8.png";
const graphData = {
nodes: [
{ id: "huawei", name: "美国众议院", category: 0, symbolSize: 60, symbol: `image://${Img}` },
{ id: "foxconn", name: "唐纳德·特朗普", category: 1, symbolSize: 42, symbol: `image://${Img1}` },
{ id: "huawei-cloud", name: "约翰·斯奎尔斯", category: 2, symbolSize: 42, symbol: `image://${Img2}` },
{ id: "huawei-digital-energy", name: "马尔科·卢比奥", category: 2, symbolSize: 42, symbol: `image://${Img3}` },
{ id: "huawei-intelligent-car", name: "埃隆·马斯克", category: 2, symbolSize: 42, symbol: `image://${Img4}` },
{ id: "qualcomm", name: "道格·伯格姆", category: 2, symbolSize: 42, symbol: `image://${Img5}` },
{ id: "intel", name: "斯科特·贝森特", category: 2, symbolSize: 42, symbol: `image://${Img6}` },
{ id: "mediatek", name: "杰弗里·凯斯勒", category: 2, symbolSize: 42, symbol: `image://${Img7}` },
{ id: "shenghongda", name: "杰弗里·凯德勒", category: 2, symbolSize: 42, symbol: `image://${Img8}` }
// { id: "luxshare", name: "立讯精密", category: 1, symbolSize: 20 },
// { id: "tianma", name: "天马微电子", category: 1, symbolSize: 20 },
// { id: "desay", name: "德赛电池", category: 1, symbolSize: 20 },
// { id: "auspicious-sound", name: "瑞声科技", category: 1, symbolSize: 20 },
// { id: "goertek", name: "歌尔股份", category: 1, symbolSize: 20 },
// { id: "sony-semiconductor", name: "索尼半导体", category: 1, symbolSize: 20 },
// { id: "ibm", name: "IBM", category: 1, symbolSize: 20 },
// { id: "lg-innotek", name: "LG伊诺特", category: 1, symbolSize: 20 },
// { id: "micron", name: "美光科技", category: 1, symbolSize: 20 }
// { id: "nokia", name: "诺基亚", category: 1, symbolSize: 20 },
// { id: "google", name: "谷歌", category: 1, symbolSize: 20 },
// { id: "vodafone", name: "沃达丰", category: 1, symbolSize: 20 },
// { id: "microsoft", name: "微软", category: 1, symbolSize: 20 },
// { id: "china-unicom", name: "中国联通", category: 1, symbolSize: 20 },
// { id: "china-mobile", name: "中国移动", category: 1, symbolSize: 20 },
// { id: "tsmc", name: "台积电", category: 1, symbolSize: 20 }
// { id: "orange", name: "Orange", category: 1, symbolSize: 20 },
// { id: "germany-telecom", name: "德国电信", category: 1, symbolSize: 20 },
// { id: "byd-electronics", name: "比亚迪电子", category: 1, symbolSize: 20 },
// { id: "boe", name: "京东方", category: 1, symbolSize: 20 },
// { id: "dali-optical", name: "大力光", category: 1, symbolSize: 20 },
// { id: "lg-display", name: "LG显示", category: 1, symbolSize: 20 },
// { id: "sunny-optical", name: "舜宇光学", category: 1, symbolSize: 20 }
],
links: [
{ source: "huawei", target: "huawei-cloud" },
{ source: "huawei", target: "huawei-digital-energy" },
{ source: "huawei", target: "huawei-intelligent-car" },
{ source: "huawei", target: "qualcomm" },
{ source: "huawei", target: "intel" },
{ source: "huawei", target: "mediatek" },
{ source: "huawei", target: "shenghongda" },
{ source: "huawei", target: "foxconn" }
// { source: "huawei", target: "luxshare" },
// { source: "huawei", target: "tianma" },
// { source: "huawei", target: "desay" },
// { source: "huawei", target: "auspicious-sound" },
// { source: "huawei", target: "goertek" },
// { source: "huawei", target: "sony-semiconductor" },
// { source: "huawei", target: "ibm" },
// { source: "huawei", target: "lg-innotek" },
// { source: "huawei", target: "micron" }
// { source: "huawei", target: "nokia" },
// { source: "huawei", target: "google" },
// { source: "huawei", target: "vodafone" },
// { source: "huawei", target: "microsoft" },
// { source: "huawei", target: "china-unicom" },
// { source: "huawei", target: "china-mobile" },
// { source: "huawei", target: "tsmc" }
// { source: "huawei", target: "orange" },
// { source: "huawei", target: "germany-telecom" },
// { source: "huawei", target: "byd-electronics" },
// { source: "huawei", target: "boe" },
// { source: "huawei", target: "dali-optical" },
// { source: "huawei", target: "lg-display" },
// { source: "huawei", target: "sunny-optical" }
],
categories: [{ name: "子业务" }, { name: "合作商" }]
};
const chartRef = ref(null);
onMounted(() => {
const chart = echarts.init(chartRef.value);
const option = {
title: { text: "", left: "center" },
tooltip: {},
// legend: {
// data: graphData.categories.map(item => item.name),
// left: "left"
// },
series: [
{
type: "graph",
layout: "force", // 力导向布局
force: {
repulsion: 1000, // 节点排斥力
edgeLength: [50, 200] // 边长度范围
},
data: graphData.nodes,
links: graphData.links,
categories: graphData.categories,
roam: true, // 支持缩放、平移
label: {
show: true,
fontSize: 14,
position: "bottom",
formatter: function (params) {
// 根据条件返回不同样式的文本
if (params.data.category === 0) {
return `{a|${params.name}}`; // 使用富文本样式
} else if (params.data.category === 1) {
return `{b|${params.name}}`;
} else {
return params.name; // 默认样式
}
},
rich: {
a: {
// 重要节点的样式
color: "#000",
fontSize: 18,
fontWeight: "bold",
padding: [2, 4],
borderRadius: 2
},
b: {
// 普通节点的样式
color: "rgba(5, 95, 194, 1)",
fontSize: 14,
}
}
},
edgeSymbol: ["arrow", "none"], // 边的箭头
edgeSymbolSize: [8, 50],
itemStyle: {
color: "rgba(5, 95, 194, 1)"
// borderColor: "red",
// borderWidth: 1
},
lineStyle: {
color: "rgba(174, 214, 255, 1)",
width: 2,
opacity: 0.5
},
emphasis: {
focus: "adjacency",
lineStyle: {
width: 2
}
}
}
]
};
chart.setOption(option);
// 窗口resize时自适应
window.addEventListener("resize", () => chart.resize());
});
</script>
<style scoped>
.chart-container {
width: 100%;
height: 430px;
margin: 0 auto;
background-color: #f7f8f9; /* 深色背景,模拟原图风格 */
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论