Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
59089e47
提交
59089e47
authored
4月 22, 2026
作者:
朱政
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat:智库原文搜索高亮开发
上级
945bd0af
流水线
#593
已失败 于阶段
in 52 秒
变更
1
流水线
1
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
82 行增加
和
50 行删除
+82
-50
pdf.vue
src/views/thinkTank/reportOriginal/pdf.vue
+82
-50
没有找到文件。
src/views/thinkTank/reportOriginal/pdf.vue
浏览文件 @
59089e47
...
@@ -326,7 +326,79 @@ export default {
...
@@ -326,7 +326,79 @@ export default {
}
}
}
}
if
(
matchList
.
value
.
length
>
0
)
jumpTo
(
0
);
if
(
matchList
.
value
.
length
>
0
)
{
// 先把所有命中都标黄,再把“当前命中”改成蓝底
renderAllHighlights
();
jumpTo
(
0
);
}
};
const
setActiveHighlight
=
(
idx
)
=>
{
const
all
=
document
.
querySelectorAll
(
'.highlight-rect[data-match-idx]'
);
all
.
forEach
((
el
)
=>
{
const
isActive
=
Number
(
el
.
getAttribute
(
'data-match-idx'
))
===
Number
(
idx
);
if
(
isActive
)
{
el
.
classList
.
add
(
'highlight-rect--active'
);
}
else
{
el
.
classList
.
remove
(
'highlight-rect--active'
);
}
});
};
const
renderAllHighlights
=
()
=>
{
clearHighlights
();
const
list
=
Array
.
isArray
(
matchList
.
value
)
?
matchList
.
value
:
[];
list
.
forEach
((
m
,
idx
)
=>
{
if
(
!
m
||
m
.
fallback
)
return
;
const
layer
=
overlayMap
[
m
.
pageNum
];
if
(
!
layer
)
return
;
const
pageWrap
=
layer
.
closest
(
'.page-wrap'
);
const
container
=
(
pageWrap
||
layer
);
const
containerRect
=
container
.
getBoundingClientRect
();
const
segs
=
Array
.
isArray
(
m
?.
segments
)
?
m
.
segments
:
[];
for
(
const
seg
of
segs
)
{
const
segEl
=
seg
?.
el
;
if
(
!
segEl
)
continue
;
const
textNode
=
segEl
.
firstChild
;
if
(
!
textNode
||
textNode
.
nodeType
!==
Node
.
TEXT_NODE
)
continue
;
try
{
const
range
=
document
.
createRange
();
range
.
setStart
(
textNode
,
Math
.
max
(
0
,
seg
.
startIdx
??
0
));
range
.
setEnd
(
textNode
,
Math
.
max
(
0
,
seg
.
endIdx
??
0
));
const
rectList
=
Array
.
from
(
range
.
getClientRects
());
if
(
rectList
.
length
)
{
rectList
.
forEach
(
r
=>
{
const
mark
=
document
.
createElement
(
'div'
);
mark
.
className
=
'highlight-rect'
;
mark
.
setAttribute
(
'data-match-idx'
,
String
(
idx
));
mark
.
style
.
zIndex
=
'5'
;
mark
.
style
.
left
=
(
r
.
left
-
containerRect
.
left
)
+
'px'
;
mark
.
style
.
top
=
(
r
.
top
-
containerRect
.
top
)
+
'px'
;
mark
.
style
.
width
=
r
.
width
+
'px'
;
mark
.
style
.
height
=
r
.
height
+
'px'
;
container
.
appendChild
(
mark
);
});
}
else
{
const
r
=
segEl
.
getBoundingClientRect
();
if
(
r
.
width
>
0
&&
r
.
height
>
0
)
{
const
mark
=
document
.
createElement
(
'div'
);
mark
.
className
=
'highlight-rect'
;
mark
.
setAttribute
(
'data-match-idx'
,
String
(
idx
));
mark
.
style
.
zIndex
=
'5'
;
mark
.
style
.
left
=
(
r
.
left
-
containerRect
.
left
)
+
'px'
;
mark
.
style
.
top
=
(
r
.
top
-
containerRect
.
top
)
+
'px'
;
mark
.
style
.
width
=
r
.
width
+
'px'
;
mark
.
style
.
height
=
r
.
height
+
'px'
;
container
.
appendChild
(
mark
);
}
}
range
.
detach
?.();
}
catch
(
e
)
{
// ignore
}
}
});
setActiveHighlight
(
matchIdx
.
value
);
};
};
// 跳转到第 N 个匹配项
// 跳转到第 N 个匹配项
...
@@ -342,55 +414,7 @@ export default {
...
@@ -342,55 +414,7 @@ export default {
const
firstSeg
=
m
?.
segments
?.[
0
];
const
firstSeg
=
m
?.
segments
?.[
0
];
const
el
=
firstSeg
?.
el
;
const
el
=
firstSeg
?.
el
;
if
(
!
el
)
return
;
if
(
!
el
)
return
;
clearHighlights
();
setActiveHighlight
(
idx
);
const
layer
=
overlayMap
[
m
.
pageNum
];
if
(
!
layer
)
return
;
const
pageWrap
=
layer
.
closest
(
'.page-wrap'
);
// 用 Range 精确计算“子串”在页面上的矩形位置,再画黄色块(支持跨 span)
const
containerRect
=
(
pageWrap
||
layer
).
getBoundingClientRect
();
const
segs
=
Array
.
isArray
(
m
?.
segments
)
?
m
.
segments
:
[];
for
(
const
seg
of
segs
)
{
const
segEl
=
seg
?.
el
;
if
(
!
segEl
)
continue
;
const
textNode
=
segEl
.
firstChild
;
if
(
!
textNode
||
textNode
.
nodeType
!==
Node
.
TEXT_NODE
)
continue
;
try
{
const
range
=
document
.
createRange
();
range
.
setStart
(
textNode
,
Math
.
max
(
0
,
seg
.
startIdx
??
0
));
range
.
setEnd
(
textNode
,
Math
.
max
(
0
,
seg
.
endIdx
??
0
));
const
rectList
=
Array
.
from
(
range
.
getClientRects
());
if
(
rectList
.
length
)
{
rectList
.
forEach
(
r
=>
{
const
mark
=
document
.
createElement
(
'div'
);
mark
.
className
=
'highlight-rect'
;
mark
.
style
.
zIndex
=
'5'
;
mark
.
style
.
left
=
(
r
.
left
-
containerRect
.
left
)
+
'px'
;
mark
.
style
.
top
=
(
r
.
top
-
containerRect
.
top
)
+
'px'
;
mark
.
style
.
width
=
r
.
width
+
'px'
;
mark
.
style
.
height
=
r
.
height
+
'px'
;
(
pageWrap
||
layer
).
appendChild
(
mark
);
});
}
else
{
// Range 兜底为空时:用 span 自身的矩形画块(精度低,但尽量可见)
const
r
=
segEl
.
getBoundingClientRect
();
if
(
r
.
width
>
0
&&
r
.
height
>
0
)
{
const
mark
=
document
.
createElement
(
'div'
);
mark
.
className
=
'highlight-rect'
;
mark
.
style
.
zIndex
=
'5'
;
mark
.
style
.
left
=
(
r
.
left
-
containerRect
.
left
)
+
'px'
;
mark
.
style
.
top
=
(
r
.
top
-
containerRect
.
top
)
+
'px'
;
mark
.
style
.
width
=
r
.
width
+
'px'
;
mark
.
style
.
height
=
r
.
height
+
'px'
;
(
pageWrap
||
layer
).
appendChild
(
mark
);
}
}
range
.
detach
?.();
}
catch
(
e
)
{
// ignore
}
}
// 优先只滚动右侧 report-box,避免触发整页滚动导致 header 遮挡
// 优先只滚动右侧 report-box,避免触发整页滚动导致 header 遮挡
const
container
=
el
.
closest
(
'.report-box'
);
const
container
=
el
.
closest
(
'.report-box'
);
...
@@ -510,6 +534,10 @@ canvas {
...
@@ -510,6 +534,10 @@ canvas {
z-index
:
5
;
z-index
:
5
;
}
}
.textLayer
:deep
(
.highlight-rect--active
)
{
background
:
rgb
(
184
,
222
,
254
);
}
.page-wrap
:deep
(
.highlight-rect
)
{
.page-wrap
:deep
(
.highlight-rect
)
{
position
:
absolute
;
position
:
absolute
;
background
:
#ff0
;
background
:
#ff0
;
...
@@ -519,6 +547,10 @@ canvas {
...
@@ -519,6 +547,10 @@ canvas {
z-index
:
3
;
z-index
:
3
;
}
}
.page-wrap
:deep
(
.highlight-rect--active
)
{
background
:
rgb
(
184
,
222
,
254
);
}
.loading
{
.loading
{
position
:
absolute
;
position
:
absolute
;
top
:
50%
;
top
:
50%
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论