提交 e0f148d0 authored 作者: 闫鹏's avatar 闫鹏

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

Yp dev 查看合并请求 !320
流水线 #377 已通过 于阶段
in 6 分 2 秒
...@@ -33,7 +33,7 @@ const financeRoutes = [ ...@@ -33,7 +33,7 @@ const financeRoutes = [
}, },
// V2.0单条制裁详情-实体清单原文 // V2.0单条制裁详情-实体清单原文
{ {
path: "/exportControl/origin", path: "/finance/origin",
name: "financeEntityListOrigin", name: "financeEntityListOrigin",
component: () => import("@/views/finance/singleSanction/originPage/index.vue") component: () => import("@/views/finance/singleSanction/originPage/index.vue")
// meta: { // meta: {
......
...@@ -476,12 +476,6 @@ ...@@ -476,12 +476,6 @@
header-row-class-name="table-header" header-row-class-name="table-header"
row-class-name="table-row" row-class-name="table-row"
> >
<!-- <el-table-column prop="index" label="序号" width="80" align="center">
<template #default="scope">
{{ scope.$index + 1 + (currentPage - 1) * pageSize }}
</template>
</el-table-column> -->
<el-table-column prop="name" label="实体名称" min-width="200"> <el-table-column prop="name" label="实体名称" min-width="200">
<template #default="scope"> <template #default="scope">
<div class="tableName" @click="handleCompClick(scope.row)"> <div class="tableName" @click="handleCompClick(scope.row)">
...@@ -970,7 +964,7 @@ onMounted(async () => { ...@@ -970,7 +964,7 @@ onMounted(async () => {
label: item.nameZh, label: item.nameZh,
value: tabMap[item.id], value: tabMap[item.id],
id: [item.id], id: [item.id],
disabled: item.id == "13" // 商业管制清单不展示 disabled: false
})); }));
resourceTabs.value.unshift({ label: "全部制裁", value: "all", id: "", disabled: false }); resourceTabs.value.unshift({ label: "全部制裁", value: "all", id: "", disabled: false });
console.log("返回的数据结构 infoList =》", infoList.value); console.log("返回的数据结构 infoList =》", infoList.value);
...@@ -1108,7 +1102,7 @@ const processYearDomainCountData = yearDomainCountData => { ...@@ -1108,7 +1102,7 @@ const processYearDomainCountData = yearDomainCountData => {
const handleEntityClick = item => { const handleEntityClick = item => {
console.log("item", item); console.log("item", item);
window.sessionStorage.setItem("curTabName", item.name || item.entityNameZh); window.sessionStorage.setItem("curTabName", item.name || item.entityNameZh);
gotoCompanyPages(item.entityId); gotoCompanyPages(item.id);
// const route = router.resolve({ // const route = router.resolve({
// name: "companyPages", // name: "companyPages",
// params: { // params: {
...@@ -1494,7 +1488,7 @@ watch( ...@@ -1494,7 +1488,7 @@ watch(
const fetchEntitiesList = async (page = 1, size = 10) => { const fetchEntitiesList = async (page = 1, size = 10) => {
try { try {
console.log("activeResourceTabItem.value.id", activeResourceTabItem.value.id); console.log("activeResourceTabItem.value.id", activeResourceTabItem.value.id);
const res = await getEntitiesList(activeResourceTabItem.value.id, page, size); const res = await getEntitiesList(activeResourceTabItem.value.id.join(","), page, size);
if (res) { if (res) {
entitiesList.value = res.content.map(item => ({ entitiesList.value = res.content.map(item => ({
...item, ...item,
...@@ -1630,6 +1624,7 @@ const fetchSocialMediaInfo = async () => { ...@@ -1630,6 +1624,7 @@ const fetchSocialMediaInfo = async () => {
if (data && Array.isArray(data)) { if (data && Array.isArray(data)) {
// console.log(data); // console.log(data);
socialMediaList.value = data.map(item => ({ socialMediaList.value = data.map(item => ({
...item,
avatar: item.personImage, avatar: item.personImage,
name: item.personName, name: item.personName,
time: formatTime(item.time), time: formatTime(item.time),
...@@ -1662,7 +1657,7 @@ const fetchNewsInfo = async () => { ...@@ -1662,7 +1657,7 @@ const fetchNewsInfo = async () => {
}; };
const handlePerClick = item => { const handlePerClick = item => {
// console.log("点击了社交媒体消息:", item); console.log("点击了社交媒体消息:", item);
window.sessionStorage.setItem("curTabName", item.name); window.sessionStorage.setItem("curTabName", item.name);
const route = router.resolve({ const route = router.resolve({
path: "/characterPage", path: "/characterPage",
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
</template> </template>
<div class="right-main"> <div class="right-main">
<div class="right-main-content"> <div class="right-main-content">
<div class="hintWrap"> <!-- <div class="hintWrap">
<div class="icon1"></div> <div class="icon1"></div>
<div class="title"> <div class="title">
2025年实体清单制裁范围扩大至芯片制造环节,为中国的芯片制造能力划定“技术天花板”,阻止其向更先进水平发展。制裁范围向上游设备和材料、下游先进封装以及关键工具(如EDA软件)延伸,意图瓦解中国构建自主可控产业链的努力。 2025年实体清单制裁范围扩大至芯片制造环节,为中国的芯片制造能力划定“技术天花板”,阻止其向更先进水平发展。制裁范围向上游设备和材料、下游先进封装以及关键工具(如EDA软件)延伸,意图瓦解中国构建自主可控产业链的努力。
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
<div class="icon2Wrap"> <div class="icon2Wrap">
<div class="icon2"></div> <div class="icon2"></div>
</div> </div>
</div> </div> -->
<div class="right-main-content-main"> <div class="right-main-content-main">
<div class="fishbone-wrapper"> <div class="fishbone-wrapper">
<div class="fishbone-scroll-container" ref="scrollContainerRef"> <div class="fishbone-scroll-container" ref="scrollContainerRef">
......
...@@ -433,11 +433,6 @@ onMounted(() => { ...@@ -433,11 +433,6 @@ onMounted(() => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
* {
margin: 0;
padding: 0;
}
.introduction-page { .introduction-page {
width: 1601px; width: 1601px;
margin: 0 auto; margin: 0 auto;
......
...@@ -155,15 +155,8 @@ const getTagStyle = tag => { ...@@ -155,15 +155,8 @@ const getTagStyle = tag => {
// 跳转公司详情页 // 跳转公司详情页
const handleCompClick = item => { const handleCompClick = item => {
console.log("item", item); console.log("item", item);
window.sessionStorage.setItem("curTabName", item.entityNameZh || item.entityName); window.sessionStorage.setItem("curTabName", item.name || item.orgName);
gotoCompanyPages(item.id); gotoCompanyPages(item.id);
// const route = router.resolve({
// name: "companyPages",
// params: {
// id: item.id
// }
// });
// window.open(route.href, "_blank");
}; };
</script> </script>
......
...@@ -540,10 +540,13 @@ watch(customDateRange, () => { ...@@ -540,10 +540,13 @@ watch(customDateRange, () => {
border: 1px solid rgba(170, 173, 177, 1); border: 1px solid rgba(170, 173, 177, 1);
background-color: #fff; background-color: #fff;
border-radius: 3px; border-radius: 3px;
border: 1px solid #ddd;
border-radius: 4px;
height: 32px;
} }
:deep(.el-input__inner) { :deep(.el-input__inner) {
font-size: 16px; font-size: 14px;
font-weight: 400; font-weight: 400;
font-family: "Microsoft YaHei"; font-family: "Microsoft YaHei";
line-height: 24px; line-height: 24px;
...@@ -552,8 +555,8 @@ watch(customDateRange, () => { ...@@ -552,8 +555,8 @@ watch(customDateRange, () => {
} }
.filters { .filters {
display: flex; // display: flex;
align-items: center; // align-items: center;
.el-checkbox { .el-checkbox {
margin-right: 20px; margin-right: 20px;
...@@ -565,8 +568,9 @@ watch(customDateRange, () => { ...@@ -565,8 +568,9 @@ watch(customDateRange, () => {
height: 32px; height: 32px;
} }
:deep(.el-checkbox__label) { :deep(.el-checkbox__label) {
font-size: 16px; font-size: 14px;
color: rgb(95, 101, 108); color: rgb(95, 101, 108);
margin-top: 3px;
} }
} }
} }
...@@ -596,9 +600,10 @@ watch(customDateRange, () => { ...@@ -596,9 +600,10 @@ watch(customDateRange, () => {
padding-left: 20px; padding-left: 20px;
.el-checkbox { .el-checkbox {
width: 50%; // width: 50%;
margin-right: 0; // margin-right: 0;
margin-bottom: 4px; // margin-bottom: 4px;
height: 24px;
font-size: 16px; font-size: 16px;
font-weight: 400; font-weight: 400;
font-family: "Microsoft YaHei"; font-family: "Microsoft YaHei";
......
...@@ -537,26 +537,30 @@ const domainChartOption = ref({ ...@@ -537,26 +537,30 @@ const domainChartOption = ref({
width: 1.1 width: 1.1
} }
}, },
// labelLayout: function (params) {
// const isLeft = params.labelRect.x < params.viewWidth / 2;
// const points = params.labelLinePoints;
// // Update the end point.
// points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width;
// return {
// labelLinePoints: points
// };
// },
labelLayout: function (params) { labelLayout: function (params) {
const isLeft = params.labelRect.x < params.viewWidth / 2; // hideOverlap: true
const points = params.labelLinePoints; const points = params.labelLinePoints;
// Update the end point. const isLeft = params.labelRect.x < params.rect.x + params.rect.width / 2;
// 调整指示线终点到 label 垂直中心
const labelCenterY = params.labelRect.y + params.labelRect.height / 2;
points[2][1] = labelCenterY;
// 调整指示线终点到 label 水平边缘
points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width; points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width;
return { return {
labelLinePoints: points labelLinePoints: points
}; };
// if (isLeft) {
// // 左侧:终点对齐到标签左边界
// points[2][0] = 0;
// } else {
// // 右侧:终点对齐到标签右边界
// points[2][0] = params.labelRect.x + params.labelRect.width;
// }
// return {
// labelLinePoints: points
// };
}, },
itemStyle: { itemStyle: {
borderWidth: 0 borderWidth: 0
...@@ -714,11 +718,27 @@ const typeChartOption = ref({ ...@@ -714,11 +718,27 @@ const typeChartOption = ref({
width: 1 width: 1
} }
}, },
// labelLayout: function (params) {
// const isLeft = params.labelRect.x < params.viewWidth / 2;
// const points = params.labelLinePoints;
// // Update the end point.
// points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width;
// return {
// labelLinePoints: points
// };
// },
labelLayout: function (params) { labelLayout: function (params) {
const isLeft = params.labelRect.x < params.viewWidth / 2; // hideOverlap: true
const points = params.labelLinePoints; const points = params.labelLinePoints;
// Update the end point. const isLeft = params.labelRect.x < params.rect.x + params.rect.width / 2;
// 调整指示线终点到 label 垂直中心
const labelCenterY = params.labelRect.y + params.labelRect.height / 2;
points[2][1] = labelCenterY;
// 调整指示线终点到 label 水平边缘
points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width; points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width;
return { return {
labelLinePoints: points labelLinePoints: points
}; };
......
...@@ -540,11 +540,6 @@ onMounted(async () => { ...@@ -540,11 +540,6 @@ onMounted(async () => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
* {
margin: 0;
padding: 0;
}
.deepMiningChartmode { .deepMiningChartmode {
height: calc(100vh - 220px) !important; height: calc(100vh - 220px) !important;
// overflow: hidden; // overflow: hidden;
...@@ -628,6 +623,9 @@ onMounted(async () => { ...@@ -628,6 +623,9 @@ onMounted(async () => {
.search-input { .search-input {
flex: 1; flex: 1;
border: 1px solid #ddd;
border-radius: 4px;
height: 32px;
} }
} }
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
<div class="left-main"> <div class="left-main">
<div class="top-bar"> <div class="top-bar">
<el-select v-model="searchDomain" placeholder="全部领域" class="domain-select"> <el-select v-model="searchDomain" placeholder="全部领域" class="domain-select">
<el-option label="全部领域" value="" /> <el-option label="全部领域" value="0" />
<el-option label="人工智能" value="1" /> <el-option label="人工智能" value="1" />
<el-option label="生物科技" value="2" /> <el-option label="生物科技" value="2" />
<el-option label="新一代信息技术" value="3" /> <el-option label="新一代信息技术" value="3" />
...@@ -515,7 +515,7 @@ const getNetProfitData = async () => { ...@@ -515,7 +515,7 @@ const getNetProfitData = async () => {
// 单次制裁-影响分析-制裁企业列表 // 单次制裁-影响分析-制裁企业列表
const entityList = ref([]); const entityList = ref([]);
const searchDomain = ref(""); const searchDomain = ref("0");
const searchKeyword = ref(""); const searchKeyword = ref("");
const selectedCompanyId = ref(null); const selectedCompanyId = ref(null);
const sanRecordId = ref(""); const sanRecordId = ref("");
...@@ -584,7 +584,7 @@ const getEntityList = async () => { ...@@ -584,7 +584,7 @@ const getEntityList = async () => {
const res = await getSingleSanctionEntityList({ const res = await getSingleSanctionEntityList({
sanRecordId: sanRecordId.value, sanRecordId: sanRecordId.value,
isOnlyCn: false, isOnlyCn: false,
domainId: searchDomain.value || undefined, domainId: searchDomain.value == 0 ? undefined : searchDomain.value || undefined,
searchText: searchKeyword.value || undefined searchText: searchKeyword.value || undefined
}); });
if (res.code === 200) { if (res.code === 200) {
...@@ -990,11 +990,6 @@ onMounted(async () => { ...@@ -990,11 +990,6 @@ onMounted(async () => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
* {
margin: 0;
padding: 0;
}
.industrial-impact { .industrial-impact {
width: 100%; width: 100%;
padding-top: 16px; padding-top: 16px;
...@@ -1056,7 +1051,8 @@ onMounted(async () => { ...@@ -1056,7 +1051,8 @@ onMounted(async () => {
:deep(.el-input__wrapper) { :deep(.el-input__wrapper) {
height: 32px; height: 32px;
border-radius: 4px; border: 1px solid rgba(170, 173, 177, 0.4);
border-radius: 5px;
} }
} }
} }
......
...@@ -1118,11 +1118,6 @@ onBeforeUnmount(() => { ...@@ -1118,11 +1118,6 @@ onBeforeUnmount(() => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
* {
margin: 0;
padding: 0;
}
.industrial-impact { .industrial-impact {
width: 100%; width: 100%;
padding-top: 16px; padding-top: 16px;
......
...@@ -28,10 +28,6 @@ const activeIndex = ref(0); ...@@ -28,10 +28,6 @@ const activeIndex = ref(0);
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
* {
margin: 0;
padding: 0;
}
.impact-analysis { .impact-analysis {
width: 1601px; width: 1601px;
margin: 0 auto; margin: 0 auto;
......
...@@ -100,10 +100,10 @@ ...@@ -100,10 +100,10 @@
<el-checkbox v-model="onlyChina" label="只看中国实体" /> <el-checkbox v-model="onlyChina" label="只看中国实体" />
<el-select <el-select
v-model="filterField" v-model="filterField"
placeholder="全部领域" placeholder="选择领域"
style="width: 150px; margin: 0 12px 0 16px" style="width: 150px; margin: 0 12px 0 16px"
> >
<el-option label="全部领域" value="" /> <!-- <el-option label="全部领域" value="" /> -->
<el-option <el-option
v-for="item in domainOptions" v-for="item in domainOptions"
:key="item.value" :key="item.value"
...@@ -243,6 +243,24 @@ import { useGotoCompanyPages } from "@/router/modules/company"; ...@@ -243,6 +243,24 @@ import { useGotoCompanyPages } from "@/router/modules/company";
const gotoCompanyPages = useGotoCompanyPages(); const gotoCompanyPages = useGotoCompanyPages();
const route = useRoute(); const route = useRoute();
const domainOptions = ref([
{ label: "全部领域", value: "0" },
{ label: "人工智能", value: "1" },
{ label: "生物科技", value: "2" },
{ label: "新一代信息技术", value: "3" },
{ label: "量子科技", value: "4" },
{ label: "新能源", value: "5" },
{ label: "集成电路", value: "6" },
{ label: "海洋", value: "7" },
{ label: "先进制造", value: "8" },
{ label: "新材料", value: "9" },
{ label: "航空航天", value: "10" },
{ label: "深海", value: "11" },
{ label: "极地", value: "12" },
{ label: "太空", value: "13" },
{ label: "核", value: "14" }
]);
// 跳转公司详情页 // 跳转公司详情页
const handleCompClick = item => { const handleCompClick = item => {
if (!item.entityId) { if (!item.entityId) {
...@@ -297,7 +315,7 @@ const getSanctionOverviewList = async () => { ...@@ -297,7 +315,7 @@ const getSanctionOverviewList = async () => {
const res = await getSingleSanctionOverviewList({ const res = await getSingleSanctionOverviewList({
sanRecordId: sanRecordId.value, sanRecordId: sanRecordId.value,
isOnlyCn: onlyChina.value, isOnlyCn: onlyChina.value,
domainId: filterField.value || undefined, domainId: filterField.value == 0 ? undefined : filterField.value || undefined,
searchText: searchKeyword.value || undefined, searchText: searchKeyword.value || undefined,
searchType: searchType.value, searchType: searchType.value,
entityTypeId: filterEntity.value || undefined entityTypeId: filterEntity.value || undefined
...@@ -465,7 +483,7 @@ const formattedData = computed(() => { ...@@ -465,7 +483,7 @@ const formattedData = computed(() => {
const filterEntity = ref("2"); const filterEntity = ref("2");
const onlyChina = ref(false); const onlyChina = ref(false);
const filterField = ref(""); const filterField = ref(domainOptions.value[0].value);
const searchKeyword = ref(""); const searchKeyword = ref("");
const activeTab = ref("add"); const activeTab = ref("add");
const searchType = computed(() => activeTab.value); const searchType = computed(() => activeTab.value);
...@@ -484,23 +502,6 @@ watch(searchKeyword, () => { ...@@ -484,23 +502,6 @@ watch(searchKeyword, () => {
debouncedSearch(); debouncedSearch();
}); });
const domainOptions = ref([
{ label: "人工智能", value: "1" },
{ label: "生物科技", value: "2" },
{ label: "新一代信息技术", value: "3" },
{ label: "量子科技", value: "4" },
{ label: "新能源", value: "5" },
{ label: "集成电路", value: "6" },
{ label: "海洋", value: "7" },
{ label: "先进制造", value: "8" },
{ label: "新材料", value: "9" },
{ label: "航空航天", value: "10" },
{ label: "深海", value: "11" },
{ label: "极地", value: "12" },
{ label: "太空", value: "13" },
{ label: "核", value: "14" }
]);
const tagColors = [ const tagColors = [
{ bg: "rgb(242, 235, 255)", border: "rgb(211, 190, 255)", text: "rgb(114, 46, 209)" }, // Purple { bg: "rgb(242, 235, 255)", border: "rgb(211, 190, 255)", text: "rgb(114, 46, 209)" }, // Purple
{ bg: "rgb(225, 250, 248)", border: "rgb(178, 242, 238)", text: "rgb(16, 178, 166)" }, // Cyan { bg: "rgb(225, 250, 248)", border: "rgb(178, 242, 238)", text: "rgb(16, 178, 166)" }, // Cyan
...@@ -570,11 +571,6 @@ onMounted(() => { ...@@ -570,11 +571,6 @@ onMounted(() => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
// * {
// margin: 0;
// padding: 0;
// }
.sanctions-overview { .sanctions-overview {
width: 1601px; width: 1601px;
margin: 0 auto; margin: 0 auto;
...@@ -888,19 +884,19 @@ onMounted(() => { ...@@ -888,19 +884,19 @@ onMounted(() => {
margin-bottom: 20px; margin-bottom: 20px;
:deep(.el-input__inner) { :deep(.el-input__inner) {
font-size: 16px; font-size: 14px;
font-weight: 400; font-weight: 400;
font-family: "Microsoft YaHei"; font-family: "Microsoft YaHei";
line-height: 24px; line-height: 24px;
color: rgb(95, 101, 108); color: #606266;
&::placeholder { &::placeholder {
color: rgb(95, 101, 108); color: rgb(95, 101, 108, 0.8);
} }
} }
:deep(.el-checkbox__label) { :deep(.el-checkbox__label) {
font-size: 16px; font-size: 14px;
font-weight: 400; font-weight: 400;
font-family: "Microsoft YaHei"; font-family: "Microsoft YaHei";
line-height: 24px; line-height: 24px;
......
...@@ -60,7 +60,9 @@ ...@@ -60,7 +60,9 @@
:class="{ active: selectedSanctionId === item.id }" :class="{ active: selectedSanctionId === item.id }"
@click="selectSanction(item)" @click="selectSanction(item)"
> >
{{ item.name }} <div class="sanction-name">
{{ item.name }}
</div>
<div class="sanction-type">{{ item.postDate }}</div> <div class="sanction-type">{{ item.postDate }}</div>
</div> </div>
</div> </div>
...@@ -108,6 +110,7 @@ import router from "@/router"; ...@@ -108,6 +110,7 @@ import router from "@/router";
// 处理点击实体清单原文按钮 // 处理点击实体清单原文按钮
const handleClickOriginalText = () => { const handleClickOriginalText = () => {
// 打开新标签页 // 打开新标签页
window.open(`/exportControl/origin?id=${sanRecordId.value}`, "_blank"); window.open(`/exportControl/origin?id=${sanRecordId.value}`, "_blank");
}; };
...@@ -206,13 +209,14 @@ const totalElements = ref(0); ...@@ -206,13 +209,14 @@ const totalElements = ref(0);
const openSanctionModal = async () => { const openSanctionModal = async () => {
sanctionModalVisible.value = true; sanctionModalVisible.value = true;
console.log("制裁事件列表11:", sanctionList.value); console.log("制裁事件列表11:", sanctionList.value);
loading.value = true;
await fetchSanctionData(); await fetchSanctionData();
}; };
// ========== 获取制裁数据 ========== // ========== 获取制裁数据 ==========
const fetchSanctionData = async () => { const fetchSanctionData = async () => {
try { try {
loading.value = true;
const res = await getSanctionProcess([1], currentPage.value, 10); const res = await getSanctionProcess([1], currentPage.value, 10);
loading.value = false; loading.value = false;
if (res && !!res.content) { if (res && !!res.content) {
...@@ -254,6 +258,7 @@ const selectSanction = async item => { ...@@ -254,6 +258,7 @@ const selectSanction = async item => {
sanctionModalVisible.value = false; sanctionModalVisible.value = false;
console.log("跳转URL:", window.location.href); console.log("跳转URL:", window.location.href);
// 根据最新URL参数刷新当前页面 // 根据最新URL参数刷新当前页面
window.sessionStorage.setItem("curTabName", item.postDate + " 《实体清单新增条目》");
window.open(`${window.location.pathname}?id=${item.id}&sanTypeId=${item.sanTypeId}`, "_self"); window.open(`${window.location.pathname}?id=${item.id}&sanTypeId=${item.sanTypeId}`, "_self");
}; };
...@@ -274,15 +279,11 @@ onMounted(() => { ...@@ -274,15 +279,11 @@ onMounted(() => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
* {
margin: 0;
padding: 0;
}
.entity-list { .entity-list {
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow-y: auto; overflow-y: auto;
padding-bottom: 50px; padding-bottom: 0px;
.header { .header {
width: 100%; width: 100%;
height: 148px; height: 148px;
...@@ -464,8 +465,15 @@ onMounted(() => { ...@@ -464,8 +465,15 @@ onMounted(() => {
.sanction-list { .sanction-list {
max-height: 400px; max-height: 400px;
min-height: 400px;
overflow-y: auto; overflow-y: auto;
padding: 0 10px; padding: 0 10px;
.sanction-name {
max-width: 85%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
} }
.sanction-item { .sanction-item {
......
...@@ -15,26 +15,21 @@ ...@@ -15,26 +15,21 @@
<div class="header-right"> <div class="header-right">
<!-- 中英文切换开关 --> <!-- 中英文切换开关 -->
<div class="toggle-group"> <div class="toggle-group">
<span :class="{ active: !showChinese }">英文</span> <!-- <span :class="{ active: !showChinese }">英文</span> -->
<el-switch <el-switch v-model="showChinese" @change="handleToggleChange" />
v-model="showChinese" <img :src="transIcon" alt="" />
active-text="中" <span :class="{ active: showChinese }">显示原文</span>
inactive-text="英"
:inline-prompt="true"
@change="handleToggleChange"
/>
<span :class="{ active: showChinese }">中文</span>
</div> </div>
<!-- 下载按钮 --> <!-- 下载按钮 -->
<el-button type="primary" :icon="Download" @click="handleDownload"> 下载 </el-button> <el-button plain :icon="Download" @click="handleDownload"> 下载 </el-button>
</div> </div>
</div> </div>
<!-- 外层滚动容器,统一控制两侧滚动 --> <!-- 外层滚动容器,统一控制两侧滚动 -->
<div class="report-box" ref="reportBoxRef"> <div class="report-box" ref="reportBoxRef">
<div class="pdf-pane-wrap" :class="{ 'center-mode': !showChinese }"> <div class="pdf-pane-wrap" v-if="showChinese" :class="{ 'center-mode': !showChinese }">
<pdf ref="leftPdfRef" :pdfUrl="headerTitle.srcUrl" class="pdf-pane-inner" /> <pdf ref="leftPdfRef" :pdfUrl="headerTitle.srcUrl" class="pdf-pane-inner" />
</div> </div>
<div class="pdf-pane-wrap" v-if="showChinese"> <div class="pdf-pane-wrap">
<pdf ref="rightPdfRef" :pdfUrl="headerTitle.transUrl" class="pdf-pane-inner" /> <pdf ref="rightPdfRef" :pdfUrl="headerTitle.transUrl" class="pdf-pane-inner" />
</div> </div>
</div> </div>
...@@ -47,6 +42,7 @@ import { ref, onMounted, watch, computed } from "vue"; ...@@ -47,6 +42,7 @@ import { ref, onMounted, watch, computed } from "vue";
import { Download } from "@element-plus/icons-vue"; import { Download } from "@element-plus/icons-vue";
import { getSingleSanctionOverview } from "@/api/exportControlV2.0.js"; import { getSingleSanctionOverview } from "@/api/exportControlV2.0.js";
import title from "../assets/title.png"; import title from "../assets/title.png";
import transIcon from "../assets/icon-translation.png";
import pdf from "./pdf.vue"; import pdf from "./pdf.vue";
const leftPdfRef = ref(null); const leftPdfRef = ref(null);
...@@ -299,15 +295,15 @@ onMounted(() => { ...@@ -299,15 +295,15 @@ onMounted(() => {
} }
} }
:deep(.el-button) { // :deep(.el-button) {
--el-button-bg-color: #055fc2; // --el-button-bg-color: #055fc2;
--el-button-border-color: #055fc2; // --el-button-border-color: #055fc2;
--el-button-hover-bg-color: #044c9b; // --el-button-hover-bg-color: #044c9b;
--el-button-hover-border-color: #044c9b; // --el-button-hover-border-color: #044c9b;
font-size: 14px; // font-size: 14px;
padding: 10px 20px; // padding: 10px 20px;
} // }
} }
} }
...@@ -318,6 +314,8 @@ onMounted(() => { ...@@ -318,6 +314,8 @@ onMounted(() => {
display: flex; display: flex;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
// ✅ 添加居中对齐
justify-content: center;
} }
.pdf-pane-wrap { .pdf-pane-wrap {
...@@ -330,6 +328,8 @@ onMounted(() => { ...@@ -330,6 +328,8 @@ onMounted(() => {
&.center-mode { &.center-mode {
flex: 0 0 100%; flex: 0 0 100%;
max-width: 100%; max-width: 100%;
// ✅ 添加居中样式
width: 728px; // 约一半宽度,保持单栏时美观
margin: 0 auto; margin: 0 auto;
} }
} }
......
...@@ -17,7 +17,6 @@ import PdfWorker from "pdfjs-dist/legacy/build/pdf.worker.min?worker"; ...@@ -17,7 +17,6 @@ import PdfWorker from "pdfjs-dist/legacy/build/pdf.worker.min?worker";
// 使用 Vite 的 ?worker 直接注入 Worker,避免线上 mjs MIME 类型问题 // 使用 Vite 的 ?worker 直接注入 Worker,避免线上 mjs MIME 类型问题
pdfjsLib.GlobalWorkerOptions.workerPort = new PdfWorker(); pdfjsLib.GlobalWorkerOptions.workerPort = new PdfWorker();
export default { export default {
name: "PdfViewer", name: "PdfViewer",
props: { props: {
...@@ -33,7 +32,6 @@ export default { ...@@ -33,7 +32,6 @@ export default {
const loading = ref(true); const loading = ref(true);
const renderedPageCount = ref(0); const renderedPageCount = ref(0);
let resolveRenderAll = null; let resolveRenderAll = null;
const waitAllPagesRendered = () => { const waitAllPagesRendered = () => {
if (pageCount.value > 0 && renderedPageCount.value >= pageCount.value) { if (pageCount.value > 0 && renderedPageCount.value >= pageCount.value) {
return Promise.resolve(); return Promise.resolve();
...@@ -42,12 +40,14 @@ export default { ...@@ -42,12 +40,14 @@ export default {
resolveRenderAll = resolve; resolveRenderAll = resolve;
}); });
}; };
// pdfjs 的 document 对象内部使用 #private 字段,
// pdfjs 的 document 对象内部使用 #private 字段,用 shallowRef 保持为原始对象引用 // 若被 Vue 响应式深度代理会触发 "Cannot read from private field"。
// 因此用 shallowRef 保持为原始对象引用。
const pdfDocRef = shallowRef(null); const pdfDocRef = shallowRef(null);
const searchKey = ref(""); const searchKey = ref("");
const matchList = ref([]); const matchList = ref([]);
const matchIdx = ref(0); const matchIdx = ref(0);
// pdfjs 3.x 的 renderTextLayer 在不同入口下导出不一致,这里做一次缓存 + 兜底加载
const pdfjsApiRef = shallowRef(pdfjsLib); const pdfjsApiRef = shallowRef(pdfjsLib);
// 保存 canvas // 保存 canvas
...@@ -69,7 +69,7 @@ export default { ...@@ -69,7 +69,7 @@ export default {
return urlPart; return urlPart;
}; };
// 清空所有高亮 // 清空所有高亮(不销毁 textLayer)
const clearHighlights = () => { const clearHighlights = () => {
Object.values(overlayMap).forEach(layer => { Object.values(overlayMap).forEach(layer => {
if (!layer) return; if (!layer) return;
...@@ -78,7 +78,7 @@ export default { ...@@ -78,7 +78,7 @@ export default {
}); });
}; };
// 重置搜索状态 // 重置搜索状态:清空关键词、匹配列表与高亮
const clearSearch = () => { const clearSearch = () => {
searchKey.value = ""; searchKey.value = "";
matchList.value = []; matchList.value = [];
...@@ -86,7 +86,7 @@ export default { ...@@ -86,7 +86,7 @@ export default {
clearHighlights(); clearHighlights();
}; };
// 渲染单页 PDF // 渲染单页 PDF(canvas + textLayer)
const renderPage = async (pdf, pageNum) => { const renderPage = async (pdf, pageNum) => {
const pdfPage = await pdf.getPage(pageNum); const pdfPage = await pdf.getPage(pageNum);
const canvas = canvasMap[pageNum]; const canvas = canvasMap[pageNum];
...@@ -94,6 +94,7 @@ export default { ...@@ -94,6 +94,7 @@ export default {
if (!canvas || !textLayer) return; if (!canvas || !textLayer) return;
// 以画布的可视宽度为基准自适应缩放,避免 CSS 强行拉伸导致 textLayer/高亮错位
const baseViewport = pdfPage.getViewport({ scale: 1 }); const baseViewport = pdfPage.getViewport({ scale: 1 });
const desiredWidth = canvas.clientWidth || 726; const desiredWidth = canvas.clientWidth || 726;
const scale = desiredWidth / baseViewport.width; const scale = desiredWidth / baseViewport.width;
...@@ -102,19 +103,23 @@ export default { ...@@ -102,19 +103,23 @@ export default {
const context = canvas.getContext("2d"); const context = canvas.getContext("2d");
canvas.width = viewport.width; canvas.width = viewport.width;
canvas.height = viewport.height; canvas.height = viewport.height;
// 保证 canvas 不再被 CSS 拉伸,和 textLayer 共享同一坐标系
canvas.style.width = `${viewport.width}px`; canvas.style.width = `${viewport.width}px`;
canvas.style.height = `${viewport.height}px`; canvas.style.height = `${viewport.height}px`;
textLayer.style.width = canvas.width + "px"; textLayer.style.width = canvas.width + "px";
textLayer.style.height = canvas.height + "px"; textLayer.style.height = canvas.height + "px";
textLayer.innerHTML = ""; textLayer.innerHTML = "";
// pdf.js v5 text layer 依赖 scale-factor 参与定位计算
textLayer.style.setProperty("--scale-factor", String(viewport.scale || 1)); textLayer.style.setProperty("--scale-factor", String(viewport.scale || 1));
await pdfPage.render({ canvasContext: context, viewport }).promise; await pdfPage.render({ canvasContext: context, viewport }).promise;
// 渲染 textLayer(pdfjs-dist 3.x):使用 renderTextLayer(不要用 TextLayer 构造器)
try { try {
const textContent = await pdfPage.getTextContent(); const textContent = await pdfPage.getTextContent();
let api = pdfjsApiRef.value || pdfjsLib; let api = pdfjsApiRef.value || pdfjsLib;
let rt = api?.renderTextLayer; let rt = api?.renderTextLayer;
// 兜底:某些入口下 renderTextLayer 不在 pdfjsLib 上,尝试 legacy 入口
if (typeof rt !== "function") { if (typeof rt !== "function") {
try { try {
const legacy = await import("pdfjs-dist/legacy/build/pdf"); const legacy = await import("pdfjs-dist/legacy/build/pdf");
...@@ -128,6 +133,7 @@ export default { ...@@ -128,6 +133,7 @@ export default {
textContent, textContent,
container: textLayer, container: textLayer,
viewport, viewport,
// pdfjs 3.x 需要传入 textDivs 数组
textDivs: [], textDivs: [],
enhanceTextSelection: false enhanceTextSelection: false
}).promise; }).promise;
...@@ -175,7 +181,7 @@ export default { ...@@ -175,7 +181,7 @@ export default {
} }
}; };
// 搜索关键词 + 高亮 // 搜索关键词 + 高亮(记录每个命中的子串范围)
const doSearch = async () => { const doSearch = async () => {
const doc = pdfDocRef.value; const doc = pdfDocRef.value;
const key = searchKey.value.trim(); const key = searchKey.value.trim();
...@@ -184,6 +190,7 @@ export default { ...@@ -184,6 +190,7 @@ export default {
matchIdx.value = 0; matchIdx.value = 0;
if (!doc || !key) return; if (!doc || !key) return;
// 首次搜索时确保所有页的 textLayer 已渲染完成,避免“越搜越多”
await waitAllPagesRendered(); await waitAllPagesRendered();
for (let pageNum = 1; pageNum <= doc.numPages; pageNum++) { for (let pageNum = 1; pageNum <= doc.numPages; pageNum++) {
...@@ -214,7 +221,7 @@ export default { ...@@ -214,7 +221,7 @@ export default {
const el = m?.el; const el = m?.el;
if (!el) return; if (!el) return;
clearHighlights(); clearHighlights();
// 用 Range 精确计算“子串”在页面上的矩形位置,再画黄色块,避免把整段 span 都标黄
const textNode = el.firstChild; const textNode = el.firstChild;
if (textNode && textNode.nodeType === Node.TEXT_NODE) { if (textNode && textNode.nodeType === Node.TEXT_NODE) {
try { try {
...@@ -242,7 +249,7 @@ export default { ...@@ -242,7 +249,7 @@ export default {
} }
} }
// 滚动到匹配位置 // 优先只滚动右侧 report-box,避免触发整页滚动导致 header 遮挡
const container = el.closest(".report-box"); const container = el.closest(".report-box");
if (container) { if (container) {
const TOP_OFFSET = 72; const TOP_OFFSET = 72;
...@@ -285,12 +292,6 @@ export default { ...@@ -285,12 +292,6 @@ export default {
} }
}; };
// 获取容器元素(用于同步滚动)
const getContainer = () => {
const firstCanvas = canvasMap[1];
return firstCanvas ? firstCanvas.closest(".report-box") : null;
};
watch( watch(
() => props.pdfUrl, () => props.pdfUrl,
newVal => { newVal => {
...@@ -313,8 +314,7 @@ export default { ...@@ -313,8 +314,7 @@ export default {
matchIdx, matchIdx,
searchKeyword, searchKeyword,
clearSearch, clearSearch,
goToPage, goToPage
getContainer
}; };
} }
}; };
...@@ -349,11 +349,13 @@ canvas { ...@@ -349,11 +349,13 @@ canvas {
line-height: 1; line-height: 1;
} }
/* 不展示整页“文字层”,只在命中时显示黄色背景 */
.textLayer :deep(span) { .textLayer :deep(span) {
position: absolute; position: absolute;
transform-origin: 0% 0%; transform-origin: 0% 0%;
white-space: pre; white-space: pre;
line-height: 1; line-height: 1;
/* pdf.js v5 TextLayer:用变量计算真实字形盒子尺寸,否则背景宽高会不准 */
font-size: calc(var(--font-height, 0px) * var(--scale-factor, 1)); font-size: calc(var(--font-height, 0px) * var(--scale-factor, 1));
transform: scaleX(var(--scale-x, 1)); transform: scaleX(var(--scale-x, 1));
color: transparent; color: transparent;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<SearchContainer <SearchContainer
style="margin-bottom: 0; margin-top: 48px; height: fit-content" style="margin-bottom: 0; margin-top: 48px; height: fit-content"
v-if="homeMainRef" v-if="homeMainRef"
placeholder="搜索出口管制" placeholder="搜索投融资限制"
:containerRef="homeMainRef" :containerRef="homeMainRef"
areaName="实体清单" areaName="实体清单"
/> />
......
...@@ -628,6 +628,9 @@ onMounted(async () => { ...@@ -628,6 +628,9 @@ onMounted(async () => {
.search-input { .search-input {
flex: 1; flex: 1;
border: 1px solid #ddd;
border-radius: 4px;
height: 32px;
} }
} }
......
...@@ -1053,6 +1053,9 @@ onMounted(async () => { ...@@ -1053,6 +1053,9 @@ onMounted(async () => {
.search-input { .search-input {
width: 288px; width: 288px;
border: 1px solid #ddd;
border-radius: 4px;
height: 32px;
:deep(.el-input__wrapper) { :deep(.el-input__wrapper) {
height: 32px; height: 32px;
......
...@@ -613,11 +613,6 @@ onMounted(() => { ...@@ -613,11 +613,6 @@ onMounted(() => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
// * {
// margin: 0;
// padding: 0;
// }
.sanctions-overview { .sanctions-overview {
width: 1601px; width: 1601px;
margin: 0 auto; margin: 0 auto;
...@@ -960,7 +955,7 @@ onMounted(() => { ...@@ -960,7 +955,7 @@ onMounted(() => {
margin-bottom: 20px; margin-bottom: 20px;
:deep(.el-input__inner) { :deep(.el-input__inner) {
font-size: 16px; font-size: 14px;
font-weight: 400; font-weight: 400;
font-family: "Microsoft YaHei"; font-family: "Microsoft YaHei";
line-height: 24px; line-height: 24px;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论