Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
18368a91
提交
18368a91
authored
4月 01, 2026
作者:
张伊明
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat 重构深度挖掘-流程概要全部样式
上级
02714a38
流水线
#269
已通过 于阶段
in 1 分 45 秒
变更
3
流水线
1
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
122 行增加
和
41 行删除
+122
-41
index.vue
src/views/bill/deepDig/processOverview/index.vue
+119
-39
index.vue
src/views/bill/introdoction/index.vue
+1
-0
index.vue
src/views/bill/template/index.vue
+2
-2
没有找到文件。
src/views/bill/deepDig/processOverview/index.vue
浏览文件 @
18368a91
...
...
@@ -153,7 +153,7 @@
class=
"item-box"
v-for=
"item in sharedEvents"
:key=
"`shared-$
{item.id}`"
style="width: 280px; flex-shrink: 0;
"
:style="{ width: TIMELINE_ITEM_WIDTH_PX + 'px', flexShrink: 0 }
"
>
<div
class=
"item-time"
>
{{
item
.
actionDate
}}
</div>
<div
class=
"item-box-dot"
></div>
...
...
@@ -211,7 +211,15 @@ const dialogPos = ref({ left: "0px", top: "0px" });
const
ORG_SENATE
=
"参议院"
;
const
ORG_HOUSE
=
"众议院"
;
const
PRESIDENT_KEYWORD
=
"呈递给总统"
;
/** 卡片宽度;同一条时间线上相邻圆点间距 ≥ 此值,避免同轨卡片横向重叠 */
const
TIMELINE_ITEM_WIDTH_PX
=
280
;
/** 时间线锚点为圆点;与样式 .item-box-dot { left: 10px } 一致 */
const
DOT_LEFT_IN_ITEM_BOX_PX
=
10
;
/** 与 scoped 样式中 .top/.bottom .content-box 的 margin-left 一致,用于跨轨圆点与「两密点中点」对齐 */
const
SENATE_CONTENT_BOX_MARGIN_LEFT_PX
=
134
;
const
HOUSE_CONTENT_BOX_MARGIN_LEFT_PX
=
30
;
/** 双轨主线在最后一个圆点/卡片之后保留的空白(原先用整卡宽 W 导致尾部过长) */
const
TIMELINE_LINE_TAIL_PADDING_PX
=
48
;
const
ARROW_SEGMENT_TOTAL_PX
=
16
;
const
DIAGONAL_LINE_WIDTH_PX
=
127
;
...
...
@@ -281,35 +289,72 @@ const dualLaneTimeline = computed(() => {
.
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
,
/**
* 双轨事件已按时间排好(dualLaneTimeline)。依次放置:与前一条同轨则绝对 x + W,
* 异轨则以前一条圆点绝对位置为锚 + 0.5W(方案 C)。单轨(灰线)仍用 sharedEvents 顺序定宽。
*/
const
dualLaneLayout
=
computed
(()
=>
{
const
U
=
dualLaneTimeline
.
value
;
const
W
=
TIMELINE_ITEM_WIDTH_PX
;
const
chamberRowSenate
=
(
item
)
=>
{
const
s
=
isSenateEvent
(
item
);
const
h
=
isHouseEvent
(
item
);
if
(
s
&&
!
h
)
return
true
;
if
(
h
&&
!
s
)
return
false
;
return
Boolean
(
s
);
};
const
idxInU
=
(
item
)
=>
U
.
indexOf
(
item
);
const
toSlots
=
(
list
,
posByItem
)
=>
list
.
map
((
item
)
=>
({
key
:
`
${
idxInU
(
item
)}
-
${
item
.
id
??
"e"
}
`,
item,
left
:
slotIndex
*
TIMELINE_ITEM_WIDTH_PX
});
slotIndex
+=
1
;
});
return
list
;
left: (posByItem.get(item) ?? 0) - DOT_LEFT_IN_ITEM_BOX_PX
}));
if (!U.length) {
return { senateSlots: [], houseSlots: [], maxDualLaneRightPx: 0 };
}
const posByItem = new Map();
let prevAbs = null;
let prevSenate = null;
for (const item of U) {
const sen = chamberRowSenate(item);
const margin = sen ? SENATE_CONTENT_BOX_MARGIN_LEFT_PX : HOUSE_CONTENT_BOX_MARGIN_LEFT_PX;
const absDot =
prevAbs === null ? margin : prevAbs + (sen === prevSenate ? W : W / 2);
posByItem.set(item, absDot - margin);
prevAbs = absDot;
prevSenate = sen;
}
/** 相对 content-box 左缘:卡片右边界 = layoutDotX - DOT_LEFT + W */
let maxDualLaneRightPx = 0;
for (const item of U) {
const layoutDotX = posByItem.get(item) ?? 0;
const rightPx = layoutDotX - DOT_LEFT_IN_ITEM_BOX_PX + W;
maxDualLaneRightPx = Math.max(maxDualLaneRightPx, rightPx);
}
return {
senateSlots: toSlots(
U.filter((item) => isSenateEvent(item)),
posByItem
),
houseSlots: toSlots(
U.filter((item) => isHouseEvent(item)),
posByItem
),
maxDualLaneRightPx
};
});
const
houseEventsPositioned
=
computed
(()
=>
{
const
list
=
[];
let
slotIndex
=
0
;
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 senateEventsPositioned = computed(() => dualLaneLayout.value.senateSlots);
const houseEventsPositioned = computed(() => dualLaneLayout.value.houseSlots);
const sharedEvents = computed(() => {
return sortedTimeline.value.filter((item, idx) => {
...
...
@@ -317,14 +362,25 @@ const sharedEvents = computed(() => {
});
});
const
dualLaneCount
=
computed
(()
=>
{
return
Math
.
max
(
senateEventsPositioned
.
value
.
length
,
houseEventsPositioned
.
value
.
length
);
/** 双轨 content-box 内所需宽度:最后卡片右缘 + 尾部留白(与 maxLineWidth 中的 extent 一致) */
const dualLaneContentExtentPx = computed(() => {
if (!dualLaneTimeline.value.length) return 0;
return (
dualLaneLayout.value.maxDualLaneRightPx + TIMELINE_LINE_TAIL_PADDING_PX
);
});
/**
* 双轨横线(top-line / bottom-line 共用)宽度:起点 left:110,需画到与卡片区右缘对齐。
* 右缘 x = 120 + 参院 margin + extent = 254 + extent,故宽度 = 254 + extent - 110 = 144 + extent。
* 旧式 254+extent 多 110px,导致上下线都偏长。
*/
const maxLineWidth = computed(() => {
const
senateWidth
=
254
+
dualLaneCount
.
value
*
TIMELINE_ITEM_WIDTH_PX
;
const
houseWidth
=
150
+
dualLaneCount
.
value
*
TIMELINE_ITEM_WIDTH_PX
;
return
Math
.
max
(
senateWidth
,
houseWidth
);
if (!dualLaneTimeline.value.length) {
return Math.max(254, 150);
}
const extent = dualLaneContentExtentPx.value;
return 120 + SENATE_CONTENT_BOX_MARGIN_LEFT_PX + extent - 110;
});
const lineWidth = computed(() => `
$
{
maxLineWidth
.
value
}
px
`);
...
...
@@ -350,22 +406,41 @@ const rightArrowCount = computed(() => {
return Math.max(1, Math.ceil(sharedLineWidth.value / ARROW_SEGMENT_TOTAL_PX));
});
/** 参院 content 起点更靠右(margin 134 vs 30),众院 box 需多 104px 才能与参院右缘对齐 */
const CONTENT_BOX_WIDTH_DELTA_SENATE_HOUSE_PX =
SENATE_CONTENT_BOX_MARGIN_LEFT_PX - HOUSE_CONTENT_BOX_MARGIN_LEFT_PX;
const senateBoxStyle = computed(() => ({
width
:
`
${
maxLineWidth
.
value
+
110
-
254
}
px`
,
width: `
$
{
dualLaneTimeline
.
value
.
length
?
dualLaneContentExtentPx
.
value
:
110
}
px
`,
justifyContent: "flex-start"
}));
const houseBoxStyle = computed(() => ({
width
:
`
${
maxLineWidth
.
value
+
110
-
150
}
px`
,
width: `
$
{
dualLaneTimeline
.
value
.
length
?
dualLaneContentExtentPx
.
value
+
CONTENT_BOX_WIDTH_DELTA_SENATE_HOUSE_PX
:
214
}
px
`,
justifyContent: "flex-start"
}));
const rightPos = computed(() => `
$
{
maxLineWidth
.
value
+
90
}
px
`);
const
sharedBoxStyle
=
computed
(()
=>
({
left
:
`
${
maxLineWidth
.
value
+
219
}
px`
,
const sharedBoxStyle = computed(() => {
const rightTopPx = Number.parseFloat(String(rightTop.value)) || 0;
const rightCenterY = rightTopPx + 12;
return {
left: `
$
{
maxLineWidth
.
value
+
230
}
px
`,
top: `
$
{
rightCenterY
}
px
`,
transform: "translateY(-100%)",
width: `
$
{
Math
.
max
(
sharedLineWidth
.
value
,
sharedEvents
.
value
.
length
*
TIMELINE_ITEM_WIDTH_PX
)}
px
`
}));
};
});
const topLineEndRef = ref(null);
const bottomLineEndRef = ref(null);
...
...
@@ -547,13 +622,18 @@ const updateRightTop = () => {
}
}
/* .top 高 260px,时间线 top:242px;卡片下缘应对齐线顶:距容器底 18px */
.content-box
{
position
:
relative
;
margin-left
:
134px
;
margin-bottom
:
19px
;
margin-bottom
:
0
;
align-self
:
stretch
;
min-height
:
0
;
.item-box
{
position
:
absolute
;
top
:
auto
;
bottom
:
18px
;
}
}
}
...
...
@@ -808,7 +888,7 @@ const updateRightTop = () => {
.shared-content-box
{
position
:
absolute
;
top
:
170
px
;
top
:
254
px
;
display
:
flex
;
.item-box
{
...
...
src/views/bill/introdoction/index.vue
浏览文件 @
18368a91
...
...
@@ -834,6 +834,7 @@ onMounted(() => {
flex
-
shrink
:
1
;
max
-
width
:
170
px
;
text
-
align
:
center
;
margin
-
bottom
:
10
px
;
}
.
nameItemActive
{
...
...
src/views/bill/template/index.vue
浏览文件 @
18368a91
...
...
@@ -46,7 +46,7 @@
<div
class=
"chart-ai-wrap"
>
<div
:class=
"['right-box2-main', { 'right-box-main--full': !domainFooterText }]"
id=
"chart2"
></div>
<div
class=
"overview-tip-row"
>
<TipTab
class=
"overview-tip"
/>
<TipTab
class=
"overview-tip"
:text=
"'涉华科技法案数量及通过率变化趋势,数据来源:美国国会官网'"
/>
<AiButton
class=
"overview-tip-action"
@
mouseenter=
"handleShowAiPane('domain')"
/>
</div>
<div
v-if=
"aiPaneVisible.domain"
class=
"overview-ai-pane"
...
...
@@ -72,7 +72,7 @@
<div
class=
"chart-ai-wrap"
>
<div
:class=
"['right-box1-main', { 'right-box-main--full': !limitFooterText }]"
id=
"chart1"
></div>
<div
class=
"overview-tip-row"
>
<TipTab
class=
"overview-tip"
/>
<TipTab
class=
"overview-tip"
:text=
"'涉华科技法案数量及通过率变化趋势,数据来源:美国国会官网'"
/>
<AiButton
class=
"overview-tip-action"
@
mouseenter=
"handleShowAiPane('limit')"
/>
</div>
<div
v-if=
"aiPaneVisible.limit"
class=
"overview-ai-pane"
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论