提交 c3dec961 authored 作者: coderBryanFu's avatar coderBryanFu

fix:更新goToPage.js文件部分跳转方法

流水线 #611 已通过 于阶段
in 1 分 43 秒
...@@ -105,19 +105,11 @@ const setChart = (option, chartId, allowClick, selectParam, otherAreaList) => { ...@@ -105,19 +105,11 @@ const setChart = (option, chartId, allowClick, selectParam, otherAreaList) => {
const year = params.name.slice(0, 4) const year = params.name.slice(0, 4)
const quatarNum = Number(params.name[params.name.length - 1]) const quatarNum = Number(params.name[params.name.length - 1])
selectParam.selectedDate = JSON.stringify(getQuarterRange(year, quatarNum)) selectParam.selectedDate = JSON.stringify(getQuarterRange(year, quatarNum))
const route = router.resolve({ openDataThinkTank(selectParam);
path: "/dataLibrary/dataThinkTank",
query: selectParam
});
window.open(route.href, "_blank");
return return
} else if (selectParam.key === 2) { } else if (selectParam.key === 2) {
selectParam.domains = params.name selectParam.domains = params.name
const route = router.resolve({ openDataThinkTank(selectParam);
path: "/dataLibrary/dataThinkTank",
query: selectParam
});
window.open(route.href, "_blank");
return return
} }
} }
......
...@@ -18,7 +18,29 @@ import { getCharacterGlobalInfo } from "@/api/characterPage/characterPage.js"; ...@@ -18,7 +18,29 @@ import { getCharacterGlobalInfo } from "@/api/characterPage/characterPage.js";
// 获取路由参数,1为科技领袖,2为国会议员,3为智库研究人员 // 获取路由参数,1为科技领袖,2为国会议员,3为智库研究人员
const route = useRoute(); const route = useRoute();
const type = ref(route.query.type || 1); const type = ref(route.query.type || 1);
const personId = ref(route.query.personId || "Y000064"); const decodeMaybeBase64 = (raw) => {
if (raw == null) return null;
const s0 = String(raw).trim();
if (!s0) return null;
// 明文 personId(如 Y000064)保持原样,避免误解码
if (/^[A-Za-z]\d{6,}$/.test(s0) || /^Y\d+/i.test(s0)) {
return s0;
}
if (s0.length >= 12 && /^[A-Za-z0-9+/_-]+={0,2}$/.test(s0)) {
try {
const normalized = s0.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
const decoded = atob(padded);
try {
return decodeURIComponent(decoded);
} catch (_) {
return decoded;
}
} catch (_) { }
}
return s0;
};
const personId = ref(decodeMaybeBase64(route.query.personId) || "Y000064");
// 获取人物全局信息 // 获取人物全局信息
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
</div> </div>
</div> </div>
</div> --> </div> -->
<NewsList :newsList="leftList" @item-click="item => gotoNewsDetail(item.id)" @more-click="handleToMoreNews" <NewsList :newsList="leftList" @item-click="item => gotoNewsDetail(encodeBase64Param(item.id))" @more-click="handleToMoreNews"
img="image" title="title" content="content" from="from" /> img="image" title="title" content="content" from="from" />
<MessageBubble :messageList="rightList" imageUrl="personImage" @more-click="handleToSocialDetail" <MessageBubble :messageList="rightList" imageUrl="personImage" @more-click="handleToSocialDetail"
@person-click="handleToSocialDetail" name="name" content="content" source="orgName" image-url="image" /> @person-click="handleToSocialDetail" name="name" content="content" source="orgName" image-url="image" />
...@@ -63,6 +63,16 @@ import title03bg from './assets/title03bg.png' ...@@ -63,6 +63,16 @@ import title03bg from './assets/title03bg.png'
import { useGotoNewsDetail } from '@/router/modules/news'; import { useGotoNewsDetail } from '@/router/modules/news';
const gotoNewsDetail = useGotoNewsDetail() const gotoNewsDetail = useGotoNewsDetail()
const encodeBase64Param = (val) => {
const s = String(val ?? "").trim();
if (!s) return "";
try {
return btoa(encodeURIComponent(s));
} catch (_) {
return s;
}
};
// 合作限制-查询社交媒体接口 // 合作限制-查询社交媒体接口
const getCoopRestrictionSocialData = async () => { const getCoopRestrictionSocialData = async () => {
try { try {
...@@ -139,10 +149,12 @@ const handleToNewsDetail = (item) => { ...@@ -139,10 +149,12 @@ const handleToNewsDetail = (item) => {
} }
// 查看社交媒体详情 // 查看社交媒体详情
const handleToSocialDetail = (item) => { const handleToSocialDetail = (item) => {
const encodedPersonId = encodeBase64Param(item?.id);
if (!encodedPersonId) return;
const route = router.resolve({ const route = router.resolve({
path: "/characterPage", path: "/characterPage",
query: { query: {
personId: item.id personId: encodedPersonId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
......
...@@ -207,10 +207,16 @@ const handleClickToDetail = item => { ...@@ -207,10 +207,16 @@ const handleClickToDetail = item => {
const id = activeItem?.ID || activeItem?.id || activeItem?.limitId; const id = activeItem?.ID || activeItem?.id || activeItem?.limitId;
if (!id) return; if (!id) return;
window.sessionStorage.setItem("cooperationRestrictionsTabName", activeItem?.LIMITNAME || ""); window.sessionStorage.setItem("cooperationRestrictionsTabName", activeItem?.LIMITNAME || "");
const encodedId = (() => {
const s = String(id).trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const curRoute = router.resolve({ const curRoute = router.resolve({
name: "CooperationRestrictionsDetail", name: "CooperationRestrictionsDetail",
query: { id: id } query: { id: encodedId }
}); });
window.open(curRoute.href, "_blank"); window.open(curRoute.href, "_blank");
}; };
...@@ -219,9 +225,15 @@ const handleClickToDetail = item => { ...@@ -219,9 +225,15 @@ const handleClickToDetail = item => {
const handleToRiskDetail = (item) => { const handleToRiskDetail = (item) => {
const id = item?.cooperationId || item?.ID || item?.id || item?.limitId; const id = item?.cooperationId || item?.ID || item?.id || item?.limitId;
if (!id) return; if (!id) return;
const encodedId = (() => {
const s = String(id).trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const curRoute = router.resolve({ const curRoute = router.resolve({
name: "CooperationRestrictionsDetail", name: "CooperationRestrictionsDetail",
query: { id }, query: { id: encodedId },
}); });
window.open(curRoute.href, "_blank"); window.open(curRoute.href, "_blank");
}; };
......
...@@ -138,6 +138,15 @@ const getMainDataList = async () => { ...@@ -138,6 +138,15 @@ const getMainDataList = async () => {
const router = useRouter(); const router = useRouter();
const encodeBase64Param = (val) => {
const s = String(val ?? "").trim();
if (!s) return "";
try {
return btoa(encodeURIComponent(s));
} catch (_) {
return s;
}
};
const handleClick = item => { const handleClick = item => {
const id = item?.id || item?.limitId || item?.ID; const id = item?.id || item?.limitId || item?.ID;
if (!id) return; if (!id) return;
...@@ -145,10 +154,12 @@ const handleClick = item => { ...@@ -145,10 +154,12 @@ const handleClick = item => {
"cooperationRestrictionsTabName", "cooperationRestrictionsTabName",
item?.limitName || item?.title || item?.name || "" item?.limitName || item?.title || item?.name || ""
); );
const encodedId = encodeBase64Param(id);
if (!encodedId) return;
const routeData = router.resolve({ const routeData = router.resolve({
name: "CooperationRestrictionsDetail", name: "CooperationRestrictionsDetail",
query: { query: {
id id: encodedId
} }
}); });
window.open(routeData.href, "_blank"); window.open(routeData.href, "_blank");
......
...@@ -106,6 +106,28 @@ import { getCoopRestrictionIntroduction, getCoopRestrictionRelated, getCoopRestr ...@@ -106,6 +106,28 @@ import { getCoopRestrictionIntroduction, getCoopRestrictionRelated, getCoopRestr
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const decodeQueryId = (raw) => {
if (raw == null) return null;
const s0 = String(raw).trim();
if (!s0) return null;
// 明文数字直接返回
if (/^\d+$/.test(s0)) return s0;
// base64(encodeURIComponent(id)) 解码(兼容短 base64:Mg==)
if (/^[A-Za-z0-9+/_-]+={0,2}$/.test(s0)) {
try {
const normalized = s0.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
const decoded = atob(padded);
try {
return decodeURIComponent(decoded);
} catch (_) {
return decoded;
}
} catch (_) { }
}
return s0;
};
const limitId = computed(() => decodeQueryId(route.query?.id));
import defaultImg from "./assets/image01.png" import defaultImg from "./assets/image01.png"
import defaultCom from "../assets/images/default-icon2.png" import defaultCom from "../assets/images/default-icon2.png"
import Harvard from "./assets/哈佛.png"; import Harvard from "./assets/哈佛.png";
...@@ -130,10 +152,11 @@ const handleOpenWrittingAsstaint = () => { ...@@ -130,10 +152,11 @@ const handleOpenWrittingAsstaint = () => {
// 合作限制-查询限制条款 // 合作限制-查询限制条款
const limitClauseData = ref([]); const limitClauseData = ref([]);
const getlimitClauseData = async () => { const getlimitClauseData = async () => {
if (!route.query.id) return; const id = limitId.value;
if (!id) return;
try { try {
const res = await getCoopRestrictionClause({ const res = await getCoopRestrictionClause({
limitId: route.query.id limitId: id
}); });
if (res && res.code === 200) { if (res && res.code === 200) {
// 兼容后端返回:数组 / 单对象 / 包一层 data // 兼容后端返回:数组 / 单对象 / 包一层 data
...@@ -153,10 +176,11 @@ const getlimitClauseData = async () => { ...@@ -153,10 +176,11 @@ const getlimitClauseData = async () => {
// 合作限制-查询背景分析 // 合作限制-查询背景分析
const backgroundList = ref([]); const backgroundList = ref([]);
const getbackgroundData = async () => { const getbackgroundData = async () => {
if (!route.query.id) return; const id = limitId.value;
if (!id) return;
try { try {
const res = await getCoopRestrictionBackground({ const res = await getCoopRestrictionBackground({
limitId: route.query.id limitId: id
}); });
if (res && res.code === 200) { if (res && res.code === 200) {
backgroundList.value = res.data || []; backgroundList.value = res.data || [];
...@@ -174,10 +198,11 @@ const getbackgroundData = async () => { ...@@ -174,10 +198,11 @@ const getbackgroundData = async () => {
// 合作限制-查询相关实体 // 合作限制-查询相关实体
const coopRelatedData = ref([]); const coopRelatedData = ref([]);
const getcoopRelatedData = async () => { const getcoopRelatedData = async () => {
if (!route.query.id) return; const id = limitId.value;
if (!id) return;
try { try {
const res = await getCoopRestrictionRelated({ const res = await getCoopRestrictionRelated({
limitId: route.query.id limitId: id
}); });
if (res && res.code === 200) { if (res && res.code === 200) {
// 展示图片:优先后端返回的 imageUrl,其次用已有 img 字段,再兜底默认图 // 展示图片:优先后端返回的 imageUrl,其次用已有 img 字段,再兜底默认图
...@@ -200,7 +225,17 @@ const handleClickOnEntity = (item) => { ...@@ -200,7 +225,17 @@ const handleClickOnEntity = (item) => {
if (entityType === "P") { if (entityType === "P") {
const personId = item?.PERSONID || item?.ENTITYID || item?.id; const personId = item?.PERSONID || item?.ENTITYID || item?.id;
if (!personId) return; if (!personId) return;
const url = `http://localhost:3000/characterPage?type=2&personId=${encodeURIComponent(personId)}`; const encodedPersonId = (() => {
const s = String(personId ?? "").trim();
if (!s) return "";
try {
return btoa(encodeURIComponent(s));
} catch (_) {
return s;
}
})();
if (!encodedPersonId) return;
const url = `http://localhost:3000/characterPage?type=2&personId=${encodeURIComponent(encodedPersonId)}`;
window.open(url, "_blank"); window.open(url, "_blank");
return; return;
} }
...@@ -216,10 +251,11 @@ const handleClickOnEntity = (item) => { ...@@ -216,10 +251,11 @@ const handleClickOnEntity = (item) => {
// 合作限制-查询简介接口 // 合作限制-查询简介接口
const coopData = ref({}); const coopData = ref({});
const getCoopRestrictionIntroductionData = async () => { const getCoopRestrictionIntroductionData = async () => {
if (!route.query.id) return; const id = limitId.value;
if (!id) return;
try { try {
const res = await getCoopRestrictionIntroduction({ const res = await getCoopRestrictionIntroduction({
limitId: route.query.id limitId: id
}); });
if (res && res.code === 200) { if (res && res.code === 200) {
coopData.value = res.data || {}; coopData.value = res.data || {};
...@@ -239,13 +275,19 @@ const handleClick = () => { ...@@ -239,13 +275,19 @@ const handleClick = () => {
let path = ""; let path = "";
let query = {}; let query = {};
const encodedRelationId = (() => {
const s = String(relation.RELATIONID ?? "").trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedRelationId) return;
if (relation.TYPE === "行政令") { if (relation.TYPE === "行政令") {
path = "/decreeLayout/overview/introduction"; path = "/decreeLayout/overview/introduction";
query = { id: relation.RELATIONID }; query = { id: encodedRelationId };
} else if (relation.TYPE === "法案") { } else if (relation.TYPE === "法案") {
path = "/billLayout/bill/introduction"; path = "/billLayout/bill/introduction";
query = { billId: relation.RELATIONID }; query = { billId: encodedRelationId };
} }
if (path) { if (path) {
...@@ -264,7 +306,7 @@ const handleClickOnLimitOrg = () => { ...@@ -264,7 +306,7 @@ const handleClickOnLimitOrg = () => {
// 监听路由 id 变化,自动刷新数据 // 监听路由 id 变化,自动刷新数据
watch( watch(
() => route.query.id, () => limitId.value,
(newId) => { (newId) => {
if (newId) { if (newId) {
getCoopRestrictionIntroductionData(); getCoopRestrictionIntroductionData();
......
...@@ -172,6 +172,7 @@ import InputBox from "../components/InputBox/index.vue"; ...@@ -172,6 +172,7 @@ import InputBox from "../components/InputBox/index.vue";
import DataChartSwitchBox from '../components/dataChartSwitchBox/index.vue' import DataChartSwitchBox from '../components/dataChartSwitchBox/index.vue'
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import router from "@/router"; import router from "@/router";
import { getDecodedParams } from "@/utils/goToPage";
import { search, getThinkTankList } from "@/api/comprehensiveSearch"; import { search, getThinkTankList } from "@/api/comprehensiveSearch";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
...@@ -912,29 +913,31 @@ const handleDownloadCurChartData = () => { ...@@ -912,29 +913,31 @@ const handleDownloadCurChartData = () => {
const initParam = () => { const initParam = () => {
const hasQuery = Object.keys(route.query).length > 0; const hasQuery = Object.keys(route.query).length > 0;
if (hasQuery) { if (hasQuery) {
if (route.query.selectedAreaList) { const decodedQuery = route.query.data ? (getDecodedParams() || {}) : null;
selectedArea.value = JSON.parse(route.query.selectedAreaList) const query = decodedQuery && typeof decodedQuery === "object" ? decodedQuery : route.query;
if (query.selectedAreaList) {
selectedArea.value = JSON.parse(query.selectedAreaList)
} else { } else {
selectedArea.value = route.query.domains ? [route.query.domains] : ['全部领域'] selectedArea.value = query.domains ? [query.domains] : ['全部领域']
} }
if ( if (
route.query.selectedDate && query.selectedDate &&
Array.isArray(JSON.parse(route.query.selectedDate)) && Array.isArray(JSON.parse(query.selectedDate)) &&
JSON.parse(route.query.selectedDate).length JSON.parse(query.selectedDate).length
) { ) {
selectedDate.value = "自定义"; selectedDate.value = "自定义";
customTime.value = JSON.parse(route.query.selectedDate); customTime.value = JSON.parse(query.selectedDate);
} }
selectedThinkTank.value = route.query.orgnizationName ? route.query.orgnizationName : "全部智库"; selectedThinkTank.value = query.orgnizationName ? query.orgnizationName : "全部智库";
isInvolveCn.value = route.query.isInvolveCn ? true : false; isInvolveCn.value = query.isInvolveCn ? true : false;
reportName.value = route.query.reportName ? route.query.reportName : ""; reportName.value = query.reportName ? query.reportName : "";
const query = route.query; if (query && Object.keys(query).length > 0) {
if (Object.keys(query).length > 0) {
sessionStorage.setItem("thinktankRouteQuery", JSON.stringify(query)); sessionStorage.setItem("thinktankRouteQuery", JSON.stringify(query));
} }
} else { } else {
...@@ -958,16 +961,28 @@ const initParam = () => { ...@@ -958,16 +961,28 @@ const initParam = () => {
} }
}; };
// 跳转政令详情 const encodeBase64Param = (val) => {
const s = String(val ?? "").trim();
if (!s) return "";
try {
return btoa(encodeURIComponent(s));
} catch (_) {
return s;
}
};
// 跳转报告详情
const handleClickToDetail = curReport => { const handleClickToDetail = curReport => {
console.log("curReport", curReport); console.log("curReport", curReport);
window.sessionStorage.setItem("billId", curReport.id); window.sessionStorage.setItem("billId", curReport.id);
window.sessionStorage.setItem("curTabName", curReport.title); window.sessionStorage.setItem("curTabName", curReport.title);
const encodedId = encodeBase64Param(curReport?.id);
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "ReportDetail", name: "ReportDetail",
params: { params: {
id: curReport.id id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted, onBeforeUnmount, reactive } from "vue"; import { ref, onMounted, onBeforeUnmount, reactive, computed } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import router from "@/router"; import router from "@/router";
import * as G6 from '@antv/g6'; import * as G6 from '@antv/g6';
...@@ -63,6 +63,34 @@ import icon1629 from "./assets/icons/icon1629.png"; ...@@ -63,6 +63,34 @@ import icon1629 from "./assets/icons/icon1629.png";
const route = useRoute(); const route = useRoute();
const decodeMaybeBase64NumericId = (raw) => {
if (raw == null) return "";
let s0 = String(raw).trim();
if (!s0) return "";
if (s0.includes("%")) {
try {
const decodedOnce = decodeURIComponent(s0);
if (decodedOnce) s0 = String(decodedOnce).trim();
} catch (_) { }
}
if (/^\d+$/.test(s0)) return s0;
if (/^[A-Za-z0-9+/_-]+={0,2}$/.test(s0)) {
try {
const normalized = s0.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
const decoded = atob(padded);
const decodedStr = (() => {
try { return decodeURIComponent(decoded); } catch (_) { return decoded; }
})();
if (/^\d+$/.test(String(decodedStr).trim())) {
return String(decodedStr).trim();
}
} catch (_) { }
}
return s0;
};
const decreeId = computed(() => decodeMaybeBase64NumericId(route.query.id));
// 关联关系 // 关联关系
const dialogVisible = ref(false); const dialogVisible = ref(false);
...@@ -71,12 +99,14 @@ const mainInfo = ref({ label: "", time: "", id: "" }); ...@@ -71,12 +99,14 @@ const mainInfo = ref({ label: "", time: "", id: "" });
const nodeInfo = ref({}); const nodeInfo = ref({});
const onDecreeSummaryData = async () => { const onDecreeSummaryData = async () => {
try { try {
const res = await getDecreeSummary({id: route.query.id}); const id = decreeId.value;
if (!id) return;
const res = await getDecreeSummary({id});
console.log("基本信息", res); console.log("基本信息", res);
if (res.code===200 && res.data) { if (res.code===200 && res.data) {
mainInfo.value.label = res.data.name; mainInfo.value.label = res.data.name;
mainInfo.value.time = res.data.postDate; mainInfo.value.time = res.data.postDate;
mainInfo.value.id = route.query.id; mainInfo.value.id = id;
} }
} catch (error) { } catch (error) {
mainInfo.value = { label: "", time: "", id: "" }; mainInfo.value = { label: "", time: "", id: "" };
...@@ -93,7 +123,9 @@ const handleClickSider = async (item) => { ...@@ -93,7 +123,9 @@ const handleClickSider = async (item) => {
}; };
const handleGetRelateOrder = async () => { const handleGetRelateOrder = async () => {
try { try {
const res = await getDecreeRelatedOrder({id: route.query.id}); const id = decreeId.value;
if (!id) return;
const res = await getDecreeRelatedOrder({id});
console.log("相关政令", res); console.log("相关政令", res);
if (res.code===200 && res.data?.length) { if (res.code===200 && res.data?.length) {
siderList.value = res.data siderList.value = res.data
...@@ -140,7 +172,7 @@ const initGraphChart = () => { ...@@ -140,7 +172,7 @@ const initGraphChart = () => {
const onFormatLink = (item, index) => { const onFormatLink = (item, index) => {
return { return {
id: `link-${index+1}`, id: `link-${index+1}`,
source: route.query.id, target: item.id+'', source: decreeId.value, target: item.id+'',
label: { show: true, color: "#055fc2", backgroundColor: "#eef7ff", borderWidth: 0, offset: [0, 15], formatter: item.relation }, label: { show: true, color: "#055fc2", backgroundColor: "#eef7ff", borderWidth: 0, offset: [0, 15], formatter: item.relation },
lineStyle: { color: '#B9DCFF', type: "solid", opacity: 1 } lineStyle: { color: '#B9DCFF', type: "solid", opacity: 1 }
} }
......
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted, computed } from "vue";
import router from "@/router"; import router from "@/router";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { getDecreeSummary } from "@/api/decree/introduction"; import { getDecreeSummary } from "@/api/decree/introduction";
...@@ -88,7 +88,33 @@ import USALogo from "./assets/images/USA-logo.png"; ...@@ -88,7 +88,33 @@ import USALogo from "./assets/images/USA-logo.png";
const route = useRoute(); const route = useRoute();
const decreeId = ref(route.query.id); const decodeMaybeBase64NumericId = (raw) => {
if (raw == null) return "";
let s0 = String(raw).trim();
if (!s0) return "";
if (s0.includes("%")) {
try {
const decodedOnce = decodeURIComponent(s0);
if (decodedOnce) s0 = String(decodedOnce).trim();
} catch (_) { }
}
if (/^\d+$/.test(s0)) return s0;
if (/^[A-Za-z0-9+/_-]+={0,2}$/.test(s0)) {
try {
const normalized = s0.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
const decoded = atob(padded);
const decodedStr = (() => {
try { return decodeURIComponent(decoded); } catch (_) { return decoded; }
})();
if (/^\d+$/.test(String(decodedStr).trim())) {
return String(decodedStr).trim();
}
} catch (_) { }
}
return s0;
};
const decreeId = computed(() => decodeMaybeBase64NumericId(route.query.id));
// const activeName = ref("分析报告"); // const activeName = ref("分析报告");
// const handleSwitchActiveName = name => { // const handleSwitchActiveName = name => {
...@@ -144,7 +170,9 @@ const summaryInfo = ref({}); ...@@ -144,7 +170,9 @@ const summaryInfo = ref({});
let pageTitle = "科技政令主页" let pageTitle = "科技政令主页"
const handleGetSummary = async () => { const handleGetSummary = async () => {
try { try {
const res = await getDecreeSummary({ id: route.query.id }); const id = decreeId.value;
if (!id) return;
const res = await getDecreeSummary({ id });
console.log("全局信息", res); console.log("全局信息", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
summaryInfo.value = res.data; summaryInfo.value = res.data;
...@@ -158,7 +186,7 @@ const handleShowReport = () => { ...@@ -158,7 +186,7 @@ const handleShowReport = () => {
const curRoute = router.resolve({ const curRoute = router.resolve({
path: "/decree/decreeOriginal", path: "/decree/decreeOriginal",
query: { query: {
id: route.query.id id: decreeId.value
} }
}); });
window.open(curRoute.href, "_blank"); window.open(curRoute.href, "_blank");
...@@ -185,7 +213,7 @@ const handleAnalysisClick = () => { ...@@ -185,7 +213,7 @@ const handleAnalysisClick = () => {
path: "/writtingAsstaint", path: "/writtingAsstaint",
query: { query: {
topic: "政令", topic: "政令",
fileId: route.query.id fileId: decreeId.value
} }
}); });
}; };
......
...@@ -92,7 +92,7 @@ ...@@ -92,7 +92,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted, computed } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { getDecreeBackground, getDecreeDepend, getDecreePrev } from "@/api/decree/background"; import { getDecreeBackground, getDecreeDepend, getDecreePrev } from "@/api/decree/background";
import router from "@/router"; import router from "@/router";
...@@ -101,7 +101,31 @@ import DefaultIcon1 from "@/assets/icons/default-icon1.png"; ...@@ -101,7 +101,31 @@ import DefaultIcon1 from "@/assets/icons/default-icon1.png";
const route = useRoute(); const route = useRoute();
const decreeId = ref(route.query.id); const decodeMaybeBase64NumericId = (raw) => {
if (raw == null) return "";
let s0 = String(raw).trim();
if (!s0) return "";
if (s0.includes("%")) {
try {
const decodedOnce = decodeURIComponent(s0);
if (decodedOnce) s0 = String(decodedOnce).trim();
} catch (_) { }
}
if (/^\d+$/.test(s0)) return s0;
if (/^[A-Za-z0-9+/_-]+={0,2}$/.test(s0)) {
try {
const normalized = s0.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
const decoded = atob(padded);
const decodedStr = (() => {
try { return decodeURIComponent(decoded); } catch (_) { return decoded; }
})();
if (/^\d+$/.test(String(decodedStr).trim())) return String(decodedStr).trim();
} catch (_) { }
}
return s0;
};
const decreeId = computed(() => decodeMaybeBase64NumericId(route.query.id));
// 提出背景 // 提出背景
const box1BtnList = ref(["涉华背景", "全部背景"]); const box1BtnList = ref(["涉华背景", "全部背景"]);
......
...@@ -9,13 +9,39 @@ ...@@ -9,13 +9,39 @@
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted, computed } from "vue";
import router from "@/router"; import router from "@/router";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import SiderTabs from "@/components/base/SiderTabs/index.vue"; import SiderTabs from "@/components/base/SiderTabs/index.vue";
const route = useRoute(); const route = useRoute();
const decreeId = ref(route.query.id); const decodeMaybeBase64NumericId = (raw) => {
if (raw == null) return "";
let s0 = String(raw).trim();
if (!s0) return "";
if (s0.includes("%")) {
try {
const decodedOnce = decodeURIComponent(s0);
if (decodedOnce) s0 = String(decodedOnce).trim();
} catch (_) { }
}
if (/^\d+$/.test(s0)) return s0;
if (/^[A-Za-z0-9+/_-]+={0,2}$/.test(s0)) {
try {
const normalized = s0.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
const decoded = atob(padded);
const decodedStr = (() => {
try { return decodeURIComponent(decoded); } catch (_) { return decoded; }
})();
if (/^\d+$/.test(String(decodedStr).trim())) return String(decodedStr).trim();
} catch (_) { }
}
return s0;
};
// rawId 用于路由展示(允许加密),decreeId 用于接口调用(只用明文数字)
const rawId = computed(() => (route.query.id == null ? "" : String(route.query.id)));
const decreeId = computed(() => decodeMaybeBase64NumericId(route.query.id));
const siderList = ref([ const siderList = ref([
{ {
...@@ -49,7 +75,7 @@ const handleClickLeftSiderBtn = node => { ...@@ -49,7 +75,7 @@ const handleClickLeftSiderBtn = node => {
router.push({ router.push({
path: node.path, path: node.path,
query: { query: {
id: decreeId.value id: rawId.value
} }
}); });
}; };
......
...@@ -181,7 +181,43 @@ import { useGotoNewsDetail } from '@/router/modules/news'; ...@@ -181,7 +181,43 @@ import { useGotoNewsDetail } from '@/router/modules/news';
const gotoNewsDetail = useGotoNewsDetail() const gotoNewsDetail = useGotoNewsDetail()
const route = useRoute(); const route = useRoute();
const decreeId = ref(route.query.id); const decodeMaybeBase64 = (raw) => {
if (raw == null) return "";
let s0 = String(raw).trim();
if (!s0) return "";
// 兼容 query 里被 URL 编码的 base64(例如 OTg%3D)
if (s0.includes("%")) {
try {
const decodedOnce = decodeURIComponent(s0);
if (decodedOnce) {
s0 = String(decodedOnce).trim();
}
} catch (_) { }
}
// 明文数字直接返回
if (/^\d+$/.test(s0)) return s0;
// base64(encodeURIComponent(id)) 解码(兼容短 base64)
if (/^[A-Za-z0-9+/_-]+={0,2}$/.test(s0)) {
try {
const normalized = s0.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
const decoded = atob(padded);
const decodedStr = (() => {
try {
return decodeURIComponent(decoded);
} catch (_) {
return decoded;
}
})();
// 只在“解出来还是纯数字”时才视为合作限制/智库的加密 id,避免误解码影响其它模块
if (/^\d+$/.test(String(decodedStr).trim())) {
return String(decodedStr).trim();
}
} catch (_) { }
}
return s0;
};
const decreeId = ref(decodeMaybeBase64(route.query.id));
// 风险警告 // 风险警告
const riskInfo = ref({ const riskInfo = ref({
......
...@@ -144,7 +144,7 @@ ...@@ -144,7 +144,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted, reactive } from "vue"; import { ref, onMounted, reactive, computed } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import router from "@/router"; import router from "@/router";
...@@ -161,6 +161,32 @@ import { onNumToChinese } from "@/views/marketAccessRestrictions/utils/index" ...@@ -161,6 +161,32 @@ import { onNumToChinese } from "@/views/marketAccessRestrictions/utils/index"
const route = useRoute(); const route = useRoute();
const decodeMaybeBase64NumericId = (raw) => {
if (raw == null) return "";
let s0 = String(raw).trim();
if (!s0) return "";
if (s0.includes("%")) {
try {
const decodedOnce = decodeURIComponent(s0);
if (decodedOnce) s0 = String(decodedOnce).trim();
} catch (_) { }
}
if (/^\d+$/.test(s0)) return s0;
if (/^[A-Za-z0-9+/_-]+={0,2}$/.test(s0)) {
try {
const normalized = s0.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
const decoded = atob(padded);
const decodedStr = (() => {
try { return decodeURIComponent(decoded); } catch (_) { return decoded; }
})();
if (/^\d+$/.test(String(decodedStr).trim())) return String(decodedStr).trim();
} catch (_) { }
}
return s0;
};
const decreeId = computed(() => decodeMaybeBase64NumericId(route.query.id));
const handleClickToolBox = () => { const handleClickToolBox = () => {
ElMessage.warning("当前功能正在开发中,敬请期待!"); ElMessage.warning("当前功能正在开发中,敬请期待!");
}; };
...@@ -191,7 +217,9 @@ const ALPHABET = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m ...@@ -191,7 +217,9 @@ const ALPHABET = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m
const onMainContentData = async () => { const onMainContentData = async () => {
try { try {
const keyword = commandWord.value; const keyword = commandWord.value;
const res = await getDecreeMainContent({ id: route.query.id, keyword, domainId: areaType.value }); const id = decreeId.value;
if (!id) return;
const res = await getDecreeMainContent({ id, keyword, domainId: areaType.value });
console.log("主要指令", res); console.log("主要指令", res);
if (res && res.code === 200) { if (res && res.code === 200) {
contentList.value = res.data || []; contentList.value = res.data || [];
...@@ -234,7 +262,9 @@ const onDecreeMindMap = async () => { ...@@ -234,7 +262,9 @@ const onDecreeMindMap = async () => {
} }
isTreeDialog.value = true; isTreeDialog.value = true;
try { try {
let res = await getDecreeMindMap({ id: route.query.id }); const id = decreeId.value;
if (!id) return;
let res = await getDecreeMindMap({ id });
console.log("思维导图", res); console.log("思维导图", res);
if (res.code === 200) { if (res.code === 200) {
let nodes = [] let nodes = []
...@@ -280,7 +310,9 @@ const onUniqueArray = (list, key = 'id') => { ...@@ -280,7 +310,9 @@ const onUniqueArray = (list, key = 'id') => {
const entityList = ref([]); const entityList = ref([]);
const onRelatedEntityData = async () => { const onRelatedEntityData = async () => {
try { try {
const res = await getDecreeRelatedEntity({ id: route.query.id }); const id = decreeId.value;
if (!id) return;
const res = await getDecreeRelatedEntity({ id });
console.log("相关实体", res); console.log("相关实体", res);
if (res && res.code === 200) { if (res && res.code === 200) {
entityList.value = res.data; entityList.value = res.data;
...@@ -300,7 +332,9 @@ const organizationInfo = reactive({ ...@@ -300,7 +332,9 @@ const organizationInfo = reactive({
}) })
const handleGetOrgnization = async () => { const handleGetOrgnization = async () => {
try { try {
const res = await getDecreeOrganization({ id: route.query.id }); const id = decreeId.value;
if (!id) return;
const res = await getDecreeOrganization({ id });
console.log("执行机构", res); console.log("执行机构", res);
if (res.code === 200 && res.data?.length) { if (res.code === 200 && res.data?.length) {
organizationInfo.list = res.data; organizationInfo.list = res.data;
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted, computed } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { getDecreeSummary } from "@/api/decree/introduction"; import { getDecreeSummary } from "@/api/decree/introduction";
...@@ -41,6 +41,33 @@ import { getDecreeReport } from "@/api/decree/introduction"; ...@@ -41,6 +41,33 @@ import { getDecreeReport } from "@/api/decree/introduction";
import newOriginal from "@/components/base/DecreeOriginal/newOriginal.vue"; import newOriginal from "@/components/base/DecreeOriginal/newOriginal.vue";
const route = useRoute(); const route = useRoute();
const decodeMaybeBase64NumericId = (raw) => {
if (raw == null) return "";
let s0 = String(raw).trim();
if (!s0) return "";
if (s0.includes("%")) {
try {
const decodedOnce = decodeURIComponent(s0);
if (decodedOnce) s0 = String(decodedOnce).trim();
} catch (_) { }
}
if (/^\d+$/.test(s0)) return s0;
if (/^[A-Za-z0-9+/_-]+={0,2}$/.test(s0)) {
try {
const normalized = s0.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
const decoded = atob(padded);
const decodedStr = (() => {
try { return decodeURIComponent(decoded); } catch (_) { return decoded; }
})();
if (/^\d+$/.test(String(decodedStr).trim())) {
return String(decodedStr).trim();
}
} catch (_) { }
}
return s0;
};
const decreeId = computed(() => decodeMaybeBase64NumericId(route.query.id));
let pdfUrl = ""; let pdfUrl = "";
const handleDownload = async () => { const handleDownload = async () => {
if (pdfUrl) { if (pdfUrl) {
...@@ -85,9 +112,9 @@ const handleDownload = async () => { ...@@ -85,9 +112,9 @@ const handleDownload = async () => {
// 获取全局信息 // 获取全局信息
const summaryInfo = ref({}); const summaryInfo = ref({});
const handleGetSummary = async () => { const handleGetSummary = async () => {
const params = { const id = decreeId.value;
id: route.query.id if (!id) return;
}; const params = { id };
try { try {
const res = await getDecreeSummary(params); const res = await getDecreeSummary(params);
console.log("全局信息", res); console.log("全局信息", res);
...@@ -101,7 +128,9 @@ const handleGetSummary = async () => { ...@@ -101,7 +128,9 @@ const handleGetSummary = async () => {
const refNewOriginal = ref(null); const refNewOriginal = ref(null);
const handleGetReport = async () => { const handleGetReport = async () => {
try { try {
const res = await getDecreeReport({id: route.query.id}); const id = decreeId.value;
if (!id) return;
const res = await getDecreeReport({id});
console.log("报告原文", res); console.log("报告原文", res);
if (res.code === 200) { if (res.code === 200) {
pdfUrl = res.data.pdfUrl; pdfUrl = res.data.pdfUrl;
......
...@@ -122,9 +122,57 @@ const route = useRoute(); ...@@ -122,9 +122,57 @@ const route = useRoute();
const gotoNewsDetail = useGotoNewsDetail(); const gotoNewsDetail = useGotoNewsDetail();
const gotoSearchResults = useGotoSearchResults(); const gotoSearchResults = useGotoSearchResults();
const decodeMaybeBase64 = (raw) => {
if (raw == null) return null;
let s0 = String(raw).trim();
if (!s0) return null;
// 兼容 URL 里被 encodeURIComponent 的 base64(例如 OTg%3D)
if (s0.includes("%")) {
try {
const decodedOnce = decodeURIComponent(s0);
if (decodedOnce) s0 = String(decodedOnce).trim();
} catch (_) { }
}
// 明显不是 base64 的(例如包含 '-' 的新闻明文 id),直接返回
if (!/^[A-Za-z0-9+/_-]+={0,2}$/.test(s0)) return s0;
const encodeBase64Param = (val) => {
const s = String(val ?? "").trim();
if (!s) return "";
try {
return btoa(encodeURIComponent(s));
} catch (_) {
return s;
}
};
const normalizeBase64 = (s) => {
const normalized = String(s ?? "").replace(/-/g, "+").replace(/_/g, "/");
return normalized + "===".slice((normalized.length + 3) % 4);
};
// base64(encodeURIComponent(id)) 解码:仅在“可逆校验通过”时才当作加密参数
try {
const padded = normalizeBase64(s0);
const decoded = atob(padded);
const decodedStr = (() => {
try {
return decodeURIComponent(decoded);
} catch (_) {
return decoded;
}
})();
const reEncoded = encodeBase64Param(decodedStr);
if (!reEncoded) return s0;
if (normalizeBase64(reEncoded) === padded) {
return decodedStr;
}
} catch (_) { }
return s0;
};
onMounted(async () => { onMounted(async () => {
const params = { const params = {
newsId: route.params.id newsId: decodeMaybeBase64(route.params.id)
}; };
const { data: newsDetailData } = await getNewsDetail(params); const { data: newsDetailData } = await getNewsDetail(params);
newsDetail.value = newsDetailData ?? {}; newsDetail.value = newsDetailData ?? {};
......
...@@ -254,6 +254,70 @@ import TipTab from "@/views/thinkTank/TipTab/index.vue"; ...@@ -254,6 +254,70 @@ import TipTab from "@/views/thinkTank/TipTab/index.vue";
const router = useRouter(); const router = useRouter();
const decodeRouteId = (raw) => {
if (raw == null) return null;
const s0 = String(raw);
if (!s0) return null;
// 明文 id(听证会/项目常见为纯数字)直接返回,避免误解码
if (/^\d+$/.test(s0) || /^Rand_/i.test(s0)) {
return s0;
}
const tryParseJson = (str) => {
if (typeof str !== "string") return null;
const s = str.trim();
if (!s) return null;
try {
return JSON.parse(s);
} catch (_) {
return null;
}
};
const isProbablyBase64 = (s) => {
if (!s) return false;
// 支持短 base64(如 "Mg==")
if (s.includes("=")) return true;
if (s.length < 12) return false;
return /^[A-Za-z0-9+/_-]+={0,2}$/.test(s);
};
const tryAtob = (val) => {
if (val == null) return null;
const s = String(val).trim();
if (!s) return null;
if (!isProbablyBase64(s)) return null;
const normalized = s.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
try {
return atob(padded);
} catch (_) {
return null;
}
};
const atobStr = tryAtob(s0);
if (atobStr != null) {
try {
const decoded = decodeURIComponent(atobStr);
return tryParseJson(decoded) ?? decoded;
} catch (_) {
return tryParseJson(atobStr) ?? atobStr;
}
}
try {
const utf8 = decodeURIComponent(escape(s0));
if (utf8 && utf8 !== s0) {
if (/^\d+$/.test(utf8) || /^Rand_/i.test(utf8)) return utf8;
return tryParseJson(utf8) ?? utf8;
}
} catch (_) { }
return s0;
};
const hearingId = computed(() => decodeRouteId(router.currentRoute.value?.params?.id));
const goToAllThinkTank = () => { const goToAllThinkTank = () => {
const thinkTankId = props?.thinkInfo?.thinkTankId || props?.thinkInfo?.id; const thinkTankId = props?.thinkInfo?.thinkTankId || props?.thinkInfo?.id;
const route = router.resolve({ const route = router.resolve({
...@@ -282,7 +346,7 @@ const applyCongressHearingDocumentTitle = (title) => { ...@@ -282,7 +346,7 @@ const applyCongressHearingDocumentTitle = (title) => {
}; };
const handleGetThinkTankHearingInfo = async () => { const handleGetThinkTankHearingInfo = async () => {
try { try {
const id = router.currentRoute._value.params.id; const id = hearingId.value;
if (!id) return; if (!id) return;
const res = await getThinkTankHearingInfo({ id }); const res = await getThinkTankHearingInfo({ id });
if (res?.code === 200 && res?.data) { if (res?.code === 200 && res?.data) {
...@@ -441,7 +505,9 @@ const box1Data = ...@@ -441,7 +505,9 @@ const box1Data =
//获取内容摘要 //获取内容摘要
const handleGetThinkTankReportAbstract = async () => { const handleGetThinkTankReportAbstract = async () => {
try { try {
const res = await getThinkTankReportAbstract(router.currentRoute._value.params.id); const id = hearingId.value;
if (!id) return;
const res = await getThinkTankReportAbstract(id);
console.log("内容摘要", res); console.log("内容摘要", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
box1Data.value = res.data; box1Data.value = res.data;
...@@ -502,7 +568,7 @@ const box5WordCloudKey = ref(0); ...@@ -502,7 +568,7 @@ const box5WordCloudKey = ref(0);
const handleGetThinkTankReportIndustryCloud = async () => { const handleGetThinkTankReportIndustryCloud = async () => {
try { try {
const params = { const params = {
id: router.currentRoute._value.params.id id: hearingId.value
// industryId: activeArea.value // industryId: activeArea.value
}; };
const res = await getThinkTankHearingCloud(params); const res = await getThinkTankHearingCloud(params);
...@@ -529,7 +595,9 @@ const handleGetThinkTankReportIndustryCloud = async () => { ...@@ -529,7 +595,9 @@ const handleGetThinkTankReportIndustryCloud = async () => {
//涉及科技领域 //涉及科技领域
const handleGetThinkTankReportIndustry = async () => { const handleGetThinkTankReportIndustry = async () => {
try { try {
const res = await getThinkTankReportIndustry(router.currentRoute._value.params.id); const id = hearingId.value;
if (!id) return;
const res = await getThinkTankReportIndustry(id);
console.log("涉及科技领域", res); console.log("涉及科技领域", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
areaList.value = res.data; areaList.value = res.data;
...@@ -569,10 +637,18 @@ const majorOpinions = ref([ ...@@ -569,10 +637,18 @@ const majorOpinions = ref([
]); ]);
//处理点击详情页事件 //处理点击详情页事件
const handleOpenReportOriginal = item => { const handleOpenReportOriginal = item => {
const id = hearingId.value;
if (!id) return;
const encodedId = (() => {
const s = String(id).trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "ReportOriginal", name: "ReportOriginal",
params: { params: {
id: router.currentRoute._value.params.id id: encodedId
}, },
query: { query: {
currentPage: currentPage.value, currentPage: currentPage.value,
...@@ -623,7 +699,7 @@ const handleCurrentChange = page => { ...@@ -623,7 +699,7 @@ const handleCurrentChange = page => {
const handleGetThinkTankReportViewpoint = async () => { const handleGetThinkTankReportViewpoint = async () => {
try { try {
const params = { const params = {
testimonyId: router.currentRoute._value.params.id, testimonyId: hearingId.value,
pageNum: currentPage.value, pageNum: currentPage.value,
pageSize: pageSize.value, pageSize: pageSize.value,
keyword: (searchOpinions.value || "").trim(), keyword: (searchOpinions.value || "").trim(),
......
...@@ -473,9 +473,15 @@ const hasReportLinkForSourceView = (sv) => Boolean(String(sv?.report_id ?? "").t ...@@ -473,9 +473,15 @@ const hasReportLinkForSourceView = (sv) => Boolean(String(sv?.report_id ?? "").t
const handleOpenReportOriginalFromSource = (sv) => { const handleOpenReportOriginalFromSource = (sv) => {
const id = String(sv?.report_id ?? "").trim() const id = String(sv?.report_id ?? "").trim()
if (!id) return if (!id) return
const encodedId = (() => {
const s = String(id).trim()
if (!s) return ""
try { return btoa(encodeURIComponent(s)) } catch (_) { return s }
})()
if (!encodedId) return
const route = router.resolve({ const route = router.resolve({
name: "ReportDetail", name: "ReportDetail",
params: { id } params: { id: encodedId }
}) })
window.open(route.href, "_blank") window.open(route.href, "_blank")
} }
...@@ -916,10 +922,16 @@ const handleCurrentChange = page => { ...@@ -916,10 +922,16 @@ const handleCurrentChange = page => {
const handleToReportDetail = (item) => { const handleToReportDetail = (item) => {
if (!item?.id) return; if (!item?.id) return;
window.sessionStorage.setItem("curTabName", item.name); window.sessionStorage.setItem("curTabName", item.name);
const encodedId = (() => {
const s = String(item.id).trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "ReportDetail", name: "ReportDetail",
params: { params: {
id: item.id id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted, computed } from "vue";
import ReportAnalysis from "./reportAnalysis/index.vue"; import ReportAnalysis from "./reportAnalysis/index.vue";
import PolicyTracking from "./policyTracking/index.vue"; import PolicyTracking from "./policyTracking/index.vue";
...@@ -93,6 +93,75 @@ import { getThinkTankReportSummary, getThinkTankReportRelated, getThinkTankRepor ...@@ -93,6 +93,75 @@ import { getThinkTankReportSummary, getThinkTankReportRelated, getThinkTankRepor
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
const decodeRouteId = (raw) => {
if (raw == null) return null;
const s0 = String(raw);
if (!s0) return null;
// 明文 id(常见:Rand_... 或纯数字)直接返回,避免被误判为 base64
if (/^\d+$/.test(s0) || /^Rand_/i.test(s0)) {
return s0;
}
const tryParseJson = (str) => {
if (typeof str !== "string") return null;
const s = str.trim();
if (!s) return null;
try {
return JSON.parse(s);
} catch (_) {
return null;
}
};
const isProbablyBase64 = (s) => {
// 过短的字符串(如 1/2)不参与 base64 解码,避免 atob 误解;
// 但像 "Mg==" 这种带 padding 的短 base64 需要支持
if (!s) return false;
if (s.includes("=")) return true;
if (s.length < 12) return false;
return /^[A-Za-z0-9+/_-]+={0,2}$/.test(s);
};
const tryAtob = (val) => {
if (val == null) return null;
const s = String(val).trim();
if (!s) return null;
if (!isProbablyBase64(s)) return null;
const normalized = s.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
try {
return atob(padded);
} catch (_) {
return null;
}
};
// 1) 常规:base64(encodeURIComponent(id)) → atob → decodeURIComponent
const atobStr = tryAtob(s0);
if (atobStr != null) {
try {
const decoded = decodeURIComponent(atobStr);
return tryParseJson(decoded) ?? decoded;
} catch (_) {
return tryParseJson(atobStr) ?? atobStr;
}
}
// 2) 兜底:路由可能把二进制串 percent-encode(出现奇怪字符),尝试 latin1→utf8
try {
const utf8 = decodeURIComponent(escape(s0));
if (utf8 && utf8 !== s0) {
if (/^\d+$/.test(utf8) || /^Rand_/i.test(utf8)) return utf8;
return tryParseJson(utf8) ?? utf8;
}
} catch (_) { }
// 3) 明文 id:直接返回
return s0;
};
const reportId = computed(() => decodeRouteId(route.params?.id));
const reportUrl = ref(""); const reportUrl = ref("");
const thinkInfo = ref({}); const thinkInfo = ref({});
const reportList = ref({}); const reportList = ref({});
...@@ -100,7 +169,9 @@ const reportList = ref({}); ...@@ -100,7 +169,9 @@ const reportList = ref({});
// 获取报告全局信息 // 获取报告全局信息
const handleGetThinkTankReportSummary = async () => { const handleGetThinkTankReportSummary = async () => {
try { try {
const res = await getThinkTankReportSummary(router.currentRoute._value.params.id); const id = reportId.value;
if (!id) return;
const res = await getThinkTankReportSummary(id);
console.log("报告全局信息", res); console.log("报告全局信息", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
reportUrl.value = res.data.reportUrl; reportUrl.value = res.data.reportUrl;
...@@ -119,7 +190,9 @@ const handleGetThinkTankReportSummary = async () => { ...@@ -119,7 +190,9 @@ const handleGetThinkTankReportSummary = async () => {
// 获取相关报告信息 // 获取相关报告信息
const handleGetThinkTankReport = async () => { const handleGetThinkTankReport = async () => {
try { try {
const res = await getThinkTankReportRelated(router.currentRoute._value.params.id); const id = reportId.value;
if (!id) return;
const res = await getThinkTankReportRelated(id);
console.log("报告全局信息", res); console.log("报告全局信息", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
reportList.value = res.data; reportList.value = res.data;
...@@ -130,10 +203,18 @@ const handleGetThinkTankReport = async () => { ...@@ -130,10 +203,18 @@ const handleGetThinkTankReport = async () => {
}; };
const toReport = () => { const toReport = () => {
console.log(reportUrl.value, "reportUrl.valuereportUrl.value"); console.log(reportUrl.value, "reportUrl.valuereportUrl.value");
const id = reportId.value;
if (!id) return;
const encodedId = (() => {
const s = String(id).trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "ReportOriginal", name: "ReportOriginal",
params: { params: {
id: router.currentRoute._value.params.id id: encodedId
} }
}); });
console.log("route.href", route.href); console.log("route.href", route.href);
...@@ -146,11 +227,13 @@ const switchTab = name => { ...@@ -146,11 +227,13 @@ const switchTab = name => {
}; };
const handleAnalysisClick = () => { const handleAnalysisClick = () => {
const id = reportId.value;
if (!id) return;
router.push({ router.push({
path: "/writtingAsstaint", path: "/writtingAsstaint",
query: { query: {
topic: "智库", topic: "智库",
fileId: router.currentRoute._value.params.id fileId: id
} }
}); });
}; };
...@@ -188,7 +271,9 @@ const downloadOnePdf = async (url, filename) => { ...@@ -188,7 +271,9 @@ const downloadOnePdf = async (url, filename) => {
const handleDownloadDocument = async () => { const handleDownloadDocument = async () => {
try { try {
const { ElMessage } = await import("element-plus"); const { ElMessage } = await import("element-plus");
const res = await getThinkTankReportcontentUrl(router.currentRoute._value.params.id); const id = reportId.value;
if (!id) return;
const res = await getThinkTankReportcontentUrl(id);
if (res.code !== 200 || !res.data) { if (res.code !== 200 || !res.data) {
ElMessage.warning("暂无下载链接"); ElMessage.warning("暂无下载链接");
return; return;
......
...@@ -135,9 +135,56 @@ import { ...@@ -135,9 +135,56 @@ import {
getThinkTankReportPolicy, getThinkTankReportPolicy,
getThinkTankReportPolicyAction getThinkTankReportPolicyAction
} from "@/api/thinkTank/overview"; } from "@/api/thinkTank/overview";
import { useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import DefaultNewsImg from '@/assets/images/default-icon-news.png' import DefaultNewsImg from '@/assets/images/default-icon-news.png'
const router = useRouter(); const router = useRouter();
const route = useRoute();
const decodeRouteId = (raw) => {
if (raw == null) return null;
const s0 = String(raw);
if (!s0) return null;
const tryParseJson = (str) => {
if (typeof str !== "string") return null;
const s = str.trim();
if (!s) return null;
try {
return JSON.parse(s);
} catch (_) {
return null;
}
};
const tryAtob = (val) => {
if (val == null) return null;
const s = String(val).trim();
if (!s) return null;
const normalized = s.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
try {
return atob(padded);
} catch (_) {
return null;
}
};
const atobStr = tryAtob(s0);
if (atobStr != null) {
try {
const decoded = decodeURIComponent(atobStr);
return tryParseJson(decoded) ?? decoded;
} catch (_) {
return tryParseJson(atobStr) ?? atobStr;
}
}
try {
const utf8 = decodeURIComponent(escape(s0));
if (utf8 && utf8 !== s0) {
return tryParseJson(utf8) ?? utf8;
}
} catch (_) { }
return s0;
};
const reportId = computed(() => decodeRouteId(route.params?.id));
const loading = ref(false); const loading = ref(false);
const searchOpinions = ref(""); const searchOpinions = ref("");
// 政策建议相关情况(当前页/当前筛选展示的数据) // 政策建议相关情况(当前页/当前筛选展示的数据)
...@@ -208,10 +255,18 @@ const scrollToWrapTop = () => { ...@@ -208,10 +255,18 @@ const scrollToWrapTop = () => {
const toReport = () => { const toReport = () => {
const id = reportId.value;
if (!id) return;
const encodedId = (() => {
const s = String(id).trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "ReportOriginal", name: "ReportOriginal",
params: { params: {
id: router.currentRoute._value.params.id id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
...@@ -286,7 +341,7 @@ const handleGetThinkTankReportPolicyAction = async () => { ...@@ -286,7 +341,7 @@ const handleGetThinkTankReportPolicyAction = async () => {
try { try {
loading.value = true; loading.value = true;
const params = { const params = {
reportId: router.currentRoute._value.params.id, reportId: reportId.value,
// 这里请求全量数据,前端自行分页 // 这里请求全量数据,前端自行分页
currentPage: 0, currentPage: 0,
pageSize: 1000, pageSize: 1000,
......
...@@ -227,7 +227,7 @@ import { ...@@ -227,7 +227,7 @@ import {
getThinkTankReportViewpoint getThinkTankReportViewpoint
} from "@/api/thinkTank/overview"; } from "@/api/thinkTank/overview";
import { getChartAnalysis } from "@/api/aiAnalysis/index"; import { getChartAnalysis } from "@/api/aiAnalysis/index";
import { useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import "echarts-wordcloud"; import "echarts-wordcloud";
import AiSummary from '@/components/base/Ai/AiSummary/index.vue' import AiSummary from '@/components/base/Ai/AiSummary/index.vue'
import { getPersonSummaryInfo } from "@/api/common/index"; import { getPersonSummaryInfo } from "@/api/common/index";
...@@ -237,6 +237,69 @@ import TipTab from "@/views/thinkTank/TipTab/index.vue"; ...@@ -237,6 +237,69 @@ import TipTab from "@/views/thinkTank/TipTab/index.vue";
const router = useRouter(); const router = useRouter();
const route = useRoute();
const decodeRouteId = (raw) => {
if (raw == null) return null;
let s0 = String(raw);
if (!s0) return null;
// 路由参数可能是百分号编码后的“乱码串”,先尝试 decodeURIComponent 还原一层
if (s0.includes("%")) {
try {
const decodedOnce = decodeURIComponent(s0);
if (decodedOnce) {
s0 = decodedOnce;
}
} catch (_) { }
}
// 明文 id(常见:Rand_... 或纯数字)直接返回,避免被误判为 base64
if (/^\d+$/.test(s0) || /^Rand_/i.test(s0)) {
return s0;
}
const tryParseJson = (str) => {
if (typeof str !== "string") return null;
const s = str.trim();
if (!s) return null;
try {
return JSON.parse(s);
} catch (_) {
return null;
}
};
const tryAtob = (val) => {
if (val == null) return null;
const s = String(val).trim();
if (!s) return null;
const normalized = s.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
try {
return atob(padded);
} catch (_) {
return null;
}
};
const atobStr = tryAtob(s0);
if (atobStr != null) {
try {
const decoded = decodeURIComponent(atobStr);
return tryParseJson(decoded) ?? decoded;
} catch (_) {
return tryParseJson(atobStr) ?? atobStr;
}
}
try {
const utf8 = decodeURIComponent(escape(s0));
if (utf8 && utf8 !== s0) {
if (/^\d+$/.test(utf8) || /^Rand_/i.test(utf8)) return utf8;
return tryParseJson(utf8) ?? utf8;
}
} catch (_) { }
return s0;
};
const reportId = computed(() => decodeRouteId(route.params?.id));
const goToAllThinkTank = () => { const goToAllThinkTank = () => {
const thinkTankId = props?.thinkInfo?.thinkTankId || props?.thinkInfo?.id; const thinkTankId = props?.thinkInfo?.thinkTankId || props?.thinkInfo?.id;
const route = router.resolve({ const route = router.resolve({
...@@ -393,7 +456,9 @@ const box1Data = ...@@ -393,7 +456,9 @@ const box1Data =
//获取内容摘要 //获取内容摘要
const handleGetThinkTankReportAbstract = async () => { const handleGetThinkTankReportAbstract = async () => {
try { try {
const res = await getThinkTankReportAbstract(router.currentRoute._value.params.id); const id = reportId.value;
if (!id) return;
const res = await getThinkTankReportAbstract(id);
console.log("内容摘要", res); console.log("内容摘要", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
box1Data.value = res.data; box1Data.value = res.data;
...@@ -454,7 +519,7 @@ const box5WordCloudKey = ref(0); ...@@ -454,7 +519,7 @@ const box5WordCloudKey = ref(0);
const handleGetThinkTankReportIndustryCloud = async () => { const handleGetThinkTankReportIndustryCloud = async () => {
try { try {
const params = { const params = {
id: router.currentRoute._value.params.id id: reportId.value
// industryId: activeArea.value // industryId: activeArea.value
}; };
const res = await getThinkTankReportIndustryCloud(params); const res = await getThinkTankReportIndustryCloud(params);
...@@ -482,7 +547,9 @@ const handleGetThinkTankReportIndustryCloud = async () => { ...@@ -482,7 +547,9 @@ const handleGetThinkTankReportIndustryCloud = async () => {
//涉及科技领域 //涉及科技领域
const handleGetThinkTankReportIndustry = async () => { const handleGetThinkTankReportIndustry = async () => {
try { try {
const res = await getThinkTankReportIndustry(router.currentRoute._value.params.id); const id = reportId.value;
if (!id) return;
const res = await getThinkTankReportIndustry(id);
console.log("涉及科技领域", res); console.log("涉及科技领域", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
areaList.value = res.data; areaList.value = res.data;
...@@ -522,10 +589,18 @@ const majorOpinions = ref([ ...@@ -522,10 +589,18 @@ const majorOpinions = ref([
]); ]);
//处理点击详情页事件 //处理点击详情页事件
const handleOpenReportOriginal = item => { const handleOpenReportOriginal = item => {
const id = reportId.value;
if (!id) return;
const encodedId = (() => {
const s = String(id).trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "ReportOriginal", name: "ReportOriginal",
params: { params: {
id: router.currentRoute._value.params.id id: encodedId
}, },
query: { query: {
currentPage: currentPage.value, currentPage: currentPage.value,
...@@ -576,7 +651,7 @@ const handleCurrentChange = page => { ...@@ -576,7 +651,7 @@ const handleCurrentChange = page => {
const handleGetThinkTankReportViewpoint = async () => { const handleGetThinkTankReportViewpoint = async () => {
try { try {
const params = { const params = {
reportId: router.currentRoute._value.params.id, reportId: reportId.value,
currentPage: currentPage.value - 1, currentPage: currentPage.value - 1,
pageSize: pageSize.value, pageSize: pageSize.value,
keyword: (searchOpinions.value || "").trim(), keyword: (searchOpinions.value || "").trim(),
......
...@@ -163,7 +163,7 @@ import { ...@@ -163,7 +163,7 @@ import {
getThinkTankProjectRelated getThinkTankProjectRelated
} from "@/api/thinkTank/overview"; } from "@/api/thinkTank/overview";
import { getChartAnalysis } from "@/api/aiAnalysis/index"; import { getChartAnalysis } from "@/api/aiAnalysis/index";
import { useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import "echarts-wordcloud"; import "echarts-wordcloud";
import AiSummary from '@/components/base/Ai/AiSummary/index.vue' import AiSummary from '@/components/base/Ai/AiSummary/index.vue'
import { getPersonSummaryInfo } from "@/api/common/index"; import { getPersonSummaryInfo } from "@/api/common/index";
...@@ -171,6 +171,69 @@ import AiButton from "@/components/base/Ai/AiButton/index.vue"; ...@@ -171,6 +171,69 @@ import AiButton from "@/components/base/Ai/AiButton/index.vue";
import AiPane from "@/components/base/Ai/AiPane/index.vue"; import AiPane from "@/components/base/Ai/AiPane/index.vue";
import TipTab from "@/views/thinkTank/TipTab/index.vue"; import TipTab from "@/views/thinkTank/TipTab/index.vue";
const router = useRouter(); const router = useRouter();
const route = useRoute();
const decodeRouteId = (raw) => {
if (raw == null) return null;
const s0 = String(raw);
if (!s0) return null;
// 明文 id(调查项目常见为纯数字)直接返回,避免误解码
if (/^\d+$/.test(s0) || /^Rand_/i.test(s0)) {
return s0;
}
const tryParseJson = (str) => {
if (typeof str !== "string") return null;
const s = str.trim();
if (!s) return null;
try {
return JSON.parse(s);
} catch (_) {
return null;
}
};
const isProbablyBase64 = (s) => {
if (!s) return false;
// 支持短 base64(如 "Mg==")
if (s.includes("=")) return true;
if (s.length < 12) return false;
return /^[A-Za-z0-9+/_-]+={0,2}$/.test(s);
};
const tryAtob = (val) => {
if (val == null) return null;
const s = String(val).trim();
if (!s) return null;
if (!isProbablyBase64(s)) return null;
const normalized = s.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
try {
return atob(padded);
} catch (_) {
return null;
}
};
const atobStr = tryAtob(s0);
if (atobStr != null) {
try {
const decoded = decodeURIComponent(atobStr);
return tryParseJson(decoded) ?? decoded;
} catch (_) {
return tryParseJson(atobStr) ?? atobStr;
}
}
try {
const utf8 = decodeURIComponent(escape(s0));
if (utf8 && utf8 !== s0) {
if (/^\d+$/.test(utf8) || /^Rand_/i.test(utf8)) return utf8;
return tryParseJson(utf8) ?? utf8;
}
} catch (_) { }
return s0;
};
const projectId = computed(() => decodeRouteId(route.params?.id));
const thinkInfo = ref({ const thinkInfo = ref({
...@@ -241,7 +304,9 @@ const formatDate = (dateStr) => { ...@@ -241,7 +304,9 @@ const formatDate = (dateStr) => {
// 获取项目报告信息 // 获取项目报告信息
const handleGetThinkTankReport = async () => { const handleGetThinkTankReport = async () => {
try { try {
const res = await getThinkTankProjectRelated(router.currentRoute._value.params.id); const id = projectId.value;
if (!id) return;
const res = await getThinkTankProjectRelated(id);
console.log("报告全局信息", res); console.log("报告全局信息", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
reportList.value = Array.isArray(res.data) ? res.data : []; reportList.value = Array.isArray(res.data) ? res.data : [];
...@@ -294,7 +359,7 @@ const box1Data = ...@@ -294,7 +359,7 @@ const box1Data =
// 获取调查项目详情(header/摘要/背景) // 获取调查项目详情(header/摘要/背景)
const handleGetThinkTankProjectsInfo = async () => { const handleGetThinkTankProjectsInfo = async () => {
try { try {
const id = router.currentRoute._value.params.id; const id = projectId.value;
if (!id) return; if (!id) return;
const res = await getThinkTankProjectsInfo({ id }); const res = await getThinkTankProjectsInfo({ id });
if (res?.code === 200 && res?.data) { if (res?.code === 200 && res?.data) {
...@@ -318,7 +383,7 @@ const handleGetThinkTankProjectsInfo = async () => { ...@@ -318,7 +383,7 @@ const handleGetThinkTankProjectsInfo = async () => {
}; };
const handleGetThinkTankProjectsAuthor = async () => { const handleGetThinkTankProjectsAuthor = async () => {
try { try {
const id = router.currentRoute._value.params.id; const id = projectId.value;
if (!id) return; if (!id) return;
const res = await getThinkTankProjectsAuthors({ id }); const res = await getThinkTankProjectsAuthors({ id });
if (res?.code === 200 && res?.data) { if (res?.code === 200 && res?.data) {
...@@ -334,7 +399,9 @@ const handleGetThinkTankProjectsAuthor = async () => { ...@@ -334,7 +399,9 @@ const handleGetThinkTankProjectsAuthor = async () => {
//获取内容摘要 //获取内容摘要
const handleGetThinkTankReportAbstract = async () => { const handleGetThinkTankReportAbstract = async () => {
try { try {
const res = await getThinkTankReportAbstract(router.currentRoute._value.params.id); const id = projectId.value;
if (!id) return;
const res = await getThinkTankReportAbstract(id);
console.log("内容摘要", res); console.log("内容摘要", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
box1Data.value = res.data; box1Data.value = res.data;
...@@ -395,7 +462,7 @@ const box5WordCloudKey = ref(0); ...@@ -395,7 +462,7 @@ const box5WordCloudKey = ref(0);
const handleGetThinkTankReportIndustryCloud = async () => { const handleGetThinkTankReportIndustryCloud = async () => {
try { try {
const params = { const params = {
id: router.currentRoute._value.params.id id: projectId.value
// industryId: activeArea.value // industryId: activeArea.value
}; };
const res = await getThinkTankProjectCloud(params); const res = await getThinkTankProjectCloud(params);
...@@ -422,7 +489,9 @@ const handleGetThinkTankReportIndustryCloud = async () => { ...@@ -422,7 +489,9 @@ const handleGetThinkTankReportIndustryCloud = async () => {
//涉及科技领域 //涉及科技领域
const handleGetThinkTankReportIndustry = async () => { const handleGetThinkTankReportIndustry = async () => {
try { try {
const res = await getThinkTankReportIndustry(router.currentRoute._value.params.id); const id = projectId.value;
if (!id) return;
const res = await getThinkTankReportIndustry(id);
console.log("涉及科技领域", res); console.log("涉及科技领域", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
areaList.value = res.data; areaList.value = res.data;
...@@ -462,10 +531,18 @@ const majorOpinions = ref([ ...@@ -462,10 +531,18 @@ const majorOpinions = ref([
]); ]);
//处理点击详情页事件 //处理点击详情页事件
const handleOpenReportOriginal = item => { const handleOpenReportOriginal = item => {
const id = projectId.value;
if (!id) return;
const encodedId = (() => {
const s = String(id).trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "ReportOriginal", name: "ReportOriginal",
params: { params: {
id: router.currentRoute._value.params.id id: encodedId
}, },
query: { query: {
currentPage: currentPage.value, currentPage: currentPage.value,
...@@ -491,7 +568,7 @@ const total = ref(0); ...@@ -491,7 +568,7 @@ const total = ref(0);
const handleGetThinkTankReportViewpoint = async () => { const handleGetThinkTankReportViewpoint = async () => {
try { try {
const params = { const params = {
reportId: router.currentRoute._value.params.id, reportId: projectId.value,
currentPage: currentPage.value - 1, currentPage: currentPage.value - 1,
pageSize: pageSize.value, pageSize: pageSize.value,
keyword: (searchOpinions.value || "").trim(), keyword: (searchOpinions.value || "").trim(),
......
...@@ -1293,10 +1293,16 @@ function mapPolicyRowToView(row) { ...@@ -1293,10 +1293,16 @@ function mapPolicyRowToView(row) {
const toDetail = item => { const toDetail = item => {
window.sessionStorage.setItem("curTabName", item.contentZh ?? item.content ?? ""); window.sessionStorage.setItem("curTabName", item.contentZh ?? item.content ?? "");
const encodedId = (() => {
const s = String(item?.reportId ?? "").trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "ReportDetail", name: "ReportDetail",
params: { params: {
id: item.reportId id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted, nextTick } from "vue"; import { ref, reactive, onMounted, nextTick, computed } from "vue";
import SurveyForm from "./SurveyForm/index.vue" import SurveyForm from "./SurveyForm/index.vue"
import TimeSortSelectBox from "@/components/base/TimeSortSelectBox/index.vue"; import TimeSortSelectBox from "@/components/base/TimeSortSelectBox/index.vue";
// import Img1 from "./images/img1.png"; // import Img1 from "./images/img1.png";
...@@ -82,7 +82,7 @@ import { getDecodedParams } from "@/utils/goToPage"; ...@@ -82,7 +82,7 @@ import { getDecodedParams } from "@/utils/goToPage";
import ThinkTankReport from "./ThinkTankReport/index.vue"; import ThinkTankReport from "./ThinkTankReport/index.vue";
import CongressHearing from "./CongressHearing/index.vue"; import CongressHearing from "./CongressHearing/index.vue";
const router = useRouter(); const router = useRouter();
const thinkTankId = getDecodedParams(); const thinkTankId = computed(() => getDecodedParams());
const isThinkTankReport = ref(true); const isThinkTankReport = ref(true);
const isSurveyForm = ref(false); const isSurveyForm = ref(false);
const isCongressHearing = ref(false); const isCongressHearing = ref(false);
...@@ -94,10 +94,16 @@ const isCongressHearingLoading = ref(false); ...@@ -94,10 +94,16 @@ const isCongressHearingLoading = ref(false);
const handleToReportDetail = (item) => { const handleToReportDetail = (item) => {
window.sessionStorage.setItem('curTabName', item.name) window.sessionStorage.setItem('curTabName', item.name)
const encodedId = (() => {
const s = String(item?.id ?? "").trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: 'ReportDetail', name: 'ReportDetail',
params: { params: {
id: item.id id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
...@@ -107,21 +113,33 @@ const handleToHearingDetail = item => { ...@@ -107,21 +113,33 @@ const handleToHearingDetail = item => {
const id = item?.id; const id = item?.id;
if (!id) return; if (!id) return;
window.sessionStorage.setItem('curTabName', item?.title || item?.name || ""); window.sessionStorage.setItem('curTabName', item?.title || item?.name || "");
const encodedId = (() => {
const s = String(id).trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "CongressHearingView", name: "CongressHearingView",
params: { params: {
id id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
const handleToProjectDetail = (item) => { const handleToProjectDetail = (item) => {
window.sessionStorage.setItem('curTabName', item.name) window.sessionStorage.setItem('curTabName', item.name)
const encodedId = (() => {
const s = String(item?.id ?? "").trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: 'SurveyProjectView', name: 'SurveyProjectView',
params: { params: {
id: item.id id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
...@@ -426,7 +444,7 @@ const handleGetThinkDynamicsReport = async (payload) => { ...@@ -426,7 +444,7 @@ const handleGetThinkDynamicsReport = async (payload) => {
curFooterList.value = []; curFooterList.value = [];
curFooterProjectList.value = []; curFooterProjectList.value = [];
const res = await getThinkTankTestimoniesByThinkTankId({ const res = await getThinkTankTestimoniesByThinkTankId({
thinkTankId, thinkTankId: thinkTankId.value,
pageNum: Math.max(0, (currentPage.value || 1)), pageNum: Math.max(0, (currentPage.value || 1)),
pageSize: 10, pageSize: 10,
// 国会听证会:排序语义与其它资源库相反(正序→desc,倒序→asc) // 国会听证会:排序语义与其它资源库相反(正序→desc,倒序→asc)
...@@ -452,7 +470,7 @@ const handleGetThinkDynamicsReport = async (payload) => { ...@@ -452,7 +470,7 @@ const handleGetThinkDynamicsReport = async (payload) => {
// 调查项目:用新接口 /think-tank/{thinkTankId}/projects // 调查项目:用新接口 /think-tank/{thinkTankId}/projects
curFooterList.value = []; curFooterList.value = [];
const res = await getThinkTankProjectsByThinkTankId({ const res = await getThinkTankProjectsByThinkTankId({
thinkTankId, thinkTankId: thinkTankId.value,
pageNum: currentPage.value, pageNum: currentPage.value,
pageSize: 12, pageSize: 12,
sortFun: sort.value === true, sortFun: sort.value === true,
...@@ -482,8 +500,8 @@ const handleGetThinkDynamicsReport = async (payload) => { ...@@ -482,8 +500,8 @@ const handleGetThinkDynamicsReport = async (payload) => {
startDate, startDate,
endDate endDate
}; };
if (thinkTankId) { if (thinkTankId.value) {
params.thinkTankId = thinkTankId; params.thinkTankId = thinkTankId.value;
} }
if (keyword) { if (keyword) {
params.keyword = keyword; params.keyword = keyword;
......
...@@ -128,9 +128,15 @@ const router = useRouter(); ...@@ -128,9 +128,15 @@ const router = useRouter();
const handleOpenReportOriginal = (item) => { const handleOpenReportOriginal = (item) => {
const reportId = item?.reportId || item?.report_id || item?.id const reportId = item?.reportId || item?.report_id || item?.id
if (!reportId) return if (!reportId) return
const encodedId = (() => {
const s = String(reportId).trim();
if (!s) return "";
try { return btoa(encodeURIComponent(s)); } catch (_) { return s; }
})();
if (!encodedId) return
const route = router.resolve({ const route = router.resolve({
name: "ReportDetail", name: "ReportDetail",
params: { id: String(reportId) } params: { id: encodedId }
}) })
window.open(route.href, "_blank") window.open(route.href, "_blank")
} }
......
...@@ -216,7 +216,7 @@ ...@@ -216,7 +216,7 @@
</div> </div>
<DivideHeader id="position2" class="divide-header" :titleText="'资讯要闻'"></DivideHeader> <DivideHeader id="position2" class="divide-header" :titleText="'资讯要闻'"></DivideHeader>
<div class="center-center"> <div class="center-center">
<NewsList :newsList="newsList" @item-click="item => gotoNewsDetail(item.newsId)" <NewsList :newsList="newsList" @item-click="item => gotoNewsDetailEncrypted(item.newsId)"
@more-click="handleToMoreNews" img="newsImage" title="newsTitle" content="newsContent" from="from" /> @more-click="handleToMoreNews" img="newsImage" title="newsTitle" content="newsContent" from="from" />
<MessageBubble :messageList="messageList" imageUrl="personImage" @more-click="handleToSocialDetail" <MessageBubble :messageList="messageList" imageUrl="personImage" @more-click="handleToSocialDetail"
@person-click="handleClickPerson" name="personName" content="remarks" source="orgName" /> @person-click="handleClickPerson" name="personName" content="remarks" source="orgName" />
...@@ -566,6 +566,23 @@ const handleSwitchAiContentShowBox7 = (val) => { ...@@ -566,6 +566,23 @@ const handleSwitchAiContentShowBox7 = (val) => {
isBox7InterpretLoading.value = false; isBox7InterpretLoading.value = false;
} }
}; };
const encodeBase64Param = (val) => {
const s = String(val ?? "").trim();
if (!s) return "";
try {
return btoa(encodeURIComponent(s));
} catch (_) {
return s;
}
};
// 智库-新闻资讯:新闻 id 加密后跳转(newsDetail 页面会做兼容解密)
const gotoNewsDetailEncrypted = (newsId) => {
const encoded = encodeBase64Param(newsId);
if (!encoded) return;
gotoNewsDetail(encoded);
};
const handleGetAllThinkTankList = async () => { const handleGetAllThinkTankList = async () => {
try { try {
const res = await getAllThinkTankList({ const res = await getAllThinkTankList({
...@@ -781,10 +798,12 @@ const handleClickToDetail = () => { ...@@ -781,10 +798,12 @@ const handleClickToDetail = () => {
const toDetaile = () => { const toDetaile = () => {
window.sessionStorage.setItem("curTabName", box1Data.value[box1DataIndex.value].reportName); window.sessionStorage.setItem("curTabName", box1Data.value[box1DataIndex.value].reportName);
const encodedId = encodeBase64Param(box1Data.value[box1DataIndex.value].reportId);
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "ReportDetail", name: "ReportDetail",
params: { params: {
id: box1Data.value[box1DataIndex.value].reportId id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
...@@ -1780,9 +1799,11 @@ const handleBox8ToDataLibrary = (item) => { ...@@ -1780,9 +1799,11 @@ const handleBox8ToDataLibrary = (item) => {
const selectParam = { const selectParam = {
reportName: item.clause reportName: item.clause
} }
const jsonStr = JSON.stringify(selectParam);
const base64 = btoa(encodeURIComponent(jsonStr));
const route = router.resolve({ const route = router.resolve({
path: "/dataLibrary/dataThinkTank", path: "/dataLibrary/dataThinkTank",
query: selectParam query: { data: base64 }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
...@@ -1873,10 +1894,12 @@ const handleGetHylyList = async () => { ...@@ -1873,10 +1894,12 @@ const handleGetHylyList = async () => {
}; };
// 查看社交媒体详情 // 查看社交媒体详情
const handleToSocialDetail = item => { const handleToSocialDetail = item => {
const encodedPersonId = encodeBase64Param(item?.id);
if (!encodedPersonId) return;
const route = router.resolve({ const route = router.resolve({
path: "/characterPage", path: "/characterPage",
query: { query: {
personId: item.id personId: encodedPersonId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
...@@ -2351,11 +2374,13 @@ const handleClickPerson = async item => { ...@@ -2351,11 +2374,13 @@ const handleClickPerson = async item => {
return; return;
} }
window.sessionStorage.setItem("curTabName", item.personName); window.sessionStorage.setItem("curTabName", item.personName);
const encodedPersonId = encodeBase64Param(item?.personId);
if (!encodedPersonId) return;
const route = router.resolve({ const route = router.resolve({
path: "/characterPage", path: "/characterPage",
query: { query: {
type: type, // type=1为科技企业领袖,2为国会议员,3为智库研究人员 type: type, // type=1为科技企业领袖,2为国会议员,3为智库研究人员
personId: item.personId personId: encodedPersonId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
...@@ -2373,30 +2398,36 @@ const handleClickPerson = async item => { ...@@ -2373,30 +2398,36 @@ const handleClickPerson = async item => {
const handleToReportDetail = item => { const handleToReportDetail = item => {
window.sessionStorage.setItem("curTabName", item.name); window.sessionStorage.setItem("curTabName", item.name);
const encodedId = encodeBase64Param(item?.id);
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "ReportDetail", name: "ReportDetail",
params: { params: {
id: item.id id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
const handleToHearingDetail = item => { const handleToHearingDetail = item => {
window.sessionStorage.setItem("curTabName", item.titleZh); window.sessionStorage.setItem("curTabName", item.titleZh);
const encodedId = encodeBase64Param(item?.id);
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "CongressHearingView", name: "CongressHearingView",
params: { params: {
id: item.id id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
const handleToSurveyProjectView = item => { const handleToSurveyProjectView = item => {
window.sessionStorage.setItem("curTabName", item.name); window.sessionStorage.setItem("curTabName", item.name);
const encodedId = encodeBase64Param(item?.id);
if (!encodedId) return;
const route = router.resolve({ const route = router.resolve({
name: "SurveyProjectView", name: "SurveyProjectView",
params: { params: {
id: item.id id: encodedId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
......
...@@ -89,6 +89,71 @@ import { useRoute, useRouter } from "vue-router"; ...@@ -89,6 +89,71 @@ import { useRoute, useRouter } from "vue-router";
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
const decodeRouteId = (raw) => {
if (raw == null) return null;
const s0 = String(raw);
if (!s0) return null;
// 明文 id(如纯数字、Rand_...)直接返回,避免误解码
if (/^\d+$/.test(s0) || /^Rand_/i.test(s0)) {
return s0;
}
const tryParseJson = (str) => {
if (typeof str !== "string") return null;
const s = str.trim();
if (!s) return null;
try {
return JSON.parse(s);
} catch (_) {
return null;
}
};
const isProbablyBase64 = (s) => {
if (!s) return false;
// 支持短 base64(如 "Mg==")
if (s.includes("=")) return true;
if (s.length < 12) return false;
return /^[A-Za-z0-9+/_-]+={0,2}$/.test(s);
};
const tryAtob = (val) => {
if (val == null) return null;
const s = String(val).trim();
if (!s) return null;
if (!isProbablyBase64(s)) return null;
const normalized = s.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "===".slice((normalized.length + 3) % 4);
try {
return atob(padded);
} catch (_) {
return null;
}
};
const atobStr = tryAtob(s0);
if (atobStr != null) {
try {
const decoded = decodeURIComponent(atobStr);
return tryParseJson(decoded) ?? decoded;
} catch (_) {
return tryParseJson(atobStr) ?? atobStr;
}
}
// 路由参数可能是 base64 解码后的二进制串(会被浏览器编码成 %E...),这里做 latin1→utf8 尝试还原
try {
const utf8 = decodeURIComponent(escape(s0));
if (utf8 && utf8 !== s0) {
if (/^\d+$/.test(utf8) || /^Rand_/i.test(utf8)) return utf8;
return tryParseJson(utf8) ?? utf8;
}
} catch (_) { }
return s0;
};
const reportId = computed(() => decodeRouteId(route.params?.id));
const reportUrl = ref('') const reportUrl = ref('')
const reportUrlEn = ref('') const reportUrlEn = ref('')
const thinkInfo = ref({}) const thinkInfo = ref({})
...@@ -268,7 +333,9 @@ const applyReportOriginalDocumentTitle = (title) => { ...@@ -268,7 +333,9 @@ const applyReportOriginalDocumentTitle = (title) => {
// 获取报告全局信息 // 获取报告全局信息
const handleGetThinkTankReportSummary = async () => { const handleGetThinkTankReportSummary = async () => {
try { try {
const res = await getThinkTankReportSummary(router.currentRoute._value.params.id); const id = reportId.value;
if (!id) return;
const res = await getThinkTankReportSummary(id);
console.log("报告全局信息", res); console.log("报告全局信息", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const raw = res.data; const raw = res.data;
...@@ -284,7 +351,9 @@ const handleGetThinkTankReportSummary = async () => { ...@@ -284,7 +351,9 @@ const handleGetThinkTankReportSummary = async () => {
//获取原文 //获取原文
const handleGetThinkTankReportcontentUrl = async () => { const handleGetThinkTankReportcontentUrl = async () => {
try { try {
const res = await getThinkTankReportcontentUrl(router.currentRoute._value.params.id); const id = reportId.value;
if (!id) return;
const res = await getThinkTankReportcontentUrl(id);
console.log("获取原文", res); console.log("获取原文", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
reportUrl.value = res.data.content reportUrl.value = res.data.content
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论