Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
1
合并请求
1
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
94274ead
提交
94274ead
authored
3月 12, 2026
作者:
hsx
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat:新闻详情页
上级
7505facb
显示空白字符变更
内嵌
并排
正在显示
14 个修改的文件
包含
224 行增加
和
125 行删除
+224
-125
.gitignore
.gitignore
+1
-0
index.ts
src/api/intelligent/index.ts
+21
-0
newsBrief.js
src/api/news/newsBrief.js
+1
-1
ColorSvg.vue
src/components/base/images/ColorSvg.vue
+1
-2
NewsItem.vue
src/components/base/newsList/NewsItem.vue
+18
-92
CommonText.vue
src/components/base/texts/CommonText.vue
+3
-3
IntelligentEntityText.vue
src/components/base/texts/IntelligentEntityText.vue
+125
-0
search.png
src/components/base/texts/images/search.png
+0
-0
common.scss
src/styles/common.scss
+7
-0
index.vue
src/styles/components/index.vue
+1
-1
ModeuleNews.vue
src/views/newsBrief/ModeuleNews.vue
+4
-1
NewsDetial.vue
src/views/newsBrief/NewsDetial.vue
+37
-9
index.vue
src/views/newsBrief/index.vue
+0
-16
vite.config.js
vite.config.js
+5
-0
没有找到文件。
.gitignore
浏览文件 @
94274ead
...
...
@@ -10,6 +10,7 @@ lerna-debug.log*
*.rar
*.zip
*.7z
*.rest
# Dependencies
node_modules
...
...
src/api/intelligent/index.ts
0 → 100644
浏览文件 @
94274ead
import
request
from
"@/api/request.js"
;
const
INTELLECTUAL_API
=
"/intelligent-api"
;
export
class
IntelligentResultWrapper
<
T
>
{
result
:
T
;
status
:
string
;
}
export
class
TextEntity
{
text_span
:
string
;
type
:
string
;
}
// 智能化:提取文本实体
export
function
extractTextEntity
(
text
:
string
):
Promise
<
IntelligentResultWrapper
<
TextEntity
[]
>>
{
return
request
({
url
:
`
${
INTELLECTUAL_API
}
/extract-entity`
,
method
:
"POST"
,
data
:
{
text
}
});
}
src/api/news/newsBrief.js
浏览文件 @
94274ead
...
...
@@ -35,7 +35,7 @@ export function getHotNews() {
export
function
getHotNewsByArea
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/news/hot
News
`
,
url
:
`/api/news/hot
AreaNews/
${
params
.
moduleId
}
`
,
params
})
}
...
...
src/components/base/images/ColorSvg.vue
浏览文件 @
94274ead
...
...
@@ -8,7 +8,6 @@
</
template
>
<
script
setup
lang=
"ts"
>
import
{
size
}
from
'lodash'
;
import
{
ref
,
computed
,
watch
,
onMounted
}
from
'vue'
;
// 组件属性
...
...
@@ -83,7 +82,7 @@ const processedSvgContent = computed(() => {
});
}
console
.
log
(
processed
)
//
console.log(processed)
return
processed
;
});
...
...
src/components/base/newsList/NewsItem.vue
浏览文件 @
94274ead
<
template
>
<div
class=
"box3-item"
@
click=
"handleToNewsAnalysis(news)"
>
<div
class=
"left"
>
<img
:src=
"news[props.img] ? news[props.img] : DefaultIconNews"
alt=
""
/>
</div>
<div
class=
"right"
>
<div
class=
"right-top"
>
<div
class=
"title"
><span
class=
"text-inner"
>
{{
news
[
props
.
title
]
}}
</span></div>
<div
class=
"time"
>
{{
news
[
props
.
from
]
}}
</div>
</div>
<div
class=
"right-footer"
>
{{
news
[
props
.
content
]
}}
</div>
</div>
</div>
<el-space
alignment=
"flex-start"
:size=
"10"
>
<img
:width=
"64"
:height=
"52"
:src=
"news ?? DefaultIconNews"
alt=
""
/>
<el-space
direction=
"vertical"
alignment=
"flex-start"
:size=
"0"
>
<common-text
:line-limit=
"1"
class=
"text-regular text-hover"
color=
"var(--text-primary-80-color)"
>
{{
title
}}
</common-text>
<common-text
:line-limit=
"1"
class=
"text-tip-1"
color=
"var(--text-primary-65-color)"
>
{{
from
}}
</common-text>
</el-space>
</el-space>
</
template
>
<
script
setup
>
import
DefaultIconNews
from
"@/assets/icons/default-icon-news.png"
;
const
props
=
defineProps
({
// 新闻列表数据
news
:
{
type
:
Object
,
default
:
()
=>
{
}
},
import
{
ElSpace
}
from
"element-plus"
;
import
CommonText
from
"../texts/CommonText.vue"
;
const
props
=
defineProps
({
img
:
{
type
:
String
,
default
:
'
img
'
default
:
''
},
title
:
{
type
:
String
,
default
:
"
title
"
default
:
""
},
from
:
{
type
:
String
,
default
:
"
from
"
default
:
""
},
content
:
{
type
:
String
,
default
:
"
content
"
default
:
""
},
});
...
...
@@ -49,72 +44,4 @@ const handleToNewsAnalysis = (item, index) => {
</
script
>
<
style
lang=
"scss"
scoped
>
@use
'@/styles/common.scss'
;
.box3-item
{
display
:
flex
;
align-items
:
center
;
height
:
78px
;
margin
:
0px
21px
;
cursor
:
pointer
;
&
:hover
{
.right-top
.title
{
color
:
rgb
(
5
,
95
,
194
)
!
important
;
font-weight
:
700
;
}
.right-top
.text-inner
{
border-bottom-color
:
rgb
(
5
,
95
,
194
)
!
important
;
}
}
}
.left
{
width
:
97px
;
// flex-shrink: 0;
height
:
72px
;
img
{
width
:
100%
;
height
:
100%
;
border-radius
:
4px
;
}
}
.right
{
flex
:
1
;
min-width
:
0
;
margin-left
:
20px
;
.right-top
{
display
:
flex
;
justify-content
:
space-between
;
.title
{
// width: 500px;
@extend
.text-title-3-bold
;
color
:
var
(
--
text-primary-80-color
);
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
.text-inner
{
border-bottom
:
1px
solid
transparent
;
}
}
.time
{
text-align
:
right
;
@extend
.text-tip-2
;
color
:
var
(
--
text-primary-65-color
);
}
}
.right-footer
{
@extend
.text-compact
;
color
:
var
(
--
text-primary-65-color
);
@include
common
.
text-ellipsis
(
2
);
}
}
</
style
>
\ No newline at end of file
src/components/base/texts/CommonText.vue
浏览文件 @
94274ead
<
template
>
<div
class=
"common-text"
>
<div
class=
"common-text
-box-hudf
"
>
<slot></slot>
</div>
</
template
>
...
...
@@ -18,8 +18,8 @@ const props = defineProps({
<
style
lang=
"scss"
scoped
>
@use
'@/styles/common.scss'
;
.common-text
{
color
:
v-bind
(
color
);
.common-text
-box-hudf
{
color
:
v-bind
(
color
)
!
important
;
@if
(
'v-bind(lineLimit) !==null'
)
{
@include
common
.
text-ellipsis
(
v-bind
(
lineLimit
));
...
...
src/components/base/texts/IntelligentEntityText.vue
0 → 100644
浏览文件 @
94274ead
<
template
>
<p
class=
"p-regular-rereg"
>
<span
class=
"text-regular"
v-for=
"(segment, index) in processedText"
:key=
"index"
>
<a
v-if=
"segment.isEntity"
:href=
"`https://cn.bing.com/search?q=$
{segment.entity?.text_span}`"
class="entity-link" target="_blank" rel="noopener noreferrer">
{{
segment
.
entity
?.
text_span
}}
<img
:src=
"SearchIcon"
:width=
"10"
:height=
"10"
alt=
"search"
/>
</a>
<span
v-else
>
{{
segment
.
text
}}
</span>
</span>
</p>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
TextEntity
}
from
'@/api/intelligent'
;
import
{
ref
,
watch
,
onMounted
}
from
'vue'
;
import
SearchIcon
from
'./images/search.png'
export
interface
ProcessedTextSegment
{
text
:
string
isEntity
:
boolean
entity
?:
TextEntity
}
const
props
=
defineProps
({
text
:
{
type
:
String
,
default
:
''
}
,
entities
:
{
type
:
Array
<
TextEntity
>
,
default
:
()
=>
[]
}
})
// 处理后的文本段
const
processedText
=
ref
<
ProcessedTextSegment
[]
>
([])
// 处理文本,识别并替换实体
const
processText
=
()
=>
{
if
(
!
props
.
text
||
!
props
.
entities
)
{
console
.
log
(
'props.text'
,
props
.
entities
.
length
)
processedText
.
value
=
[{
text
:
''
,
isEntity
:
false
}]
return
}
const
result
=
[]
let
currentPosition
=
0
// 按实体文本长度排序,优先匹配长文本
const
sortedEntities
=
[...
props
.
entities
].
sort
((
a
,
b
)
=>
b
.
text_span
.
length
-
a
.
text_span
.
length
)
while
(
currentPosition
<
props
.
text
.
length
)
{
let
matched
=
false
for
(
const
entity
of
sortedEntities
)
{
const
entityText
=
entity
.
text_span
const
endPosition
=
currentPosition
+
entityText
.
length
if
(
props
.
text
.
substring
(
currentPosition
,
endPosition
)
===
entityText
)
{
// 如果当前位置是实体,添加到结果
result
.
push
({
isEntity
:
true
,
entity
:
{
...
entity
}
})
currentPosition
=
endPosition
matched
=
true
break
}
}
if
(
!
matched
)
{
// 如果不是实体,收集普通文本
let
nextEntityStart
=
props
.
text
.
length
for
(
const
entity
of
sortedEntities
)
{
const
pos
=
props
.
text
.
indexOf
(
entity
.
text_span
,
currentPosition
)
if
(
pos
!==
-
1
&&
pos
<
nextEntityStart
)
{
nextEntityStart
=
pos
}
}
if
(
nextEntityStart
>
currentPosition
)
{
const
plainText
=
props
.
text
.
substring
(
currentPosition
,
nextEntityStart
)
result
.
push
({
text
:
plainText
,
isEntity
:
false
})
currentPosition
=
nextEntityStart
}
else
{
// 没有更多实体,添加剩余文本
const
remainingText
=
props
.
text
.
substring
(
currentPosition
)
if
(
remainingText
)
{
result
.
push
({
text
:
remainingText
,
isEntity
:
false
})
}
currentPosition
=
props
.
text
.
length
}
}
}
processedText
.
value
=
result
}
// 监听文本和实体变化
watch
(()
=>
props
.
text
,
processText
)
watch
(()
=>
props
.
entities
,
processText
,
{
deep
:
true
})
// 初始化处理
onMounted
(
processText
)
</
script
>
<
style
lang=
"scss"
scoped
>
@use
'@/styles/common.scss'
;
.entity-link
{
color
:
var
(
--
color-primary-100
);
}
.p-regular-rereg
{
text-indent
:
2em
;
}
</
style
>
\ No newline at end of file
src/components/base/texts/images/search.png
0 → 100644
浏览文件 @
94274ead
1.7 KB
src/styles/common.scss
浏览文件 @
94274ead
...
...
@@ -71,6 +71,13 @@
color
:
var
(
--
text-primary-80
);
}
.text-hover
{
&
:hover
{
color
:
rgb
(
5
,
95
,
194
)
!
important
;
font-weight
:
700
;
}
}
//0级标题
.text-title-0
{
@extend
.text-base
;
...
...
src/styles/components/index.vue
浏览文件 @
94274ead
...
...
@@ -8,7 +8,7 @@
<div
class=
"text-title-1-show"
>
文字样式
</div>
<TextStyle
/>
<div
class=
"text-title-1-show"
>
通用样式/组件
</div>
<div
style=
"position: relative; min-height:
3
00px;"
>
<div
style=
"position: relative; min-height:
7
00px;"
>
<el-tabs
tabPosition=
"left"
class=
"tabs-nav-no-wrap left-float-nav-tabs"
>
<el-tab-pane
label=
"通用"
lazy
>
<common-page
/>
...
...
src/views/newsBrief/ModeuleNews.vue
浏览文件 @
94274ead
...
...
@@ -56,8 +56,11 @@ onMounted(async () => {
async
function
changeArea
(
id
)
{
const
{
data
}
=
await
getHotNewsByArea
({
moduleId
:
moduleId
.
value
,
industryId
:
id
,
industryId
:
id
?
id
:
null
,
});
data
?.
forEach
(
item
=>
{
item
.
newsImage
=
item
.
coverUrl
??
""
})
NewsData
.
value
=
data
??
[];
}
...
...
src/views/newsBrief/NewsDetial.vue
浏览文件 @
94274ead
...
...
@@ -11,9 +11,9 @@
{{
newsDetail
.
title
}}
</common-text>
<common-text
class=
"text-tip-1-bold"
color=
"var(--text-primary-65-color)"
>
{{
`${newsDetail.publishedTime
}
· ${newsDetail.source
}
`
}}
{{
`${newsDetail.publishedTime
}
· ${newsDetail.source
}
`
}}
<
el
-
space
>
<
area
-
tag
:
area
-
name
=
"newsDetail.area
Name"
/>
<
area
-
tag
v
-
for
=
"item in newsDetail.domainList"
:
key
=
"item"
:
tag
-
name
=
"item.industry
Name"
/>
<
/el-space
>
<
/common-text
>
<
/el-space
>
...
...
@@ -28,11 +28,12 @@
<
/div
>
<
div
class
=
"flex-display common-page content-box-news-detail"
>
<
el
-
space
direction
=
"vertical"
class
=
"background-as-card flex-fill"
fill
alignment
=
"flex-start"
>
<
div
style
=
"margin-top: 10px; margin-right: 24px;"
class
=
"flex-display"
>
<
div
style
=
"margin-top: 10px; margin-right: 24px;
gap:10px
"
class
=
"flex-display"
>
<
color
-
prefix
-
title
height
=
"20px"
>
<
div
class
=
"text-title-2-bold"
>
新闻内容
<
/div
>
<
/color-prefix-title
>
<
div
class
=
"flex-fill"
><
/div
>
<
el
-
switch
v
-
model
=
"isHightLightEntity"
active
-
text
=
"高亮实体"
@
change
=
"handleHighlightEntity"
/>
<
el
-
button
v
-
if
=
"hasTranslation"
:
type
=
"isOpenTranslation ? 'primary' : ''"
plain
@
click
=
"handleTranslation"
>
<
color
-
svg
:
svg
-
url
=
"TranslationSvg"
color
=
"var(--color-primary-100)"
:
size
=
"18"
...
...
@@ -42,11 +43,12 @@
<
/div
>
<
div
class
=
"common-padding"
>
<
div
class
=
"flex-display"
style
=
"align-items: center;"
>
<
common
-
text
class
=
"text-title-3-bold"
color
=
"var(--text-primary-80-color)"
>
中文
<
/common-text
>
<
common
-
text
class
=
"text-title-3-bold"
color
=
"var(--text-primary-80-color)"
>
{{
isOpenTranslation
?
'中文'
:
'原文'
}}
<
/common-text
>
<
div
class
=
"flex-fill"
style
=
"margin: 0 10px;"
>
<
el
-
divider
><
/el-divider
>
<
/div
>
<
el
-
button
@
click
=
"() => showMore = !showMore"
>
<
el
-
button
v
-
if
=
"zhEnTexts.length > 6"
@
click
=
"() => showMore = !showMore"
>
{{
showMore
?
'收起'
:
'展开'
}}
<
el
-
icon
>
<
arrow
-
down
v
-
if
=
"showMore"
/>
...
...
@@ -57,7 +59,9 @@
<
el
-
row
:
gutter
=
"32"
>
<
el
-
col
:
span
=
"znEnColSpan"
v
-
for
=
"(item, index) in showMore ? zhEnTexts : zhEnTexts.slice(0, 6)"
:
key
=
"index"
>
<
p
class
=
"p-news-content"
>
{{
item
}}
<
/p
>
<!--
<
p
class
=
"p-news-content"
>
{{
item
}}
<
/p> --
>
<
intelligent
-
entity
-
text
:
text
=
"item"
:
entities
=
"isHightLightEntity ? textEntities : []"
><
/intelligent-entity-text
>
<
/el-col
>
<
/el-row
>
<
/div
>
...
...
@@ -68,8 +72,10 @@
<
div
class
=
"text-title-2-bold"
>
相关新闻
<
/div
>
<
/color-prefix-title
>
<
/el-space
>
<
el
-
space
style
=
"margin-top: 10px;"
>
<
news
-
item
v
-
for
=
"item in relationNews"
:
key
=
"item.newsId"
:
news
-
item
=
"item"
/>
<
el
-
space
direction
=
"vertical"
fill
class
=
"common-padding"
>
<
news
-
item
v
-
for
=
"item in relationNews"
:
key
=
"item.newsId"
:
news
=
"item"
:
img
=
"item.newsImage"
:
title
=
"item.newsTitle"
:
from
=
"`${item.newsDate
}
· ${item.newsOrg
}
`"
@
click
=
"gotoNewsDetail(item.newsId)"
/>
<
/el-space
>
<
/el-space
>
<
/div
>
...
...
@@ -81,7 +87,7 @@ import '@/styles/container.scss';
import
'@/styles/common.scss'
;
import
{
ref
,
onMounted
}
from
"vue"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
ElSpace
,
ElImage
,
ElButton
,
ElIcon
,
ElScrollbar
,
ElRow
,
ElCol
,
ElDivider
}
from
"element-plus"
;
import
{
ElSpace
,
ElImage
,
ElButton
,
ElIcon
,
ElScrollbar
,
ElRow
,
ElCol
,
ElDivider
,
ElSwitch
}
from
"element-plus"
;
import
CommonText
from
"@/components/base/texts/CommonText.vue"
;
import
AreaTag
from
"@/components/base/AreaTag/index.vue"
;
import
ColorPrefixTitle
from
'@/components/base/texts/ColorPrefixTitle.vue'
;
...
...
@@ -90,14 +96,22 @@ import NewsItem from "@/components/base/newsList/NewsItem.vue";
import
ColorSvg
from
"@/components/base/images/ColorSvg.vue"
;
import
TranslationSvg
from
'./assets/images/翻译 1.svg'
;
import
NewsLogo
from
'./assets/images/组合 293.svg'
;
import
{
extractTextEntity
}
from
"@/api/intelligent"
;
import
{
useGotoNewsDetail
}
from
"@/router/modules/news"
;
import
IntelligentEntityText
from
"@/components/base/texts/IntelligentEntityText.vue"
;
const
newsDetail
=
ref
({
}
);
const
relationNews
=
ref
([]);
const
zhEnTexts
=
ref
([]);
const
znEnColSpan
=
ref
(
12
);
const
hasTranslation
=
ref
(
false
);
const
isOpenTranslation
=
ref
(
true
);
const
isHightLightEntity
=
ref
(
true
);
const
textEntities
=
ref
([]);
const
showMore
=
ref
(
false
);
const
route
=
useRoute
();
const
gotoNewsDetail
=
useGotoNewsDetail
();
onMounted
(
async
()
=>
{
const
params
=
{
newsId
:
route
.
params
.
id
...
...
@@ -107,9 +121,23 @@ onMounted(async () => {
const
{
data
:
relationNewsData
}
=
await
getRelationNews
(
params
);
relationNews
.
value
=
relationNewsData
??
[];
console
.
log
(
relationNews
.
value
)
updateText
();
await
handleHighlightEntity
();
}
);
async
function
handleHighlightEntity
()
{
if
(
textEntities
.
value
.
length
>
0
)
return
const
{
result
:
entityDataZh
}
=
await
extractTextEntity
(
newsDetail
.
value
.
contentZh
);
textEntities
.
value
=
[...
entityDataZh
??
[]]
if
(
newsDetail
.
value
.
contentZh
!==
newsDetail
.
value
.
content
)
{
const
{
result
:
entityData
}
=
await
extractTextEntity
(
newsDetail
.
value
.
content
);
textEntities
.
value
=
[...
textEntities
.
value
,
...
entityData
??
[]]
}
}
function
handleTranslation
()
{
isOpenTranslation
.
value
=
!
isOpenTranslation
.
value
;
updateText
();
...
...
src/views/newsBrief/index.vue
浏览文件 @
94274ead
...
...
@@ -15,31 +15,15 @@
<
script
setup
>
import
{
ref
,
onMounted
}
from
"vue"
;
import
'@/styles/container.scss'
;
import
{
useRoute
}
from
"vue-router"
;
import
Headlines
from
"./Headlines.vue"
;
import
Subject
from
"./Subject.vue"
;
import
{
ElInput
,
ElSpace
,
ElImage
,
ElDivider
,
ElCol
,
ElRow
}
from
"element-plus"
;
import
AreaTag
from
'@/components/base/AreaTag/index.vue'
import
CommonText
from
"@/components/base/texts/CommonText.vue"
;
import
NewsMain
from
"./NewsMain.vue"
;
import
SearchBox
from
"@/components/base/SearchBox/index.vue"
;
//顶部数据搜索
const
searchInput
=
ref
(
""
);
//当前页面显示
const
showPage
=
ref
(
"home"
);
const
changePage
=
page
=>
{
console
.
log
(
page
);
showPage
.
value
=
page
;
};
</
script
>
<
style
lang=
"scss"
scoped
>
...
...
vite.config.js
浏览文件 @
94274ead
...
...
@@ -104,6 +104,11 @@ export default defineConfig({
proxyReq
.
setHeader
(
'Cache-Control'
,
'no-cache'
);
});
}
},
'/intelligent-api'
:
{
target
:
'http://8.140.26.4:10029/'
,
changeOrigin
:
true
,
rewrite
:
(
path
)
=>
path
.
replace
(
/^
\/
intelligent-api/
,
''
)
}
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论