提交 4d30163e authored 作者: yanpeng's avatar yanpeng

Merge branch 'pre' of http://8.140.26.4:10003/caijian/risk-monitor into yp-dev

流水线 #259 已通过 于阶段
in 1 分 31 秒
...@@ -18,13 +18,13 @@ const getWordCloudChart = data => { ...@@ -18,13 +18,13 @@ const getWordCloudChart = data => {
// 其他形状你可以使用形状路径 // 其他形状你可以使用形状路径
// shape: 'circle', // 示例 // shape: 'circle', // 示例
// 或者自定义路径 // 或者自定义路径
gridSize: 15, // 网格大小,影响词间距。 gridSize: 5, // 网格大小,影响词间距。
sizeRange: [16, 36], // 定义词云中文字大小的范围 sizeRange: [16, 36], // 定义词云中文字大小的范围
rotationRange: [0, 0], rotationRange: [0, 0],
// rotationRange: [-90, 90], // rotationRange: [-90, 90],
// rotationStep: 10, // rotationStep: 10,
drawOutOfBound: false, // 是否超出画布 drawOutOfBound: false, // 是否超出画布
shrinkToFit: true, // 是否自动缩小以适应容器 shrinkToFit: false, // 是否自动缩小以适应容器
// 字体 // 字体
textStyle: { textStyle: {
color: function (params) { color: function (params) {
......
...@@ -128,7 +128,19 @@ const homeTitleList = ref([ ...@@ -128,7 +128,19 @@ const homeTitleList = ref([
} }
]); ]);
const homeActiveTitleIndex = ref(0); const homeActiveTitleIndex = computed(() => {
let activeIndex = 1
if (route.fullPath.includes('/ZMOverView')) {
activeIndex = 0
} else if (route.fullPath.includes('/dataLibrary')) {
activeIndex = 3
} else if (route.fullPath.includes('/chat') || route.fullPath.includes('/writtingAsstaint')) {
activeIndex = 2
} else {
activeIndex = 1
}
return activeIndex
})
const isShowMenu = ref(false); const isShowMenu = ref(false);
const handleShowMenu = (index, isShow) => { const handleShowMenu = (index, isShow) => {
...@@ -148,79 +160,150 @@ const handleHoverMenu = isShow => { ...@@ -148,79 +160,150 @@ const handleHoverMenu = isShow => {
isShowMenu.value = isShow; isShowMenu.value = isShow;
}; };
const menuList = ref([ const menuList = computed(() => {
// { let menu = [
// title: "中美科技博弈概览", // {
// icon: Menu1, // title: "中美科技博弈概览",
// path: "/ZMOverView" // icon: Menu1,
// }, // path: "/ZMOverView"
{ // },
title: "科技法案", {
icon: Menu2, title: "科技法案",
path: "/billHome", icon: Menu2,
active: false path: "/billHome",
}, active: false
{ },
title: "科技政令", {
icon: Menu3, title: "科技政令",
path: "/decree", icon: Menu3,
active: false path: "/decree",
}, active: false
{ },
title: "美国科技智库", {
icon: Menu4, title: "美国科技智库",
path: "/thinkTank", icon: Menu4,
active: false path: "/thinkTank",
}, active: false
{ },
title: "出口管制", {
icon: Menu5, title: "出口管制",
path: "/exportControl", icon: Menu5,
active: false path: "/exportControl",
}, active: false
{ },
title: "科研合作限制", {
icon: Menu6, title: "科研合作限制",
path: "/cooperationRestrictions", icon: Menu6,
active: false path: "/cooperationRestrictions",
}, active: false
{ },
title: "投融资限制", {
icon: Menu7, title: "投融资限制",
path: "/finance", icon: Menu7,
active: false path: "/finance",
}, active: false
{ },
title: "市场准入限制", {
icon: Menu8, title: "市场准入限制",
path: "/marketAccessRestrictions", icon: Menu8,
active: false path: "/marketAccessRestrictions",
}, active: false
{ },
title: "规则限制", {
icon: Menu9, title: "规则限制",
path: "/ruleRestrictions", icon: Menu9,
active: false path: "/ruleRestrictions",
}, active: false
{ },
title: "美国科技人物观点", {
icon: Menu10, title: "美国科技人物观点",
path: "/technologyFigures", icon: Menu10,
active: false path: "/technologyFigures",
}, active: false
{ },
title: "美国主要创新主体动向", {
icon: Menu11, title: "美国主要创新主体动向",
path: "/innovationSubject", icon: Menu11,
active: false path: "/innovationSubject",
}, active: false
{ },
title: "美国科研资助体系", {
icon: Menu12, title: "美国科研资助体系",
path: "/scientificFunding", icon: Menu12,
active: false path: "/scientificFunding",
active: false
}
]
switch (route.fullPath) {
case '/billHome':
menu.forEach(item => {
item.active = false
})
menu[0].active = true
break
case '/decree':
menu.forEach(item => {
item.active = false
})
menu[1].active = true
break
case '/thinkTank':
menu.forEach(item => {
item.active = false
})
menu[2].active = true
break
case '/exportControl':
menu.forEach(item => {
item.active = false
})
menu[3].active = true
break
case '/cooperationRestrictions':
menu.forEach(item => {
item.active = false
})
menu[4].active = true
break
case '/finance':
menu.forEach(item => {
item.active = false
})
menu[5].active = true
break
case '/marketAccessRestrictions':
menu.forEach(item => {
item.active = false
})
menu[6].active = true
break
case '/ruleRestrictions':
menu.forEach(item => {
item.active = false
})
menu[7].active = true
break
case '/technologyFigures':
menu.forEach(item => {
item.active = false
})
menu[8].active = true
break
case '/innovationSubject':
menu.forEach(item => {
item.active = false
})
menu[9].active = true
break
case '/scientificFunding':
menu.forEach(item => {
item.active = false
})
menu[10].active = true
break
} }
]); return menu
})
const isShowTool = ref(false); const isShowTool = ref(false);
...@@ -243,13 +326,7 @@ const toolList = ref([ ...@@ -243,13 +326,7 @@ const toolList = ref([
]) ])
const handleToModule = (item, index) => { const handleToModule = (item, index) => {
window.sessionStorage.setItem('homeActiveTitleIndex', index)
if (index === 1) { if (index === 1) {
homeActiveTitleIndex.value = index
menuList.value.forEach(val => {
val.active = false
})
item.active = true
router.push({ router.push({
path: item.path path: item.path
}) })
...@@ -268,10 +345,7 @@ const handleToModule = (item, index) => { ...@@ -268,10 +345,7 @@ const handleToModule = (item, index) => {
}; };
const handleClickTitle = (item, index) => { const handleClickTitle = (item, index) => {
if (index === 0 || index === 3) { if (index === 0 || index === 3) {
window.sessionStorage.setItem('homeActiveTitleIndex', index)
homeActiveTitleIndex.value = index
router.push(item.path) router.push(item.path)
} }
}; };
...@@ -282,17 +356,8 @@ const handleClickToolBox = () => { ...@@ -282,17 +356,8 @@ const handleClickToolBox = () => {
onMounted(() => { onMounted(() => {
handleGetPersonType(); handleGetPersonType();
if (route.query.titleIndex) {
homeActiveTitleIndex.value = Number(route.query.titleIndex)
} else {
homeActiveTitleIndex.value = Number(window.sessionStorage.getItem('homeActiveTitleIndex'))
}
}); });
onUnmounted(() => {
window.sessionStorage.removeItem('homeActiveTitleIndex')
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
...@@ -73,8 +73,9 @@ const setChart = (option, chartId, allowClick, selectParam) => { ...@@ -73,8 +73,9 @@ const setChart = (option, chartId, allowClick, selectParam) => {
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
} else if (params.componentType === 'series' && params.seriesType === 'bar') { } else if (params.componentType === 'series' && params.seriesType === 'bar') {
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(selectParam.selectedDate, quatarNum)) selectParam.selectedDate = JSON.stringify(getQuarterRange(year, quatarNum))
const route = router.resolve({ const route = router.resolve({
path: "/dataLibrary/dataDecree", path: "/dataLibrary/dataDecree",
query: selectParam query: selectParam
...@@ -86,7 +87,7 @@ const setChart = (option, chartId, allowClick, selectParam) => { ...@@ -86,7 +87,7 @@ const setChart = (option, chartId, allowClick, selectParam) => {
case '科技智库报告': case '科技智库报告':
if (selectParam.key === 1) { if (selectParam.key === 1) {
selectParam.domains = params.seriesName selectParam.domains = params.seriesName
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({ const route = router.resolve({
......
...@@ -1093,11 +1093,21 @@ const handleBox9Data = async () => { ...@@ -1093,11 +1093,21 @@ const handleBox9Data = async () => {
const selectedIndex = box9LegislativeStatusList.value.findIndex( const selectedIndex = box9LegislativeStatusList.value.findIndex(
item => item.value === box9LegislativeStatus.value item => item.value === box9LegislativeStatus.value
); );
const arr = [
{ label: "提出法案", value: "提案" },
{ label: "众议院通过", value: "众议院通过" },
{ label: "参议院通过", value: "参议院通过" },
{ label: "解决分歧", value: "分歧已解决" },
{ label: "完成立法", value: "完成立法" }
]
const status = arr.filter(item => {
return item.value === box9LegislativeStatus.value
})[0].label
const selectParam = { const selectParam = {
moduleType: '国会法案', moduleType: '国会法案',
key: 2, key: 2,
selectedDate: box9selectetedTime.value ? JSON.stringify([box9selectetedTime.value + '-01-01', box9selectetedTime.value + '-12-31']) : '', selectedDate: box9selectetedTime.value ? JSON.stringify([box9selectetedTime.value + '-01-01', box9selectetedTime.value + '-12-31']) : '',
selectedStatus: box9LegislativeStatus.value ? box9LegislativeStatus.value : '全部阶段', selectedStatus: status ? status : '全部阶段',
isInvolveCn: true isInvolveCn: true
} }
box9ChartInstance = setChart(box9Chart, "box9Chart", true, selectParam); box9ChartInstance = setChart(box9Chart, "box9Chart", true, selectParam);
......
...@@ -2,68 +2,93 @@ ...@@ -2,68 +2,93 @@
<div class="process-overview-wrap"> <div class="process-overview-wrap">
<AnalysisBox title="流程概要" :showAllBtn="false"> <AnalysisBox title="流程概要" :showAllBtn="false">
<div class="main"> <div class="main">
<div class="left" :style="{ width: (maxLineWidth + 250) + 'px' }"> <div class="left" :style="{ width: boardWidth + 'px' }">
<div class="top"> <div class="top">
<div class="top-line" :style="{ width: lineWidth }"> <div class="top-line" :style="{ width: lineWidth }">
<div class="top-line1" ref="topLineEndRef"></div> <div class="arrow-track">
<div
class="arrow-segment arrow-segment-top"
v-for="i in mainArrowCount"
:key="`top-main-${i}`"
></div>
</div>
<div class="top-line1" ref="topLineEndRef">
<div class="arrow-track">
<div
class="arrow-segment arrow-segment-top"
v-for="i in diagonalArrowCount"
:key="`top-diagonal-${i}`"
></div>
</div>
</div>
</div> </div>
<div class="start"> <div class="start">
<div class="icon"> <div class="icon">
<img src="./assets/images/logo1.png" alt="" /> <img src="./assets/images/logo1.png" alt="" />
</div> </div>
<div class="name">{{ "参议院" }}</div> <div class="name">参议院</div>
</div> </div>
<div class="content-box" :style="senateBoxStyle"> <div class="content-box" :style="senateBoxStyle">
<div <div
class="item-box" class="item-box"
v-for="slot in senateSlots" v-for="slot in senateEventsPositioned"
:key="slot.key" :key="slot.key"
style="width: 280px; flex-shrink: 0;" :style="{ left: slot.left + 'px', width: TIMELINE_ITEM_WIDTH_PX + 'px' }"
> >
<template v-if="slot.item"> <div class="item-box-dot">
<div class="item-box-dot"> <img src="./assets/images/top-line-dot.png" alt="" />
<img src="./assets/images/top-line-dot.png" alt="" /> </div>
</div> <div class="item-content">
<div class="item-content"> <div class="item-header">
<div class="item-header"> <div class="item-title" :title="slot.item.actionTitle">
<div class="item-title" :title="slot.item.actionTitle"> {{ slot.item.actionTitle }} <span v-if="slot.item.versionId">({{ slot.item.versionId }})</span>
{{ slot.item.actionTitle }} <span v-if="slot.item.versionId">({{ slot.item.versionId }})</span>
</div>
<div class="item-header-icon" @click="handleClickDetail(true, slot.item, $event)">
<img src="./assets/images/item-header-icon.png" alt="" />
</div>
</div> </div>
<div class="item-info" v-if="slot.item.agreeVote !== null || slot.item.disagreeVote !== null"> <div class="item-header-icon" @click="handleClickDetail(true, slot.item, $event)">
{{ formatVoteText(slot.item) }} <img src="./assets/images/item-header-icon.png" alt="" />
</div>
<div class="item-main" v-if="slot.item.fynrList && slot.item.fynrList.length">
<div
class="item-main-item"
v-for="(sub, subIndex) in slot.item.fynrList"
:key="`${slot.item.id}-${subIndex}-${sub}`"
>
<div class="icon"></div>
<CommonPrompt :content="sub">
<div class="text">{{ sub }}</div>
</CommonPrompt>
</div>
</div> </div>
</div> </div>
<div class="item-time"> <div class="item-info" v-if="slot.item.agreeVote !== null || slot.item.disagreeVote !== null">
{{ slot.item.actionDate }} {{ formatVoteText(slot.item) }}
</div> </div>
</template> <div class="item-main" v-if="slot.item.fynrList && slot.item.fynrList.length">
<div
class="item-main-item"
v-for="(sub, subIndex) in slot.item.fynrList"
:key="`${slot.item.id}-${subIndex}-${sub}`"
>
<div class="icon"></div>
<CommonPrompt :content="sub">
<div class="text">{{ sub }}</div>
</CommonPrompt>
</div>
</div>
</div>
<div class="item-time">{{ slot.item.actionDate }}</div>
</div> </div>
</div> </div>
</div> </div>
<div class="bottom"> <div class="bottom">
<div class="bottom-line" :style="{ width: lineWidth }"> <div class="bottom-line" :style="{ width: lineWidth }">
<div class="bottom-line1" ref="bottomLineEndRef"></div> <div class="arrow-track">
<div
class="arrow-segment arrow-segment-bottom"
v-for="i in mainArrowCount"
:key="`bottom-main-${i}`"
></div>
</div>
<div class="bottom-line1" ref="bottomLineEndRef">
<div class="arrow-track">
<div
class="arrow-segment arrow-segment-bottom"
v-for="i in diagonalArrowCount"
:key="`bottom-diagonal-${i}`"
></div>
</div>
</div>
</div> </div>
<div class="start"> <div class="start">
<div class="name">{{ "众议院" }}</div> <div class="name">众议院</div>
<div class="icon"> <div class="icon">
<img src="./assets/images/logo2.png" alt="" /> <img src="./assets/images/logo2.png" alt="" />
</div> </div>
...@@ -71,51 +96,93 @@ ...@@ -71,51 +96,93 @@
<div class="content-box" :style="houseBoxStyle"> <div class="content-box" :style="houseBoxStyle">
<div <div
class="item-box" class="item-box"
v-for="slot in houseSlots" v-for="slot in houseEventsPositioned"
:key="slot.key" :key="slot.key"
style="width: 280px; flex-shrink: 0;" :style="{ left: slot.left + 'px', width: TIMELINE_ITEM_WIDTH_PX + 'px' }"
> >
<template v-if="slot.item"> <div class="item-time">{{ slot.item.actionDate }}</div>
<div class="item-time"> <div class="item-box-dot">
{{ slot.item.actionDate }} <img src="./assets/images/bottom-line-dot.png" alt="" />
</div> </div>
<div class="item-box-dot"> <div class="item-content">
<img src="./assets/images/bottom-line-dot.png" alt="" /> <div class="item-header">
</div> <div class="item-title" :title="slot.item.actionTitle">
<div class="item-content"> {{ slot.item.actionTitle }} <span v-if="slot.item.versionId">({{ slot.item.versionId }})</span>
<div class="item-header">
<div class="item-title" :title="slot.item.actionTitle">
{{ slot.item.actionTitle }} <span v-if="slot.item.versionId">({{ slot.item.versionId }})</span>
</div>
<div class="item-header-icon" @click="handleClickDetail(true, slot.item, $event)">
<img src="./assets/images/item-header-icon.png" alt="" />
</div>
</div> </div>
<div class="item-info" v-if="slot.item.agreeVote !== null || slot.item.disagreeVote !== null"> <div class="item-header-icon" @click="handleClickDetail(true, slot.item, $event)">
{{ formatVoteText(slot.item) }} <img src="./assets/images/item-header-icon.png" alt="" />
</div> </div>
<div class="item-main" v-if="slot.item.fynrList && slot.item.fynrList.length"> </div>
<div <div class="item-info" v-if="slot.item.agreeVote !== null || slot.item.disagreeVote !== null">
class="item-main-item" {{ formatVoteText(slot.item) }}
v-for="(sub, subIndex) in slot.item.fynrList" </div>
:key="`${slot.item.id}-${subIndex}-${sub}`" <div class="item-main" v-if="slot.item.fynrList && slot.item.fynrList.length">
> <div
<div class="icon"></div> class="item-main-item"
<CommonPrompt :content="sub"> v-for="(sub, subIndex) in slot.item.fynrList"
<div class="text">{{ sub }}</div> :key="`${slot.item.id}-${subIndex}-${sub}`"
</CommonPrompt> >
</div> <div class="icon"></div>
<CommonPrompt :content="sub">
<div class="text">{{ sub }}</div>
</CommonPrompt>
</div> </div>
</div> </div>
</template> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="right" :style="{ left: rightPos, top: rightTop }"> <div class="right" :style="{ left: rightPos, top: rightTop }">
<div class="junction-dot"> <div class="junction-dot">
<div class="inner-dot"></div> <div class="inner-dot"></div>
</div> </div>
<div class="right-line"></div> <div class="right-line" :style="{ width: sharedLineWidth + 'px' }">
<div class="arrow-track">
<div
class="arrow-segment arrow-segment-shared"
v-for="i in rightArrowCount"
:key="`right-${i}`"
></div>
</div>
</div>
</div>
<div class="shared-content-box" :style="sharedBoxStyle">
<div
class="item-box"
v-for="item in sharedEvents"
:key="`shared-${item.id}`"
style="width: 280px; flex-shrink: 0;"
>
<div class="item-time">{{ item.actionDate }}</div>
<div class="item-box-dot"></div>
<div class="item-content">
<div class="item-header">
<div class="item-title" :title="item.actionTitle">
{{ item.actionTitle }} <span v-if="item.versionId">({{ item.versionId }})</span>
</div>
<div class="item-header-icon" @click="handleClickDetail(true, item, $event)">
<img src="./assets/images/item-header-icon.png" alt="" />
</div>
</div>
<div class="item-info" v-if="item.agreeVote !== null || item.disagreeVote !== null">
{{ formatVoteText(item) }}
</div>
<div class="item-main" v-if="item.fynrList && item.fynrList.length">
<div
class="item-main-item"
v-for="(sub, subIndex) in item.fynrList"
:key="`shared-${item.id}-${subIndex}-${sub}`"
>
<div class="icon"></div>
<CommonPrompt :content="sub">
<div class="text">{{ sub }}</div>
</CommonPrompt>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -136,38 +203,54 @@ import { getBillDyqkSummary } from "@/api/bill"; ...@@ -136,38 +203,54 @@ import { getBillDyqkSummary } from "@/api/bill";
import CommonPrompt from "../../commonPrompt/index.vue"; import CommonPrompt from "../../commonPrompt/index.vue";
import ProcessOverviewDetailDialog from "../../ProcessOverviewDetailDialog.vue"; import ProcessOverviewDetailDialog from "../../ProcessOverviewDetailDialog.vue";
// 获取法案流程
const actionList = ref([]); const actionList = ref([]);
const isShowDetailDialog = ref(false);
const currentDetailItem = ref({});
const dialogPos = ref({ left: "0px", top: "0px" });
const ORG_SENATE = "参议院";
const ORG_HOUSE = "众议院";
const PRESIDENT_KEYWORD = "呈递给总统";
const TIMELINE_ITEM_WIDTH_PX = 280;
const ARROW_SEGMENT_TOTAL_PX = 16;
const DIAGONAL_LINE_WIDTH_PX = 127;
const getBillDyqkSummaryList = async () => { const getBillDyqkSummaryList = async () => {
try { try {
const billId = window.sessionStorage.getItem("billId"); const billId = window.sessionStorage.getItem("billId");
if (!billId) return; // 防止 id 为空 if (!billId) {
const params = {
id: billId
};
const res = await getBillDyqkSummary(params);
if (res && res.code === 200) {
// 确保赋值的是数组,如果 data 为 null 则给空数组
actionList.value = Array.isArray(res.data) ? res.data : [];
} else {
actionList.value = []; actionList.value = [];
return;
} }
const res = await getBillDyqkSummary({ id: billId });
actionList.value = res && res.code === 200 && Array.isArray(res.data) ? res.data : [];
} catch (error) { } catch (error) {
actionList.value = []; // 出错时也重置为空数组 actionList.value = [];
} }
}; };
const ORG_SENATE = "参议院";
const ORG_HOUSE = "众议院";
const PRESIDENT_KEYWORD = "呈递给总统";
const TIMELINE_ITEM_WIDTH_PX = 280;
const getTime = (actionDate) => { const getTime = (actionDate) => {
const t = new Date(actionDate).getTime(); const t = new Date(actionDate).getTime();
return Number.isFinite(t) ? t : 0; return Number.isFinite(t) ? t : 0;
}; };
const isDualEvent = (item) => {
const type = String(item?.congressType || "");
return type.includes("双院");
};
const isSenateEvent = (item) => {
const org = String(item?.orgName || "");
const type = String(item?.congressType || "");
return org === ORG_SENATE || type.includes(ORG_SENATE);
};
const isHouseEvent = (item) => {
const org = String(item?.orgName || "");
const type = String(item?.congressType || "");
return org === ORG_HOUSE || type.includes(ORG_HOUSE);
};
const formatVoteText = (item) => { const formatVoteText = (item) => {
if (!item) return ""; if (!item) return "";
const agree = item.agreeVote ?? 0; const agree = item.agreeVote ?? 0;
...@@ -175,130 +258,140 @@ const formatVoteText = (item) => { ...@@ -175,130 +258,140 @@ const formatVoteText = (item) => {
return `${agree}赞成:${disagree}反对`; return `${agree}赞成:${disagree}反对`;
}; };
// 总统交汇节点(用于确定两条时间线的汇合位置)
const presidentAction = computed(() => {
return (
actionList.value.find(
(item) => item.actionTitle && item.actionTitle.includes(PRESIDENT_KEYWORD)
) || null
);
});
// 全局时间排序后的“时间步”
const sortedTimeline = computed(() => { const sortedTimeline = computed(() => {
return [...actionList.value].sort((a, b) => { return [...actionList.value].sort((a, b) => {
const tA = getTime(a.actionDate); const tA = getTime(a.actionDate);
const tB = getTime(b.actionDate); const tB = getTime(b.actionDate);
if (tA !== tB) return tA - tB; if (tA !== tB) return tA - tB;
return String(a.id ?? "").localeCompare(String(b.id ?? ""));
// 时间相同的情况下用 id 保证稳定排序,避免节点在不同渲染中漂移
const idA = String(a.id ?? "");
const idB = String(b.id ?? "");
return idA.localeCompare(idB);
}); });
}); });
// 交汇点(总统节点)在全局时间线里的位置:slice endIndexExclusive 用来排除总统节点本身
const mergeIndexExclusive = computed(() => { const mergeIndexExclusive = computed(() => {
if (!sortedTimeline.value.length) return 0; if (!sortedTimeline.value.length) return 0;
if (!presidentAction.value) return sortedTimeline.value.length; const idx = sortedTimeline.value.findIndex(
(item) => item.actionTitle && item.actionTitle.includes(PRESIDENT_KEYWORD)
const idx = sortedTimeline.value.findIndex((item) => item.id === presidentAction.value.id); );
return idx >= 0 ? idx : sortedTimeline.value.length; return idx >= 0 ? idx : sortedTimeline.value.length;
}); });
// 两条时间线共享同一组时间步(每个时间步只展示属于该阵营的事件;其他阵营用空占位对齐) const dualLaneTimeline = computed(() => {
const timelineSlots = computed(() => { return sortedTimeline.value
return sortedTimeline.value.slice(0, mergeIndexExclusive.value); .slice(0, mergeIndexExclusive.value)
.filter((item) => !isDualEvent(item));
});
const senateEventsPositioned = computed(() => {
const list = [];
let slotIndex = 0;
dualLaneTimeline.value.forEach((item) => {
if (!isSenateEvent(item)) return;
list.push({
key: item.id,
item,
left: slotIndex * TIMELINE_ITEM_WIDTH_PX
});
slotIndex += 1;
});
return list;
}); });
const senateSlots = computed(() => { const houseEventsPositioned = computed(() => {
return timelineSlots.value.map((step) => ({ const list = [];
key: step.id, let slotIndex = 0;
item: step.orgName === ORG_SENATE ? step : null dualLaneTimeline.value.forEach((item) => {
})); if (!isHouseEvent(item)) return;
list.push({
key: item.id,
item,
left: slotIndex * TIMELINE_ITEM_WIDTH_PX
});
slotIndex += 1;
});
return list;
}); });
const houseSlots = computed(() => { const sharedEvents = computed(() => {
return timelineSlots.value.map((step) => ({ return sortedTimeline.value.filter((item, idx) => {
key: step.id, return isDualEvent(item) || idx >= mergeIndexExclusive.value;
item: step.orgName === ORG_HOUSE ? step : null });
}));
}); });
const timelineCount = computed(() => timelineSlots.value.length); const dualLaneCount = computed(() => {
return Math.max(senateEventsPositioned.value.length, houseEventsPositioned.value.length);
});
// 计算最大线条宽度数值(两条线共享时间步长度)
const maxLineWidth = computed(() => { const maxLineWidth = computed(() => {
const senateWidth = 254 + timelineCount.value * TIMELINE_ITEM_WIDTH_PX; const senateWidth = 254 + dualLaneCount.value * TIMELINE_ITEM_WIDTH_PX;
const houseWidth = 150 + timelineCount.value * TIMELINE_ITEM_WIDTH_PX; const houseWidth = 150 + dualLaneCount.value * TIMELINE_ITEM_WIDTH_PX;
return Math.max(senateWidth, houseWidth); return Math.max(senateWidth, houseWidth);
}); });
// 绑定给线条的样式 const lineWidth = computed(() => `${maxLineWidth.value}px`);
const lineWidth = computed(() => {
return maxLineWidth.value + 'px'; const sharedLineWidth = computed(() => {
const w = sharedEvents.value.length * TIMELINE_ITEM_WIDTH_PX;
return Math.max(70, w);
}); });
// 参议院容器宽度:线条总长 + 线条左偏移(110) - 容器左偏移(254) const boardWidth = computed(() => {
const senateBoxStyle = computed(() => { return maxLineWidth.value + 90 + 24 + sharedLineWidth.value + 180;
return {
width: (maxLineWidth.value + 110 - 254) + 'px',
justifyContent: 'flex-start'
};
}); });
// 众议院容器宽度:线条总长 + 线条左偏移(110) - 容器左偏移(150) const mainArrowCount = computed(() => {
const houseBoxStyle = computed(() => { return Math.max(1, Math.ceil(maxLineWidth.value / ARROW_SEGMENT_TOTAL_PX));
return {
width: (maxLineWidth.value + 110 - 150) + 'px',
justifyContent: 'flex-start'
};
}); });
const rightPos = computed(() => { const diagonalArrowCount = computed(() => {
// 右侧节点位置 = 线条宽度 + 斜线水平投影长度(约90px) return Math.max(1, Math.ceil(DIAGONAL_LINE_WIDTH_PX / ARROW_SEGMENT_TOTAL_PX));
return (maxLineWidth.value + 90) + 'px';
}); });
const rightArrowCount = computed(() => {
return Math.max(1, Math.ceil(sharedLineWidth.value / ARROW_SEGMENT_TOTAL_PX));
});
const senateBoxStyle = computed(() => ({
width: `${maxLineWidth.value + 110 - 254}px`,
justifyContent: "flex-start"
}));
const houseBoxStyle = computed(() => ({
width: `${maxLineWidth.value + 110 - 150}px`,
justifyContent: "flex-start"
}));
const rightPos = computed(() => `${maxLineWidth.value + 90}px`);
const sharedBoxStyle = computed(() => ({
left: `${maxLineWidth.value + 219}px`,
width: `${Math.max(sharedLineWidth.value, sharedEvents.value.length * TIMELINE_ITEM_WIDTH_PX)}px`
}));
const topLineEndRef = ref(null); const topLineEndRef = ref(null);
const bottomLineEndRef = ref(null); const bottomLineEndRef = ref(null);
const rightTop = ref('370px'); const rightTop = ref("370px");
const isShowDetailDialog = ref(false);
const currentDetailItem = ref({});
const dialogPos = ref({ left: '0px', top: '0px' });
const handleClickDetail = (isShow, item = {}, event = null) => { const handleClickDetail = (isShow, item = {}, event = null) => {
isShowDetailDialog.value = isShow; isShowDetailDialog.value = isShow;
if (isShow) { if (!isShow) return;
currentDetailItem.value = item;
if (event) {
// 计算弹窗位置,出现在点击位置附近(偏移一些避免挡住鼠标)
const x = event.clientX;
const y = event.clientY;
// 获取包裹容器的偏移量,因为弹窗是 absolute 定位在 wrap 里的
const wrap = document.querySelector('.process-overview-wrap');
const rect = wrap.getBoundingClientRect();
let left = x - rect.left + 20;
let top = y - rect.top - 50;
// 边界处理:防止超出右边界
if (left + 480 > rect.width) {
left = x - rect.left - 500;
}
dialogPos.value = { currentDetailItem.value = item;
left: left + 'px', if (!event) return;
top: top + 'px'
}; const wrap = document.querySelector(".process-overview-wrap");
} if (!wrap) return;
const rect = wrap.getBoundingClientRect();
let left = event.clientX - rect.left + 20;
let top = event.clientY - rect.top - 50;
if (left + 480 > rect.width) {
left = event.clientX - rect.left - 500;
} }
dialogPos.value = { left: `${left}px`, top: `${top}px` };
}; };
// 挂载阶段调用
onMounted(async () => { onMounted(async () => {
await getBillDyqkSummaryList(); await getBillDyqkSummaryList();
await nextTick(); await nextTick();
...@@ -306,9 +399,7 @@ onMounted(async () => { ...@@ -306,9 +399,7 @@ onMounted(async () => {
}); });
const updateRightTop = () => { const updateRightTop = () => {
// 交汇点需要精确对齐上下两条斜线端点在页面中的 y 坐标 const wrap = document.querySelector(".process-overview-wrap");
// rightTop 是相对 .process-overview-wrap 的 absolute top
const wrap = document.querySelector('.process-overview-wrap');
if (!wrap) return; if (!wrap) return;
const topLineEndEl = topLineEndRef.value; const topLineEndEl = topLineEndRef.value;
...@@ -319,22 +410,12 @@ const updateRightTop = () => { ...@@ -319,22 +410,12 @@ const updateRightTop = () => {
const topRect = topLineEndEl.getBoundingClientRect(); const topRect = topLineEndEl.getBoundingClientRect();
const bottomRect = bottomLineEndEl.getBoundingClientRect(); const bottomRect = bottomLineEndEl.getBoundingClientRect();
// 根据 CSS 的旋转原点:
// - top-line1: rotate(45deg) 且 transform-origin: 0 0,因此左侧“尖端”约等于 rect.top
// - bottom-line1: rotate(-45deg) 且 transform-origin: 0 100%,因此左侧“尖端”约等于 rect.bottom
// 但我们对齐的是“斜线中心线”,而不是外包矩形边缘。
// 该斜线块在样式里高度为 8px,所以中心线偏移 4px
const LINE_THICKNESS_PX = 8; const LINE_THICKNESS_PX = 8;
const topLineCenterY = topRect.top + LINE_THICKNESS_PX / 2; const topLineCenterY = topRect.top + LINE_THICKNESS_PX / 2;
const bottomLineCenterY = bottomRect.bottom - LINE_THICKNESS_PX / 2; const bottomLineCenterY = bottomRect.bottom - LINE_THICKNESS_PX / 2;
const desiredCenterY = (topLineCenterY + bottomLineCenterY) / 2; const desiredCenterY = (topLineCenterY + bottomLineCenterY) / 2;
rightTop.value = `${desiredCenterY - wrapRect.top - 12 - 49}px`;
// .right 里 junction-dot 高度为 24px,flex 会让 right-line 与其垂直居中
const junctionCenterOffsetY = 12;
// 经验补偿:整体向上平移约 49px,使视觉交汇点精确落在两条斜线交点
const VISUAL_OFFSET_Y = -49;
rightTop.value = (desiredCenterY - wrapRect.top - junctionCenterOffsetY + VISUAL_OFFSET_Y) + 'px';
}; };
</script> </script>
...@@ -345,51 +426,6 @@ const updateRightTop = () => { ...@@ -345,51 +426,6 @@ const updateRightTop = () => {
margin-top: 16px; margin-top: 16px;
position: relative; position: relative;
.box-header {
width: 100%;
height: 56px;
display: flex;
position: relative;
.header-left {
margin-top: 18px;
width: 8px;
height: 20px;
border-radius: 0 4px 4px 0;
background: var(--color-main-active);
}
.title {
margin-left: 14px;
margin-top: 14px;
height: 26px;
line-height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
}
.header-right {
position: absolute;
top: 14px;
right: 12px;
display: flex;
justify-content: flex-end;
gap: 4px;
.icon {
width: 28px;
height: 28px;
img {
width: 100%;
height: 100%;
}
}
}
}
.main { .main {
margin-left: 24px; margin-left: 24px;
margin-right: 24px; margin-right: 24px;
...@@ -398,7 +434,6 @@ const updateRightTop = () => { ...@@ -398,7 +434,6 @@ const updateRightTop = () => {
overflow-x: auto; overflow-x: auto;
overflow-y: hidden; overflow-y: hidden;
/* 自定义滚动条样式,模拟进度条 */
&::-webkit-scrollbar { &::-webkit-scrollbar {
height: 8px; height: 8px;
} }
...@@ -423,10 +458,37 @@ const updateRightTop = () => { ...@@ -423,10 +458,37 @@ const updateRightTop = () => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
/* 确保内容区域宽度足够展示所有节点和右侧汇合点 */
min-width: fit-content; min-width: fit-content;
padding-right: 150px; padding-right: 150px;
.arrow-track {
width: 100%;
height: 8px;
display: flex;
align-items: center;
overflow: hidden;
}
.arrow-segment {
width: 14px;
height: 8px;
margin-right: 2px;
flex-shrink: 0;
clip-path: polygon(0 0, 80% 0, 100% 50%, 80% 100%, 0 100%, 14% 50%);
}
.arrow-segment-top {
background: #3c8bf7;
}
.arrow-segment-bottom {
background: #ffac4d;
}
.arrow-segment-shared {
background: #5f656c;
}
.top { .top {
height: 260px; height: 260px;
display: flex; display: flex;
...@@ -437,8 +499,6 @@ const updateRightTop = () => { ...@@ -437,8 +499,6 @@ const updateRightTop = () => {
left: 110px; left: 110px;
top: 242px; top: 242px;
height: 8px; height: 8px;
width: 1100px;
background: url("./assets/images/top-line-icon.png");
.top-line1 { .top-line1 {
position: absolute; position: absolute;
...@@ -446,7 +506,6 @@ const updateRightTop = () => { ...@@ -446,7 +506,6 @@ const updateRightTop = () => {
top: 0; top: 0;
height: 8px; height: 8px;
width: 127px; width: 127px;
background: url("./assets/images/top-line-icon.png");
transform: rotate(45deg); transform: rotate(45deg);
transform-origin: 0 0; transform-origin: 0 0;
} }
...@@ -475,211 +534,32 @@ const updateRightTop = () => { ...@@ -475,211 +534,32 @@ const updateRightTop = () => {
width: 100px; width: 100px;
height: 30px; height: 30px;
display: flex; display: flex;
flex-direction: row;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
gap: 8;
padding: 1px 8px; padding: 1px 8px;
box-sizing: border-box; box-sizing: border-box;
border: 1px solid rgba(186, 224, 255, 1); border: 1px solid rgba(186, 224, 255, 1);
border-radius: 4px; border-radius: 4px;
background: rgba(230, 244, 255, 1); background: rgba(230, 244, 255, 1);
color: rgba(22, 119, 255, 1); color: rgba(22, 119, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px; font-size: 16px;
font-weight: 700; font-weight: 700;
line-height: 20px;
} }
} }
.content-box { .content-box {
display: flex; position: relative;
margin-left: 134px; margin-left: 134px;
margin-bottom: 19px; margin-bottom: 19px;
.item-box { .item-box {
padding: 2px 15px; position: absolute;
display: flex;
flex-direction: column;
justify-content: flex-end;
position: relative;
.item-time {
position: absolute;
bottom: -50px;
left: 30px;
height: 30px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 30px;
}
.item-box-dot {
position: absolute;
z-index: 9999;
left: 10px;
bottom: -7px;
width: 12px;
height: 12px;
img {
width: 100%;
height: 100%;
}
}
.item-content {
border-left: 1px solid rgb(20, 89, 187);
}
.item-header {
display: flex;
align-items: center;
height: 30px;
padding: 0 10px;
margin-bottom: 8px;
.item-title {
line-height: 26px;
color: rgb(59, 65, 75);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
span {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
}
.item-header-icon {
margin-left: 5px;
width: 16px;
height: 16px;
cursor: pointer;
flex-shrink: 0;
img {
width: 100%;
height: 100%;
}
}
}
.item-info {
padding: 0 10px;
color: rgb(59, 65, 75);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
margin-bottom: 4px;
}
.item-main {
padding: 5px 10px;
.item-main-item {
display: flex;
align-items: baseline;
width: 269px;
margin-bottom: 4px;
.icon {
margin: 9px 12px;
width: 6px;
height: 6px;
border-radius: 3px;
background: #84888e;
}
.text {
width: 240px;
color: rgb(59, 65, 75);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
height: 48px;
}
:deep(.text-ellipsis) {
white-space: normal !important;
}
}
}
.item-footer {
border-left: 1px solid rgb(20, 89, 187);
display: flex;
padding: 8px 15px;
justify-content: space-between;
.item-footer-box {
display: flex;
margin-left: 12px;
.icon {
position: relative;
width: 24px;
height: 24px;
img {
width: 100%;
height: 100%;
}
.inner-icon {
position: absolute;
right: -5px;
top: 0;
width: 12px;
height: 12px;
border-radius: 6px;
background: rgba(255, 255, 255, 0.8);
display: flex;
box-sizing: border-box;
padding: 1px;
img {
width: 10px;
height: 10px;
}
}
}
.text {
margin-left: 9px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 24px;
}
}
}
} }
} }
} }
.bottom { .bottom {
margin-top: 150px; margin-top: 150px;
// height: 300px;
display: flex; display: flex;
position: relative; position: relative;
...@@ -688,8 +568,6 @@ const updateRightTop = () => { ...@@ -688,8 +568,6 @@ const updateRightTop = () => {
left: 110px; left: 110px;
top: 11px; top: 11px;
height: 8px; height: 8px;
width: 1100px;
background: url("./assets/images/bottom-line-icon.png");
.bottom-line1 { .bottom-line1 {
position: absolute; position: absolute;
...@@ -697,7 +575,6 @@ const updateRightTop = () => { ...@@ -697,7 +575,6 @@ const updateRightTop = () => {
top: 0; top: 0;
height: 8px; height: 8px;
width: 127px; width: 127px;
background: url("./assets/images/bottom-line-icon.png");
transform: rotate(-45deg); transform: rotate(-45deg);
transform-origin: 0 100%; transform-origin: 0 100%;
} }
...@@ -705,7 +582,6 @@ const updateRightTop = () => { ...@@ -705,7 +582,6 @@ const updateRightTop = () => {
.start { .start {
width: 120px; width: 120px;
// height: 260px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-start; justify-content: flex-start;
...@@ -726,542 +602,228 @@ const updateRightTop = () => { ...@@ -726,542 +602,228 @@ const updateRightTop = () => {
width: 100px; width: 100px;
height: 30px; height: 30px;
display: flex; display: flex;
flex-direction: row;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
gap: 8;
padding: 1px 8px; padding: 1px 8px;
box-sizing: border-box; box-sizing: border-box;
border-radius: 4px; border-radius: 4px;
border: 1px solid rgba(255, 229, 143, 1); border: 1px solid rgba(255, 229, 143, 1);
background: rgba(255, 251, 230, 1); background: rgba(255, 251, 230, 1);
color: rgba(250, 173, 20, 1); color: rgba(250, 173, 20, 1);
font-family: Microsoft YaHei;
font-size: 16px; font-size: 16px;
font-weight: 700; font-weight: 700;
line-height: 20px;
} }
} }
.content-box { .content-box {
display: flex; position: relative;
margin-left: 30px; margin-left: 30px;
.item-box { .item-box {
padding: 20px 15px; position: absolute;
display: flex;
flex-direction: column;
justify-content: flex-start;
position: relative;
.item-time {
position: absolute;
top: -30px;
left: 30px;
height: 30px;
color: rgba(255, 172, 77, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 30px;
}
.item-box-dot {
position: absolute;
z-index: 9999;
left: 10px;
top: 7px;
width: 12px;
height: 12px;
img {
width: 100%;
height: 100%;
}
}
.item-content {
border-left: 1px solid rgba(255, 172, 77, 1);
}
.item-header {
display: flex;
align-items: center;
height: 30px;
padding: 5px 10px;
margin-top: 8px;
.item-title {
line-height: 26px;
color: rgb(59, 65, 75);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
span {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
}
.item-header-icon {
margin-left: 5px;
width: 16px;
height: 16px;
cursor: pointer;
flex-shrink: 0;
img {
width: 100%;
height: 100%;
}
}
}
.item-info {
padding: 0 10px;
color: rgb(59, 65, 75);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
margin-top: 8px;
}
.item-main {
padding: 5px 10px;
.item-main-item {
display: flex;
align-items: baseline;
width: 269px;
margin-top: 4px;
.icon {
margin: 9px 12px;
width: 6px;
height: 6px;
border-radius: 3px;
background: #84888e;
}
.text {
width: 240px;
color: rgb(59, 65, 75);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
height: 48px;
}
:deep(.text-ellipsis) {
white-space: normal !important;
}
}
}
.item-footer {
border-left: 1px solid rgba(255, 172, 77, 1);
display: flex;
padding: 8px 15px;
justify-content: space-between;
.item-footer-box {
display: flex;
margin-left: 12px;
.icon {
position: relative;
width: 24px;
height: 24px;
img {
width: 100%;
height: 100%;
}
.inner-icon {
position: absolute;
right: -5px;
top: 0;
width: 12px;
height: 12px;
border-radius: 6px;
background: rgba(255, 255, 255, 0.8);
display: flex;
box-sizing: border-box;
padding: 1px;
img {
width: 10px;
height: 10px;
}
}
}
.text {
margin-left: 9px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 24px;
}
}
}
} }
} }
} }
.right { .item-box {
position: absolute; padding: 2px 15px;
top: 370px;
margin-left: 90px;
display: flex; display: flex;
align-items: center; flex-direction: column;
position: relative;
.junction-dot { .item-time {
width: 24px; position: absolute;
height: 24px; left: 30px;
height: 30px;
color: rgba(95, 101, 108, 1);
font-size: 16px;
font-weight: 700;
line-height: 30px;
}
.item-box-dot {
position: absolute;
z-index: 5;
left: 10px;
width: 12px;
height: 12px;
border-radius: 50%; border-radius: 50%;
background: #5f656c; background: #5f656c;
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
margin-right: -4px; // 稍微重叠
.inner-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: #fff;
}
} }
.right-line { .item-content {
width: 70px; border-left: 1px solid #919191;
height: 8px;
background: url("./assets/images/right-line-icon.png");
} }
}
}
}
.footer {
width: 1710px;
height: 76px;
display: flex;
border: 1px solid rgba(231, 241, 255, 1);
border-radius: 4px;
background: rgba(246, 251, 255, 1);
margin-left: 13px;
.footer-left {
margin-top: 28px;
margin-left: 12px;
width: 19px;
height: 20px;
img {
width: 100%;
height: 100%;
}
}
.footer-center { .item-header {
margin-left: 13px; display: flex;
margin-top: 8px; align-items: center;
width: 1617px; height: 30px;
height: 60px; padding: 0 10px;
color: var(--color-main-active); margin-bottom: 8px;
font-family: Microsoft YaHei;
font-size: 14px; .item-title {
font-weight: 400; line-height: 26px;
line-height: 24px; color: rgb(59, 65, 75);
} font-size: 20px;
font-weight: 700;
.footer-right { white-space: nowrap;
margin-left: 13px; overflow: hidden;
margin-top: 28px; text-overflow: ellipsis;
width: 24px;
height: 24px;
background: rgba(231, 241, 255, 1);
border-radius: 12px;
background: #e7f1ff;
box-sizing: border-box;
padding: 3px;
img {
width: 100%;
height: 100%;
}
}
}
.dialog-wrapper1 {
position: absolute;
z-index: 9999;
top: -120px;
width: 1600px;
height: 1000px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 10px;
background: rgba(255, 255, 255, 1);
.dialog-header {
height: 48px;
box-sizing: border-box;
border-bottom: 1px solid rgba(240, 242, 244, 1);
display: flex;
justify-content: space-between;
.header-left { span {
display: flex; color: rgba(132, 136, 142, 1);
font-size: 14px;
font-weight: 400;
}
}
.icon { .item-header-icon {
width: 20px; margin-left: 5px;
height: 20px; width: 16px;
margin-left: 14px; height: 16px;
margin-top: 14px; cursor: pointer;
flex-shrink: 0;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
}
} }
} }
.title { .item-info {
margin-left: 11px; padding: 0 10px;
margin-top: 16px; color: rgb(59, 65, 75);
height: 14px; font-size: 16px;
color: rgba(95, 101, 108, 1); line-height: 24px;
font-family: Microsoft YaHei; margin-bottom: 4px;
font-size: 14px;
font-weight: 400;
line-height: 14px;
} }
}
.header-right { .item-main {
width: 16px; padding: 5px 10px;
height: 16px;
margin-top: 16px;
margin-right: 16px;
cursor: pointer;
img { .item-main-item {
width: 100%; display: flex;
height: 100%; align-items: baseline;
} width: 269px;
} margin-bottom: 4px;
}
.icon {
.dialog-info { margin: 9px 12px;
display: flex; width: 6px;
width: 1552px; height: 6px;
height: 64px; border-radius: 3px;
margin: 12px auto; background: #84888e;
}
.info-box1 {
span {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 14px;
}
}
.info-box2 { .text {
margin-left: 24px; width: 240px;
color: rgb(59, 65, 75);
font-size: 16px;
line-height: 24px;
display: -webkit-box;
line-clamp: 2;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
height: 48px;
}
span { :deep(.text-ellipsis) {
color: rgba(95, 101, 108, 1); white-space: normal !important;
font-family: Microsoft YaHei; }
font-size: 14px; }
font-weight: 400;
line-height: 14px;
} }
} }
.info-box3 { .top .item-box {
display: flex; justify-content: flex-end;
.icon1 { .item-time {
margin-left: 25px; bottom: -50px;
margin-top: 8px; color: rgba(20, 89, 187, 1);
width: 14px;
height: 14px;
border-radius: 4px;
border: 1px solid #333;
} }
.icon2 { .item-box-dot {
margin-left: 25px; bottom: -7px;
margin-top: 8px; background: #1677ff;
width: 18px;
height: 18px;
border-radius: 4px;
img {
width: 18px;
height: 18px;
}
} }
.text { .item-content {
margin-left: 9px; border-left: 1px solid rgb(20, 89, 187);
margin-top: 9px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 14px;
} }
} }
.info-box4 { .bottom .item-box {
margin-left: 500px; padding-top: 20px;
margin-top: 5px; justify-content: flex-start;
position: relative;
.icon { .item-time {
position: absolute; top: -30px;
right: 5px; color: rgba(255, 172, 77, 1);
top: 5px;
width: 16px;
height: 16px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
} }
}
}
.dialog-main {
height: 750px;
width: 1505px;
margin: 0 auto;
border-bottom: 1px solid #e9e9e9;
.dialog-main-header { .item-box-dot {
width: 1505px; top: 7px;
height: 54px; background: #faad14;
display: flex;
background: rgba(59, 65, 75, 1);
color: #fff;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 54px;
.dialog-main-header-left {
flex: 1;
padding-left: 16px;
} }
.dialog-main-header-right { .item-content {
flex: 1; border-left: 1px solid rgba(255, 172, 77, 1);
} }
} }
.dialog-main-item { .right {
width: 1505px; position: absolute;
top: 370px;
margin-left: 90px;
display: flex; display: flex;
padding: 16px; align-items: center;
height: 139px;
box-sizing: border-box;
.dialog-main-left {
flex: 1;
.dialog-main-item-title {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 30px;
display: flex;
.title-left {
width: 96px;
}
.title-right { .junction-dot {
flex: 1; width: 24px;
} height: 24px;
} border-radius: 50%;
background: #5f656c;
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
margin-right: -4px;
.dialog-main-item-content { .inner-dot {
margin-left: 96px; width: 10px;
color: rgba(132, 136, 142, 1); height: 10px;
font-family: Microsoft YaHei; border-radius: 50%;
font-size: 14px; background: #fff;
font-weight: 400;
line-height: 18px;
} }
} }
.dialog-main-right { .right-line {
flex: 1; height: 8px;
}
}
.dialog-main-item-title { .shared-content-box {
color: rgba(59, 65, 75, 1); position: absolute;
font-family: Microsoft YaHei; top: 170px;
font-size: 16px; display: flex;
font-weight: 700;
line-height: 30px;
display: flex;
.title-left { .item-box {
width: 96px; justify-content: flex-end;
}
.title-right { .item-time {
flex: 1; bottom: -50px;
}
} }
.dialog-main-item-content { .item-box-dot {
margin-left: 96px; bottom: -7px;
color: rgba(132, 136, 142, 1); background: #5f656c;
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
} }
} }
} }
.dialog-main-item:nth-child(2n-1) {
border-radius: 4px;
background: rgba(248, 249, 250, 1);
}
}
.dialog-footer {
height: 100px;
display: flex;
justify-content: center;
align-items: center;
} }
} }
} }
......
...@@ -693,10 +693,6 @@ const statusList = ref([ ...@@ -693,10 +693,6 @@ const statusList = ref([
name: '提出法案', name: '提出法案',
id: '提出法案' id: '提出法案'
}, },
{
name: '通过法案',
id: '通过法案'
},
{ {
name: '众议院通过', name: '众议院通过',
id: '众议院通过' id: '众议院通过'
...@@ -706,8 +702,12 @@ const statusList = ref([ ...@@ -706,8 +702,12 @@ const statusList = ref([
id: '参议院通过' id: '参议院通过'
}, },
{ {
name: '分歧已解决', name: '解决分歧',
id: '分歧已解决' id: '解决分歧'
},
{
name: '完成立法',
id: '完成立法'
}, },
]) ])
......
...@@ -459,6 +459,7 @@ const handleGetThinkTankReportIndustryCloud = async () => { ...@@ -459,6 +459,7 @@ const handleGetThinkTankReportIndustryCloud = async () => {
})); }));
// 该接口数据用于「报告关键词云」 // 该接口数据用于「报告关键词云」
box5Data.value = data; box5Data.value = data;
console.log("box5Data", box5Data.value);
if (data.length) { if (data.length) {
box5WordCloudKey.value += 1; box5WordCloudKey.value += 1;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论