提交 78d38246 authored 作者: coderBryanFu's avatar coderBryanFu

feat:新增数据资源库模块,新增时间选择框通用组件

......@@ -213,3 +213,18 @@ export const countryCoordMap = {
法属波利尼西亚: [-149.5986, -17.6797], // 法属波利尼西亚帕皮提
"新喀里多尼亚(法)": [166.4572, -21.5547] // 新喀里多尼亚努美阿
};
export function convertAsiaCenterCoord(coord) {
const [lng, lat] = coord;
// 将以本初子午线为基准的坐标转换为以亚洲为中心的坐标
// world-asia-center.json 是将标准坐标的经度减去了 180 度
let newLng = lng - 180;
// 规范化到 [-180, 180] 范围
if (newLng < -180) {
newLng += 360;
}
return [newLng, lat];
}
<template>
<div class="layout-container">
<div class="layout-main">
<div class="layout-main-center">
<div class="report-header">
<div class="report-title">政令原文</div>
<el-switch v-model="isHighlight" />
<div class="switch-label switch-label-left">高亮实体</div>
<el-switch v-model="isTranslate" />
<div class="switch-label">原文显示</div>
<div
v-for="action in headerActions"
:key="action.key"
class="btn"
@click="action.onClick"
>
<div :class="['icon', action.iconGapClass]">
<img :src="action.icon" alt="" />
</div>
<div class="text">{{ action.text }}</div>
</div>
<div class="find-word-box" v-if="findWordBox">
<div class="find-word-input">
<el-input
v-model="findWordTxt"
placeholder="查找原文内容"
@input="handleUpdateWord"
/>
</div>
<div class="find-word-limit">{{ findWordNum }}/{{ findWordMax }}</div>
<div class="find-word-icon" @click="handleFindWord('last')">
<el-icon><ArrowUp /></el-icon>
</div>
<div class="find-word-icon" @click="handleFindWord('next')">
<el-icon><ArrowDown /></el-icon>
</div>
<div class="find-word-icon" @click="handleFindWord('close')">
<el-icon><Close /></el-icon>
</div>
</div>
</div>
<div class="report-main">
<div v-if="!displayReportData.length" class="no-content">暂无数据</div>
<el-scrollbar v-else height="100%">
<div
v-for="item in displayReportData"
:key="item.num"
class="content-row"
:class="{ 'high-light': isHighlight }"
>
<div class="content-cn" :class="{ 'translate-cn': !isTranslate }" v-html="item.content" />
<div v-if="isTranslate" class="content-en" v-html="item.contentEn" />
</div>
</el-scrollbar>
</div>
</div>
</div>
</div>
</template>
<script setup>
import defaultDownloadIcon from "./assets/icons/download.png";
import defaultSearchIcon from "./assets/icons/search.png";
import { nextTick, ref, watch } from "vue";
import { debounce } from "lodash";
const props = defineProps({
reportData: { type: Array, default: () => [] },
});
const emits = defineEmits(["download"]);
const isHighlight = ref(false);
const isTranslate = ref(true);
const findWordTxt = ref("");
const findWordBox = ref(false);
const findWordNum = ref(0);
const findWordMax = ref(0);
const originReportData = ref([]);
const displayReportData = ref([]);
const headerActions = [
{
key: "download",
text: "下载",
icon: defaultDownloadIcon,
iconGapClass: "icon-gap-4",
onClick: () => emits("download"),
},
{
key: "search",
text: "查找",
icon: defaultSearchIcon,
iconGapClass: "icon-gap-6",
onClick: () => handleFindWord("open"),
},
];
function escapeRegExp(text) {
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function applyHighlightToText(text, searchTerm) {
if (!text || !searchTerm) {
return { html: text || "", count: 0 };
}
const escapedTerm = escapeRegExp(searchTerm);
let count = 0;
const html = String(text).replace(new RegExp(escapedTerm, "g"), (match) => {
count += 1;
return `<span class="highlight">${match}</span>`;
});
return { html, count };
}
function setDisplayFromOrigin() {
displayReportData.value = originReportData.value.map((item) => ({
...item,
content: item.content || "",
contentEn: item.contentEn || "",
}));
}
function updateActiveHighlight() {
const spans = document.querySelectorAll("span.highlight");
spans.forEach((span, index) => {
if (index + 1 === findWordNum.value) {
span.scrollIntoView({});
span.style.backgroundColor = "#ff9632";
} else {
span.style.backgroundColor = "#ffff00";
}
});
}
const doUpdateWord = () => {
findWordNum.value = 0;
findWordMax.value = 0;
const term = findWordTxt.value?.trim();
if (!term) {
setDisplayFromOrigin();
return;
}
displayReportData.value = originReportData.value.map((item) => {
const cn = applyHighlightToText(item.content, term);
const en = isTranslate.value
? applyHighlightToText(item.contentEn, term)
: { html: item.contentEn, count: 0 };
findWordMax.value += cn.count + en.count;
return {
...item,
content: cn.html,
contentEn: en.html,
};
});
if (findWordMax.value > 0) {
nextTick(() => {
findWordNum.value = 1;
updateActiveHighlight();
});
}
};
const handleUpdateWord = debounce(() => {
doUpdateWord();
}, 300);
function handleFindWord(event) {
switch (event) {
case "open":
findWordBox.value = true;
break;
case "last":
if (findWordMax.value > 1) {
findWordNum.value = findWordNum.value === 1 ? findWordMax.value : findWordNum.value - 1;
updateActiveHighlight();
}
break;
case "next":
if (findWordMax.value > 1) {
findWordNum.value = findWordNum.value === findWordMax.value ? 1 : findWordNum.value + 1;
updateActiveHighlight();
}
break;
case "close":
findWordBox.value = false;
findWordTxt.value = "";
doUpdateWord();
break;
}
}
watch(
() => props.reportData,
(val) => {
originReportData.value = (val || []).map((item) => ({
content: item?.content || "",
contentEn: item?.contentEn || "",
num: item?.num,
}));
setDisplayFromOrigin();
doUpdateWord();
},
{ deep: true, immediate: true },
);
watch(isTranslate, () => {
doUpdateWord();
});
</script>
<style lang="scss" scoped>
.high-light {
:deep(span.highlight) {
background-color: #ffff00;
}
}
.layout-container {
width: 100%;
height: 100%;
background-color: #f7f8f9;
.layout-main {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
.layout-main-center {
width: 1600px;
background-color: white;
padding: 0 60px;
flex: auto;
display: flex;
flex-direction: column;
.report-header {
height: 80px;
display: flex;
align-items: center;
border-bottom: solid 1px rgba(234, 236, 238, 1);
margin: 0 20px 10px;
position: relative;
.find-word-box {
position: absolute;
top: -50px;
right: 0px;
width: 430px;
height: 60px;
border: 1px solid rgba(230, 231, 232, 1);
background-color: white;
border-radius: 6px;
display: flex;
align-items: center;
.find-word-input {
flex: auto;
}
.find-word-limit {
border-right: solid 1px rgba(230, 231, 232, 1);
color: #5f656c;
padding-right: 16px;
}
.find-word-icon {
padding: 10px 12px;
margin: 0 2px;
cursor: pointer;
}
}
.report-title {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
line-height: 20px;
font-weight: 700;
flex: 1;
}
.btn {
margin-left: 10px;
width: 88px;
height: 32px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 6px;
background: rgba(255, 255, 255, 1);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.text {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 14px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
.icon {
width: 16px;
height: 16px;
font-size: 0px;
img {
width: 100%;
height: 100%;
}
}
.icon-gap-4 {
margin-right: 4px;
}
.icon-gap-6 {
margin-right: 6px;
}
}
}
.report-main {
flex: auto;
box-sizing: border-box;
padding-top: 10px;
.no-content {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 20px;
font-weight: 400;
}
.content-row {
display: flex;
width: 100%;
padding: 0 20px;
min-height: 100px;
gap: 80px;
.content-en,
.content-cn {
width: 50%;
flex: auto;
padding-bottom: 40px;
box-sizing: border-box;
font-size: 16px;
line-height: 1.8;
color: #3b414b;
font-family: Microsoft YaHei;
text-align: justify;
white-space: pre-wrap;
}
.translate-cn {
padding-bottom: 10px;
}
}
}
}
}
}
.switch-label {
margin-left: 6px;
}
.switch-label-left {
margin-right: 10px;
}
:deep(.el-scrollbar__bar.is-vertical) {
right: 0px;
width: 4px;
background: transparent;
border-radius: 2px;
& > div {
background: #c5c7c9;
opacity: 1;
}
& > div:hover {
background: #505357;
}
}
</style>
import 'echarts-wordcloud';
import { MUTICHARTCOLORS } from '@/common/constant';
const getWordCloudChart = (data) => {
const option = {
const getWordCloudChart = data => {
const option = {
grid: {
left: 5,
top: 5,
......@@ -12,9 +12,9 @@ const getWordCloudChart = (data) => {
series: [
{
type: "wordCloud",
shape: 'circle',
width: '100%',
height: '100%',
shape: "circle",
width: "100%",
height: "100%",
// 其他形状你可以使用形状路径
// shape: 'circle', // 示例
// 或者自定义路径
......@@ -27,39 +27,25 @@ const getWordCloudChart = (data) => {
shrinkToFit: true, // 是否自动缩小以适应容器
// 字体
textStyle: {
// normal: {
// color: function () {
// return 'rgb(' + [
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160)
// ].join(',') + ')';
// }
// },
color: function () {
// let colors = [
// "rgba(189, 33, 33, 1)",
// "rgba(232, 151, 21, 1)",
// "rgba(220, 190, 68, 1)",
// "rgba(96, 58, 186, 1)",
// "rgba(32, 121, 69, 1)",
// "rgba(22, 119, 255, 1)",
// ];
// let colors = MUTICHARTCOLORS
return MUTICHARTCOLORS[parseInt(Math.random() * MUTICHARTCOLORS.length)];
color: function (params) {
const colors = MUTICHARTCOLORS || [];
if (!colors.length) {
return "#69B1FF";
}
return colors[params.dataIndex % colors.length];
},
emphasis: {
shadowBlur: 5,
shadowColor: "#333",
},
shadowColor: "#333"
}
},
// 设置词云数据
data: data,
},
],
data
}
]
};
return option
}
return option;
};
export default getWordCloudChart
\ No newline at end of file
export default getWordCloudChart;
\ No newline at end of file
......@@ -588,22 +588,18 @@ function handleUnionItemClick(item) {
createUnionChart();
});
}
// ... existing code ...
// ... existing code ...
function createChart() {
// 如果没有数据,直接返回
if (!countryTotalList.value || countryTotalList.value.length === 0) {
console.error("No country data available");
return;
}
// 找到最大值用于颜色计算
const maxValue = Math.max(...countryTotalList.value.map(item => item.value));
console.log("全部国家数据 countryTotalList =>", countryTotalList.value);
// 为每个数据项计算颜色
const processedData = countryTotalList.value.map(item => {
const color = getColorByValueRandom(item.value, maxValue);
return {
......@@ -621,12 +617,12 @@ function createChart() {
};
});
// 构建基础地图配置
const option = {
geo: {
map: "world",
roam: true,
zoom: 1.2,
// center: [104.1954, 35.8617], // 设置地图中心点为中国
label: {
show: false
},
......@@ -687,7 +683,6 @@ function createChart() {
]
};
// 如果有选中的国家,添加关系线
if (
currentSelectedCountry.value &&
currentSelectedCountry.value.memberRelation &&
......@@ -698,8 +693,19 @@ function createChart() {
currentSelectedCountry.value.zhName ||
nameMap[currentSelectedCountry.value.name] ||
currentSelectedCountry.value.name;
const sourceCoord = countryCoordMap[sourceCountryName];
if (!sourceCoord) {
console.warn(`无法找到源国家 ${sourceCountryName} 的坐标`);
return;
}
console.log("=== 源国家信息 ===");
console.log("源国家名称:", sourceCountryName);
console.log("源国家坐标:", sourceCoord);
console.log("==================");
const validRelations = relations.filter(relation => {
return relation.tagetMemberName && relation.tagetMemberCount;
});
......@@ -711,10 +717,12 @@ function createChart() {
const targetPoints = [];
validRelations.forEach(relation => {
const targetCountry = relation.tagetMemberName;
const targetCoord = countryCoordMap[targetCountry];
const targetCountryZhName = relation.tagetMemberName;
const targetCoord = countryCoordMap[targetCountryZhName];
if (targetCoord) {
console.log(`目标国家:${targetCountryZhName}, 坐标:`, targetCoord);
const ratio = relation.tagetMemberCount / maxRelationCount;
const r = Math.round(5 + (255 - 5) * ratio);
const g = Math.round(95 + (77 - 95) * ratio);
......@@ -724,9 +732,9 @@ function createChart() {
const lineWidth = 1 + (relation.tagetMemberCount / maxRelationCount) * 7;
linesData.push({
name: `${sourceCountryName} - ${targetCountry}`,
name: `${sourceCountryName} - ${targetCountryZhName}`,
sourceName: sourceCountryName,
targetName: targetCountry,
targetName: targetCountryZhName,
coords: [sourceCoord, targetCoord],
value: relation.tagetMemberCount,
lineStyle: {
......@@ -737,13 +745,15 @@ function createChart() {
});
targetPoints.push({
name: targetCountry,
name: targetCountryZhName,
value: targetCoord,
symbolSize: 8 + (relation.tagetMemberCount / maxRelationCount) * 7,
itemStyle: {
color: lineColor
}
});
} else {
console.warn(`无法找到目标国家 ${targetCountryZhName} 的坐标`);
}
});
......@@ -795,244 +805,29 @@ function createChart() {
// ... existing code ...
// ... existing code ...
// 处理国家列表项点击事件
// 在 handleCountryClick 中添加调试代码
const handleCountryClick = country => {
currentSelectedCountry.value = country;
console.log("国家之间的关系 =>", country);
console.log("=== 点击的国家信息 ===");
console.log("国家中文名:", country.zhName);
console.log("国家英文名:", country.name);
// 检查坐标映射
const coordFromZhName = countryCoordMap[country.zhName];
const coordFromEnName = countryCoordMap[country.name];
const coordFromMappedName = countryCoordMap[nameMap[country.name]];
console.log("通过中文名获取坐标:", coordFromZhName);
console.log("通过英文名获取坐标:", coordFromEnName);
console.log("通过映射名获取坐标:", coordFromMappedName);
console.log("=====================");
nextTick(() => {
createChart();
});
};
const countryMock = {
name: "Australia",
ename: "Commonwealth of Australia",
image: "http://8.140.26.4:10010/kjb-files/images/cr_flag/AUS.jpg",
count: 7,
memberRelation: [
{
tagetMemberName: "美国",
tagetMemberCount: 7
},
{
tagetMemberName: "英国",
tagetMemberCount: 6
},
{
tagetMemberName: "日本",
tagetMemberCount: 5
},
{
tagetMemberName: "韩国",
tagetMemberCount: 4
},
{
tagetMemberName: "印度",
tagetMemberCount: 4
},
{
tagetMemberName: "新西兰",
tagetMemberCount: 3
},
{
tagetMemberName: "加拿大",
tagetMemberCount: 3
},
{
tagetMemberName: "挪威",
tagetMemberCount: 2
},
{
tagetMemberName: "德国",
tagetMemberCount: 2
},
{
tagetMemberName: "法国",
tagetMemberCount: 2
},
{
tagetMemberName: "意大利",
tagetMemberCount: 2
},
{
tagetMemberName: "荷兰",
tagetMemberCount: 2
},
{
tagetMemberName: "芬兰",
tagetMemberCount: 2
},
{
tagetMemberName: "瑞典",
tagetMemberCount: 2
},
{
tagetMemberName: "爱沙尼亚",
tagetMemberCount: 2
},
{
tagetMemberName: "新加坡",
tagetMemberCount: 2
},
{
tagetMemberName: "泰国",
tagetMemberCount: 1
},
{
tagetMemberName: "文莱",
tagetMemberCount: 1
},
{
tagetMemberName: "丹麦",
tagetMemberCount: 1
},
{
tagetMemberName: "克罗地亚",
tagetMemberCount: 1
},
{
tagetMemberName: "卢森堡",
tagetMemberCount: 1
},
{
tagetMemberName: "欧盟",
tagetMemberCount: 1
},
{
tagetMemberName: "阿根廷",
tagetMemberCount: 1
},
{
tagetMemberName: "越南",
tagetMemberCount: 1
},
{
tagetMemberName: "罗马尼亚",
tagetMemberCount: 1
},
{
tagetMemberName: "立陶宛",
tagetMemberCount: 1
},
{
tagetMemberName: "以色列",
tagetMemberCount: 1
},
{
tagetMemberName: "阿联酋",
tagetMemberCount: 1
},
{
tagetMemberName: "斐济",
tagetMemberCount: 1
},
{
tagetMemberName: "墨西哥",
tagetMemberCount: 1
},
{
tagetMemberName: "希腊",
tagetMemberCount: 1
},
{
tagetMemberName: "捷克",
tagetMemberCount: 1
},
{
tagetMemberName: "保加利亚",
tagetMemberCount: 1
},
{
tagetMemberName: "马耳他",
tagetMemberCount: 1
},
{
tagetMemberName: "匈牙利",
tagetMemberCount: 1
},
{
tagetMemberName: "波兰",
tagetMemberCount: 1
},
{
tagetMemberName: "瑞士",
tagetMemberCount: 1
},
{
tagetMemberName: "奥地利",
tagetMemberCount: 1
},
{
tagetMemberName: "俄罗斯",
tagetMemberCount: 1
},
{
tagetMemberName: "斯洛文尼亚",
tagetMemberCount: 1
},
{
tagetMemberName: "土耳其",
tagetMemberCount: 1
},
{
tagetMemberName: "西班牙",
tagetMemberCount: 1
},
{
tagetMemberName: "斯洛伐克",
tagetMemberCount: 1
},
{
tagetMemberName: "比利时",
tagetMemberCount: 1
},
{
tagetMemberName: "乌克兰",
tagetMemberCount: 1
},
{
tagetMemberName: "南非",
tagetMemberCount: 1
},
{
tagetMemberName: "拉脱维亚",
tagetMemberCount: 1
},
{
tagetMemberName: "马来西亚",
tagetMemberCount: 1
},
{
tagetMemberName: "爱尔兰",
tagetMemberCount: 1
},
{
tagetMemberName: "葡萄牙",
tagetMemberCount: 1
},
{
tagetMemberName: "菲律宾",
tagetMemberCount: 1
}
],
value: 7,
zhName: "澳大利亚"
};
// function initMap() {
// chartDom.value = document.getElementById("echartsMap");
// if (!chartDom.value) return;
// if (myChart.value) myChart.value.dispose();
// myChart.value = echarts.init(chartDom.value);
// myChart.value.showLoading();
// echarts.registerMap("world", mapJson);
// createChart();
// myChart.value.hideLoading();
// }
function initMap() {
chartDom.value = document.getElementById("echartsMap");
unionChartDom.value = document.getElementById("echartsUnionMap");
......
......@@ -69,7 +69,13 @@
<div class="right-num">参与排华联盟</div>
</div>
</div>
<div class="item" v-for="(item, index) in countList" :key="index" @click="handleCountryClick(item)">
<div
class="item"
v-for="(item, index) in countList"
:key="index"
@click="handleCountryClick(item)"
:class="{ 'selected-country': currentSelectedCountry && currentSelectedCountry.name === item.name }"
>
<div class="item-left">
<img :src="item.image" alt />
<el-tooltip
......@@ -298,7 +304,7 @@ import { link } from "d3";
import { get, union, update } from "lodash";
import ButtonList from "@/components/buttonList/buttonList.vue";
import { fieldOptions, COLORS, countryNameMap, nameMap } from "@/views/ZMOverView/public.js";
import { countryCoordMap } from "@/assets/json/countryCoordMap.js";
import { countryCoordMap, convertAsiaCenterCoord } from "@/assets/json/countryCoordMap.js";
const buttonList = ref([
{
......@@ -589,8 +595,6 @@ function handleUnionItemClick(item) {
});
}
// ... existing code ...
function createChart() {
if (!countryTotalList.value || countryTotalList.value.length === 0) {
console.error("No country data available");
......@@ -622,7 +626,6 @@ function createChart() {
map: "world",
roam: true,
zoom: 1.2,
// center: [104.1954, 35.8617], // 设置地图中心点为中国
label: {
show: false
},
......@@ -672,6 +675,8 @@ function createChart() {
type: "scatter",
coordinateSystem: "geo",
geoIndex: 0,
nameMap: nameMap,
data: processedData,
symbolSize: function (val) {
return Math.max(val.value / 5, 5);
......@@ -689,20 +694,36 @@ function createChart() {
Array.isArray(currentSelectedCountry.value.memberRelation)
) {
const relations = currentSelectedCountry.value.memberRelation;
const sourceCountryName =
currentSelectedCountry.value.zhName ||
nameMap[currentSelectedCountry.value.name] ||
currentSelectedCountry.value.name;
const sourceCoord = countryCoordMap[sourceCountryName];
const sourceCountryZhName = currentSelectedCountry.value.zhName;
const sourceCountryEnName = currentSelectedCountry.value.name;
let sourceCoord = null;
let finalSourceName = "";
if (sourceCountryZhName && countryCoordMap[sourceCountryZhName]) {
const convertedCoord = convertAsiaCenterCoord(countryCoordMap[sourceCountryZhName]);
sourceCoord = convertedCoord;
finalSourceName = sourceCountryZhName;
} else if (sourceCountryEnName) {
const mappedName = nameMap[sourceCountryEnName] || countryNameMap[sourceCountryEnName];
const zhName = mappedName || sourceCountryEnName;
if (countryCoordMap[zhName]) {
const convertedCoord = convertAsiaCenterCoord(countryCoordMap[zhName]);
sourceCoord = convertedCoord;
finalSourceName = zhName;
}
}
if (!sourceCoord) {
console.warn(`无法找到源国家 ${sourceCountryName} 的坐标`);
console.warn(`无法找到源国家 ${sourceCountryZhName || sourceCountryEnName} 的坐标`);
return;
}
console.log("=== 源国家信息 ===");
console.log("源国家名称:", sourceCountryName);
console.log("源国家中文名:", sourceCountryZhName);
console.log("源国家英文名:", sourceCountryEnName);
console.log("最终使用的国家名称:", finalSourceName);
console.log("源国家坐标:", sourceCoord);
console.log("==================");
......@@ -718,23 +739,46 @@ function createChart() {
validRelations.forEach(relation => {
const targetCountryZhName = relation.tagetMemberName;
const targetCoord = countryCoordMap[targetCountryZhName];
let targetCoord = null;
let finalTargetName = "";
if (countryCoordMap[targetCountryZhName]) {
const convertedCoord = convertAsiaCenterCoord(countryCoordMap[targetCountryZhName]);
targetCoord = convertedCoord;
finalTargetName = targetCountryZhName;
} else {
const possibleNames = [
targetCountryZhName,
nameMap[targetCountryZhName],
countryNameMap[targetCountryZhName]
];
for (const name of possibleNames) {
if (name && countryCoordMap[name]) {
const convertedCoord = convertAsiaCenterCoord(countryCoordMap[name]);
targetCoord = convertedCoord;
finalTargetName = name;
break;
}
}
}
if (targetCoord) {
console.log(`目标国家:${targetCountryZhName}, 坐标:`, targetCoord);
console.log(`目标国家:${targetCountryZhName}, 最终名称:${finalTargetName}, 坐标:`, targetCoord);
const ratio = relation.tagetMemberCount / maxRelationCount;
const r = Math.round(5 + (255 - 5) * ratio);
const g = Math.round(95 + (77 - 95) * ratio);
const b = Math.round(194 + (79 - 194) * ratio);
const b = Math.round(194 + (194 - 194) * ratio);
const lineColor = `rgb(${r}, ${g}, ${b})`;
const lineWidth = 1 + (relation.tagetMemberCount / maxRelationCount) * 7;
linesData.push({
name: `${sourceCountryName} - ${targetCountryZhName}`,
sourceName: sourceCountryName,
targetName: targetCountryZhName,
name: `${finalSourceName} - ${finalTargetName}`,
sourceName: finalSourceName,
targetName: finalTargetName,
coords: [sourceCoord, targetCoord],
value: relation.tagetMemberCount,
lineStyle: {
......@@ -745,7 +789,7 @@ function createChart() {
});
targetPoints.push({
name: targetCountryZhName,
name: finalTargetName,
value: targetCoord,
symbolSize: 8 + (relation.tagetMemberCount / maxRelationCount) * 7,
itemStyle: {
......@@ -753,7 +797,7 @@ function createChart() {
}
});
} else {
console.warn(`无法找到目标国家 ${targetCountryZhName} 的坐标`);
console.warn(`无法找到目标国家 ${targetCountryZhName} 的坐标,尝试的名称都不匹配`);
}
});
......@@ -776,7 +820,7 @@ function createChart() {
});
targetPoints.unshift({
name: sourceCountryName,
name: finalSourceName,
value: sourceCoord,
symbolSize: 15,
itemStyle: {
......@@ -803,44 +847,24 @@ function createChart() {
}
}
// ... existing code ...
// 处理国家列表项点击事件
// 在 handleCountryClick 中添加调试代码
const handleCountryClick = country => {
currentSelectedCountry.value = country;
if (currentSelectedCountry.value?.name === country.name) {
// currentSelectedCountry.value = null;
return;
} else {
currentSelectedCountry.value = country;
}
console.log("=== 点击的国家信息 ===");
console.log("国家中文名:", country.zhName);
console.log("国家英文名:", country.name);
// 检查坐标映射
const coordFromZhName = countryCoordMap[country.zhName];
const coordFromEnName = countryCoordMap[country.name];
const coordFromMappedName = countryCoordMap[nameMap[country.name]];
console.log("通过中文名获取坐标:", coordFromZhName);
console.log("通过英文名获取坐标:", coordFromEnName);
console.log("通过映射名获取坐标:", coordFromMappedName);
console.log("=====================");
console.log("联盟关系数据:", country.memberRelation);
nextTick(() => {
createChart();
});
};
// function initMap() {
// chartDom.value = document.getElementById("echartsMap");
// if (!chartDom.value) return;
// if (myChart.value) myChart.value.dispose();
// myChart.value = echarts.init(chartDom.value);
// myChart.value.showLoading();
// echarts.registerMap("world", mapJson);
// createChart();
// myChart.value.hideLoading();
// }
function initMap() {
chartDom.value = document.getElementById("echartsMap");
unionChartDom.value = document.getElementById("echartsUnionMap");
......@@ -1489,22 +1513,21 @@ const getPredictionList = async () => {
};
// 获取排华联盟数量
const getUnionCountList = async () => {
try {
const res = await getUnionCount({ page: 1, pageSize: 100, domainId: selectedFieldForLatest.value });
if (res && res.code === 200) {
console.log("----getUnionCountList", res.data);
// 处理一下数据
countryTotalList.value = res.data.content
.sort((a, b) => b.count - a.count)
.map(item => {
item.value = item.count;
item.zhName = item.name;
// 1. 尝试直接从映射表获取
let mappedName = countryNameMap[item.ename];
// 2. 如果映射表没有,尝试简单的模糊匹配
if (!mappedName && item.ename) {
let tempName = item.ename
.replace(/Republic of /i, "")
......@@ -1517,7 +1540,8 @@ const getUnionCountList = async () => {
mappedName = tempName;
}
item.name = mappedName || item.ename;
item.name = nameMap[item.ename] || mappedName || item.ename;
item.originalEnName = item.ename;
return item;
});
......@@ -1878,11 +1902,15 @@ watch(activeDate, async () => {
padding: 4px 12px 4px 12px;
box-sizing: border-box;
// border: 1px solid rgba(234, 236, 238, 1);
border-radius: 50px;
// border-radius: 50px;
/* 业务系统/模态背景模糊 */
backdrop-filter: blur(30px);
background: rgba(255, 255, 255, 0.65);
&.selected-country {
background-color: rgb(246, 250, 255) !important;
}
.item-left {
display: flex;
align-items: center;
......
<template>
<div v-if="visible" ref="dialogRef" class="dialog-wrapper" :style="position">
<div class="dialog-box1" @mousedown="handleMouseDown">
<div class="icon">
<img v-if="detailItem.orgName === '参议院'" :src="logoSenate" alt="" />
<img v-else :src="logoHouse" alt="" />
</div>
<div class="title">
<div class="date">{{ detailItem.actionDate }}</div>
<div class="text">
{{ detailItem.actionTitle }}
</div>
</div>
<div class="close" @click="handleClose">
<img :src="closeIcon" alt="" />
</div>
</div>
<div class="dialog-box2" v-if="detailItem.agreeVote !== null || detailItem.disagreeVote !== null">
<div class="vote-bar">
<div class="agree-bar" :style="{ flex: detailItem.agreeVote || 1 }"></div>
<div class="disagree-bar" :style="{ flex: detailItem.disagreeVote || 1 }"></div>
</div>
<div class="vote-text">
<div class="agree-text">{{ (detailItem.agreeVote || 0) + "赞成" }}</div>
<div class="disagree-text">{{ (detailItem.disagreeVote || 0) + "反对" }}</div>
</div>
</div>
<template v-if="detailItem.fynrList && detailItem.fynrList.length">
<div class="dialog-box4">
<div class="box4-left">
<div class="icon">
<img :src="changeIcon" alt="" />
</div>
<div class="text">{{ "变更条款" }}</div>
</div>
</div>
<div class="dialog-box5">
<div class="box5-item" v-for="(sub, subIndex) in detailItem.fynrList" :key="subIndex + '-' + sub">
<div class="icon"></div>
<div class="text">{{ sub }}</div>
</div>
</div>
</template>
</div>
</template>
<script setup>
import { ref } from "vue";
defineProps({
visible: {
type: Boolean,
default: false,
},
detailItem: {
type: Object,
default: () => ({}),
},
position: {
type: Object,
default: () => ({ left: "0px", top: "0px" }),
},
});
const emit = defineEmits(["close"]);
const logoSenate = new URL("@/views/bill/deepDig/processOverview/assets/images/logo1.png", import.meta.url).href;
const logoHouse = new URL("@/views/bill/deepDig/processOverview/assets/images/logo2.png", import.meta.url).href;
const closeIcon = new URL("@/views/bill/deepDig/processOverview/assets/images/close.png", import.meta.url).href;
const changeIcon = new URL("@/views/bill/deepDig/processOverview/assets/images/dialog-box4-icon.png", import.meta.url).href;
const dialogRef = ref(null);
const handleClose = () => {
emit("close");
};
const handleMouseDown = (e) => {
const dialog = dialogRef.value;
if (!dialog) return;
const startX = e.clientX;
const startY = e.clientY;
const initialLeft = dialog.offsetLeft;
const initialTop = dialog.offsetTop;
const move = (moveEvent) => {
const deltaX = moveEvent.clientX - startX;
const deltaY = moveEvent.clientY - startY;
dialog.style.right = "auto";
dialog.style.left = `${initialLeft + deltaX}px`;
dialog.style.top = `${initialTop + deltaY}px`;
};
const stop = () => {
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", stop);
};
document.addEventListener("mousemove", move);
document.addEventListener("mouseup", stop);
};
</script>
<style lang="scss" scoped>
.dialog-wrapper {
position: absolute;
width: 480px;
padding-bottom: 20px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
z-index: 10000;
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.15);
.dialog-box1 {
display: flex;
min-height: 90px;
height: auto;
padding-bottom: 15px;
position: relative;
border-bottom: 1px solid rgba(240, 242, 244, 1);
cursor: move;
.icon {
width: 48px;
height: 48px;
margin-left: 18px;
margin-top: 20px;
img {
width: 100%;
height: 100%;
}
}
.title {
margin-top: 20px;
margin-left: 16px;
width: 350px;
.date {
height: 22px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 22px;
}
.text {
margin-top: 4px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 22px;
span {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
}
}
}
.close {
position: absolute;
top: 14px;
right: 15px;
width: 16px;
height: 16px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
}
.dialog-box2 {
height: 59px;
padding: 0 23px;
.vote-bar {
display: flex;
height: 4px;
width: 100%;
margin-top: 20px;
border-radius: 2px;
overflow: hidden;
.agree-bar {
background: #52c41a;
margin-right: 2px;
}
.disagree-bar {
background: #f5222d;
}
}
.vote-text {
display: flex;
justify-content: space-between;
margin-top: 8px;
.agree-text {
color: #52c41a;
font-size: 14px;
}
.disagree-text {
color: #f5222d;
font-size: 14px;
}
}
}
.dialog-box4 {
width: 438px;
margin-left: 23px;
margin-top: 20px;
display: flex;
justify-content: space-between;
height: 30px;
.box4-left {
display: flex;
.icon {
margin-top: 6px;
width: 18px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
.text {
width: 64px;
height: 30px;
margin-left: 6px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 30px;
}
}
}
.dialog-box5 {
margin-top: 3px;
margin-left: 23px;
width: 438px;
.box5-item {
min-height: 30px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 1.5;
display: flex;
margin-bottom: 8px;
.icon {
flex-shrink: 0;
margin-left: 15px;
width: 6px;
height: 6px;
margin-top: 9px;
border-radius: 3px;
background: #84888e;
}
.text {
margin-left: 10px;
word-break: break-all;
}
}
}
}
</style>
......@@ -647,7 +647,7 @@ onMounted(() => {
.icon1 {
position: absolute;
left: 5px;
left: 8px;
bottom: -8px;
width: 16px;
height: 16px;
......@@ -663,7 +663,7 @@ onMounted(() => {
.icon2 {
position: absolute;
right: 5px;
right: 8px;
bottom: -8px;
width: 16px;
height: 16px;
......
......@@ -180,7 +180,8 @@
<OverviewCard class="overview-card--single box9" title="涉华法案关键条款" :icon="box7HeaderIcon">
<div class="overview-card-body box9-main">
<div class="overview-chart-wrap">
<div id="wordCloudChart" class="overview-chart"></div>
<el-empty v-if="!wordCloudHasData" description="暂无数据" :image-size="100" />
<WordCloundChart v-else class="overview-chart" width="100%" height="100%" :data="wordCloudData" />
</div>
<TipTab class="overview-tip" />
</div>
......@@ -197,8 +198,8 @@
</template>
<script setup>
import RiskSignal from "@/components/base/RiskSignal/index.vue";
import { onMounted, ref, onUnmounted, nextTick, watch } from "vue";
import RiskSignal from "@/components/base/riskSignal/index.vue";
import { onMounted, ref, onUnmounted, nextTick, watch, computed } from "vue";
import router from "@/router/index";
import setChart from "@/utils/setChart";
import {
......@@ -220,9 +221,9 @@ import OverviewCard from "./OverviewCard.vue";
import ResourceLibrarySection from "./ResourceLibrarySection.vue";
import { useContainerScroll } from "@/hooks/useScrollShow";
import TipTab from "@/components/base/TipTab/index.vue";
import WordCloundChart from "@/components/base/WordCloundChart/index.vue";
import getMultiLineChart from "./utils/multiLineChart";
import getWordCloudChart from "./utils/worldCloudChart";
import getPieChart from "./utils/piechart";
import getDoublePieChart from "./utils/doublePieChart";
......@@ -637,6 +638,7 @@ const handleToSocialDetail = item => {
};
// 关键条款
const wordCloudData = ref([]);
const wordCloudHasData = computed(() => Array.isArray(wordCloudData.value) && wordCloudData.value.length > 0);
const handleGetKeyTK = async () => {
try {
const res = await getBillOverviewKeyTK();
......@@ -655,8 +657,6 @@ const handleGetKeyTK = async () => {
};
const handleBox6 = async () => {
await handleGetKeyTK();
const wordCloudChart = getWordCloudChart(wordCloudData.value);
setChart(wordCloudChart, "wordCloudChart");
};
// 涉华领域分布
......
<template>
<div class="bill-original-text-page">
<div class="page-header">
<div class="page-title">法案原文</div>
<div class="page-actions">
<div class="action-btn" @click="handleBack">返回</div>
</div>
</div>
<div class="page-content">
<iframe v-if="billFullText" :src="billFullText" width="100%" height="100%" frameborder="0"></iframe>
<div v-else class="empty-state">暂无原文</div>
</div>
<DecreeOriginal :report-data="reportData" @download="handleDownload" />
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { getBillFullText } from "@/api/bill";
const route = useRoute();
const router = useRouter();
const billFullText = ref("");
import { ref } from "vue";
import DecreeOriginal from "@/components/base/DecreeOriginal/index.vue";
const getBillFullTextFn = async () => {
const res = await getBillFullText({
id: route.query.billId
});
if (res.code === 200 && res.data) {
billFullText.value = typeof res.data === "string" ? res.data.trim() : res.data;
}
};
// 旧“法案原文”功能/按钮全部废弃:页面仅承载通用原文组件,后续接入新接口再赋值。
const reportData = ref([]);
const handleBack = () => {
router.back();
const handleDownload = () => {
// 后续接入新接口/下载逻辑
};
onMounted(() => {
getBillFullTextFn();
});
</script>
<style lang="scss" scoped>
.bill-original-text-page {
width: 100%;
box-sizing: border-box;
background: rgba(248, 249, 250, 1);
padding: 0 0 20px;
.page-header {
width: 100%;
height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
.page-title {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 700;
}
.page-actions {
display: flex;
justify-content: flex-end;
.action-btn {
cursor: pointer;
height: 32px;
line-height: 32px;
padding: 0 12px;
border-radius: 6px;
border: 1px solid rgba(230, 231, 232, 1);
background: rgba(255, 255, 255, 1);
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
}
}
}
.page-content {
width: 100%;
height: calc(100vh - 320px);
min-height: 600px;
background: #fff;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
overflow: hidden;
iframe {
display: block;
}
.empty-state {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
}
}
height: 100%;
}
</style>
......@@ -111,48 +111,6 @@
</AnalysisBox>
</div>
<div class="box3">
<!-- <div class="box-header">
<div class="icon"></div>
<div class="title">{{ "政治献金领域分布" }}</div>
<div class="header-right">
<div class="right-icon">
<img src="@/assets/icons/box-header-icon1.png" alt="" />
</div>
<div class="right-icon">
<img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="right-icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div>
<div class="box3-main">
<div class="box3-main-left" id="chart2"></div>
<div class="box3-main-right">
<el-empty v-if="!areaList.length" description="暂无数据" :image-size="100" />
<div class="box3-main-right-item" v-for="(item, index) in areaList" :key="index">
<div class="id">{{ index + 1 }}</div>
<div class="name">{{ item.name }}</div>
<div class="line">
<div class="inner-line" :style="{ width: (item.num / areaList[0].num) * 100 + '%' }"></div>
</div>
<div class="num">{{ item.numtext }}</div>
<div class="more">{{ `${item.insNum}家机构 >` }}</div>
</div>
</div>
</div>
<div class="box-footer">
<div class="box-footer-left">
<img src="@/assets/icons/box-footer-left-icon.png" alt="" />
</div>
<div class="box-footer-center">
{{ currentPersonName }}的政治资金主要依赖于一个由亿万富翁、特定行业利益集团及通过​“超级政治行动委员会”​​
运作的大额捐款网络。
</div>
<div class="box-footer-right">
<img src="@/assets/icons/box-footer-right-icon.png" alt="" />
</div>
</div> -->
<AnalysisBox title="政治献金领域分布">
<div class="box3-main" :class="{ 'box3-main-no-footer': !showHardcodedTips }">
<div class="box3-main-left" id="chart2"></div>
......@@ -196,6 +154,7 @@ import setChart from "@/utils/setChart";
import getPieChart from "./utils/piechart";
import getSankeyChart from "./utils/sankey";
import { MUTICHARTCOLORS } from "@/common/constant";
import Img1 from "./assets/images/1.png";
import Img2 from "./assets/images/2.png";
......@@ -434,23 +393,9 @@ const topAreaList = computed(() => {
return areaList.value.slice(0, 5);
});
const chart2ColorList = ref(["#4096FF", "#FFA39E", "#ADC6FF", "#FFC069", "#B5F5EC", "#B37FEB", "#D6E4FF"]);
const sankeyColors = [
"#5470c6",
"#91cc75",
"#fac858",
"#ee6666",
"#73c0de",
"#3ba272",
"#fc8452",
"#9a60b4",
"#ea7ccc",
"#a2c0f1",
"#f596aa",
"#e6b422",
"#4b2c20"
];
const chart2ColorList = ref([...MUTICHARTCOLORS]);
const sankeyColors = [...MUTICHARTCOLORS];
const partyContributionList = ref([
{
......
......@@ -100,11 +100,11 @@
<div class="term-main">
<div class="term-row term-row-cn">
<div class="term-no-cn">第{{ term.tkxh }}条.</div>
<div class="term-content-cn">{{ term.fynr }}</div>
<div class="term-content-cn" v-html="getTermContentHtml(term, 'cn')"></div>
</div>
<div class="term-row term-row-en" v-if="termsShowOriginal">
<div class="term-no-en">Sec.{{ term.tkxh }}</div>
<div class="term-content-en">{{ term.ywnr }}</div>
<div class="term-content-en" v-html="getTermContentHtml(term, 'en')"></div>
</div>
</div>
</div>
......@@ -136,6 +136,8 @@ import * as echarts from "echarts";
import { Search } from "@element-plus/icons-vue";
import getPieChart from "./utils/piechart";
import { getBillContentId, getBillContentTk, getBillContentXzfs, getBillHyly } from "@/api/bill";
import { MUTICHARTCOLORS } from "@/common/constant";
import { extractTextEntity } from "@/api/intelligent/index";
const route = useRoute();
......@@ -161,6 +163,134 @@ const domainLoading = ref(false);
const termsHighlight = ref(true);
const termsShowOriginal = ref(true);
const entityRequestToken = ref(0);
const termEntityCache = ref(new Map());
const escapeHtml = value => {
const str = String(value ?? "");
return str
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
};
const normalizeEntities = entities => {
const list = Array.isArray(entities) ? entities : [];
return list
.map(item => {
return {
text_span: String(item?.text_span ?? "").trim(),
type: String(item?.type ?? "").trim()
};
})
.filter(item => item.text_span);
};
const getEntityRanges = (text, entities) => {
const ranges = [];
const rawText = String(text ?? "");
if (!rawText) return ranges;
const list = normalizeEntities(entities).sort((a, b) => b.text_span.length - a.text_span.length);
for (const ent of list) {
let startIndex = 0;
while (startIndex < rawText.length) {
const idx = rawText.indexOf(ent.text_span, startIndex);
if (idx === -1) break;
ranges.push({ start: idx, end: idx + ent.text_span.length, ent });
startIndex = idx + ent.text_span.length;
}
}
ranges.sort((a, b) => a.start - b.start || b.end - a.end);
const merged = [];
let lastEnd = 0;
for (const r of ranges) {
if (r.start < lastEnd) continue;
merged.push(r);
lastEnd = r.end;
}
return merged;
};
const buildHighlightedHtml = (text, entities, enableHighlight) => {
const rawText = String(text ?? "");
if (!rawText) return "";
const safeText = escapeHtml(rawText).replace(/\n/g, "<br />");
if (!enableHighlight) return safeText;
const ranges = getEntityRanges(rawText, entities);
if (!ranges.length) return safeText;
let html = "";
let cursor = 0;
for (const r of ranges) {
if (cursor < r.start) {
html += escapeHtml(rawText.slice(cursor, r.start));
}
const spanText = rawText.slice(r.start, r.end);
const type = escapeHtml(r.ent?.type ?? "");
html += `<span class="term-entity" data-entity-type="${type}">${escapeHtml(spanText)}</span>`;
cursor = r.end;
}
if (cursor < rawText.length) {
html += escapeHtml(rawText.slice(cursor));
}
return html.replace(/\n/g, "<br />");
};
const getTermEntityKey = (term, lang) => {
const baseKey = getTermKey(term, -1);
return `${baseKey}__${lang}`;
};
const ensureEntitiesForTerms = async terms => {
if (!termsHighlight.value) return;
const list = Array.isArray(terms) ? terms : [];
if (!list.length) return;
const currentToken = ++entityRequestToken.value;
const tasks = [];
for (const term of list) {
const cnKey = getTermEntityKey(term, "cn");
const enKey = getTermEntityKey(term, "en");
if (!termEntityCache.value.has(cnKey) && String(term?.fynr ?? "").trim()) {
tasks.push({ key: cnKey, text: term.fynr });
}
if (!termEntityCache.value.has(enKey) && String(term?.ywnr ?? "").trim()) {
tasks.push({ key: enKey, text: term.ywnr });
}
}
if (!tasks.length) return;
try {
const results = await Promise.all(
tasks.map(async item => {
const res = await extractTextEntity(item.text);
const entities = normalizeEntities(res?.result ?? res?.data?.result ?? res?.data ?? res);
return { key: item.key, entities };
})
);
if (currentToken !== entityRequestToken.value) return;
for (const r of results) {
termEntityCache.value.set(r.key, r.entities);
}
} catch (error) {
if (currentToken !== entityRequestToken.value) return;
}
};
const getTermContentHtml = (term, lang) => {
const raw = lang === "en" ? term?.ywnr : term?.fynr;
const key = getTermEntityKey(term, lang);
const entities = termEntityCache.value.get(key) || [];
return buildHighlightedHtml(raw, entities, termsHighlight.value);
};
const tkRequestToken = ref(0);
const xzfsRequestToken = ref(0);
const hylyRequestToken = ref(0);
......@@ -182,9 +312,9 @@ const getTermSerial = index => {
};
const chart1Data = ref([]);
const chart1ColorList = ref(["#4096ff", "#b37feb", "#ff7875", "#85a5ff", "#69b1ff", "#ffc069", "#87e8de"]);
const chart1ColorList = ref([...MUTICHARTCOLORS]);
const chart2ColorList = ref(["#ff7875", "#85a5ff", "#95de64", "#ffc069", "#85e5db"]);
const chart2ColorList = ref([...MUTICHARTCOLORS]);
const chart2Data = ref([]);
......@@ -218,6 +348,14 @@ watch([selectedDomain, selectedLimit], () => {
handleGetBillContentTk(checkedValue.value ? "Y" : "N");
});
watch(
[termsHighlight, termsShowOriginal],
() => {
ensureEntitiesForTerms(displayTermsList.value);
},
{ immediate: true }
);
const handleSearchSubmit = () => {
searchKeyword.value = searchValue.value;
currentPage.value = 1;
......@@ -362,6 +500,7 @@ const handleGetBillContentTk = async cRelated => {
return item;
});
total.value = res.data.totalElements || 0;
ensureEntitiesForTerms(mainTermsList.value);
} else {
mainTermsList.value = [];
total.value = 0;
......@@ -805,6 +944,14 @@ onMounted(async () => {
font-weight: 700;
line-height: 24px;
color: var(--text-primary-80-color);
:deep(.term-entity) {
display: inline;
padding: 0 2px;
border-radius: 4px;
background: rgba(255, 213, 79, 0.35);
box-shadow: inset 0 0 0 1px rgba(255, 193, 7, 0.25);
}
}
.term-content-en {
......@@ -813,6 +960,14 @@ onMounted(async () => {
font-weight: 400;
line-height: 24px;
color: var(--text-primary-65-color);
:deep(.term-entity) {
display: inline;
padding: 0 2px;
border-radius: 4px;
background: rgba(255, 213, 79, 0.28);
box-shadow: inset 0 0 0 1px rgba(255, 193, 7, 0.2);
}
}
.open {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论