Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
1
合并请求
1
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
0204674d
提交
0204674d
authored
4月 21, 2026
作者:
张烨
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'origin/pre' into zy-dev
上级
d3315d67
f0cdfc5f
流水线
#567
已通过 于阶段
in 1 分 34 秒
变更
41
流水线
1
隐藏空白字符变更
内嵌
并排
正在显示
41 个修改的文件
包含
1822 行增加
和
852 行删除
+1822
-852
service-back.js
src/api/finance/service-back.js
+153
-0
service.js
src/api/finance/service.js
+55
-22
index.js
src/api/zmOverview/risk/index.js
+8
-0
risk-signal-overview-detail-dialog.scss
...rviewDetailDialog/risk-signal-overview-detail-dialog.scss
+23
-1
index.vue
src/components/base/SummaryCardsPanel/index.vue
+5
-1
index.vue
src/components/base/moduleHeader/index.vue
+37
-48
index.vue
src/components/base/riskSignal/index.vue
+8
-3
index.js
src/router/index.js
+5
-45
bill.js
src/router/modules/bill.js
+1
-1
goToPage.js
src/utils/goToPage.js
+53
-0
riskSignalOverviewDetailHelpers.js
src/utils/riskSignalOverviewDetailHelpers.js
+4
-4
index.vue
src/views/ZMOverView/components/newRisk/index.vue
+118
-37
index.vue
src/views/bill/allCommittee/index.vue
+63
-5
box8-header-icon.png
src/views/bill/billHome/assets/images/box8-header-icon.png
+0
-0
index.vue
src/views/bill/billHome/index.vue
+176
-104
doublePieChart.js
src/views/bill/billHome/utils/doublePieChart.js
+1
-1
piechart.js
src/views/bill/billHome/utils/piechart.js
+2
-1
index.vue
src/views/comprehensiveSearch/searchResults/index.vue
+302
-124
index.vue
src/views/coopRestriction/components/dataSub/index.vue
+43
-46
index.vue
src/views/coopRestriction/components/resLib/index.vue
+56
-32
index.vue
src/views/coopRestriction/detail/index.vue
+19
-5
index.vue
src/views/coopRestriction/index.vue
+1
-0
index.vue
src/views/dataLibrary/bill/countryBill/index.vue
+3
-3
lineChart.js
src/views/dataLibrary/components/LineChart/lineChart.js
+1
-0
piechart.js
src/views/dataLibrary/components/PieChart/piechart.js
+4
-3
index.vue
src/views/dataLibrary/index.vue
+16
-8
index.vue
src/views/dataLibrary/news/index.vue
+1
-1
index.vue
src/views/decree/institution/index.vue
+44
-11
index.vue
src/views/exportControl/index.vue
+12
-15
index.vue
src/views/finance/index.vue
+24
-22
common-back.js
src/views/finance/utils/common-back.js
+63
-0
common.js
src/views/finance/utils/common.js
+45
-8
index.vue
...views/marketAccessRestrictions/marketAccessHome/index.vue
+1
-0
ModeuleNews.vue
src/views/newsBrief/ModeuleNews.vue
+76
-72
index.vue
src/views/ruleRestriction/detail/index.vue
+294
-185
index.vue
src/views/thinkTank/index.vue
+1
-1
danger.svg
src/views/viewRiskSignal/assets/images/danger.svg
+5
-0
warning.svg
src/views/viewRiskSignal/assets/images/warning.svg
+9
-0
index.vue
src/views/viewRiskSignal/index.vue
+87
-34
cleandarHeat.js
src/views/viewRiskSignal/utils/cleandarHeat.js
+1
-1
vite.config.js
vite.config.js
+2
-8
没有找到文件。
src/api/finance/service-back.js
0 → 100644
浏览文件 @
0204674d
// 引入 axios 请求
import
axios
from
'axios'
// 引入 element-plus 里面的消息提示
import
{
ElMessage
}
from
'element-plus'
import
{
getToken
,
setToken
,
removeToken
,
formatBearerAuthorization
}
from
'@/api/request.js'
export
{
getToken
,
setToken
,
removeToken
}
// 【新增】全局 AbortController,用于管理所有通过此 service 发出的请求
let
globalAbortController
=
new
AbortController
()
// 【新增】暴露一个方法,供外部(如路由守卫)调用以取消所有正在进行的请求
export
const
cancelAllRequests
=
()
=>
{
if
(
globalAbortController
)
{
globalAbortController
.
abort
()
// 创建一个新的 Controller 以备下次使用
globalAbortController
=
new
AbortController
()
}
}
// 创建 axios 实例
const
service
=
axios
.
create
({
timeout
:
30
*
1000
// 请求超时时间
})
// request 拦截器:与主 request 一致,就地改 config,避免 mergeConfig 破坏 url
service
.
interceptors
.
request
.
use
(
config
=>
{
const
raw
=
getToken
()
const
token
=
raw
?
String
(
raw
).
trim
()
:
""
if
(
!
config
.
headers
)
{
config
.
headers
=
new
axios
.
AxiosHeaders
()
}
else
if
(
!
(
config
.
headers
instanceof
axios
.
AxiosHeaders
))
{
config
.
headers
=
axios
.
AxiosHeaders
.
from
(
config
.
headers
)
}
if
(
token
)
{
config
.
headers
.
set
(
'token'
,
token
,
true
)
}
else
{
config
.
headers
.
delete
(
'token'
)
config
.
headers
.
delete
(
'Token'
)
}
const
reqUrl
=
String
(
config
.
url
??
''
)
if
(
reqUrl
.
includes
(
'aiAnalysis'
))
{
const
aiApiKey
=
import
.
meta
.
env
.
VITE_AI_ANALYSIS_API_KEY
if
(
aiApiKey
)
{
if
(
!
config
.
headers
)
{
config
.
headers
=
new
axios
.
AxiosHeaders
()
}
else
if
(
!
(
config
.
headers
instanceof
axios
.
AxiosHeaders
))
{
config
.
headers
=
axios
.
AxiosHeaders
.
from
(
config
.
headers
)
}
config
.
headers
.
set
(
'X-API-Key'
,
aiApiKey
)
}
}
// 【新增】将全局控制器的 signal 注入到当前请求中
// 注意:如果 config 中已经手动传入了 signal(例如组件内单独控制),则优先使用组件内的
if
(
!
config
.
signal
)
{
config
.
signal
=
globalAbortController
.
signal
}
return
config
},
error
=>
{
console
.
log
(
error
)
return
Promise
.
reject
(
error
)
})
// response 拦截器
service
.
interceptors
.
response
.
use
(
response
=>
{
const
res
=
response
?.
data
if
(
!
res
)
{
return
Promise
.
reject
(
new
Error
(
'响应数据为空'
))
}
// 根据需求:接口返回 code 不等于 200 的时候报错
if
(
res
.
code
!==
200
)
{
ElMessage
({
message
:
res
.
message
||
'请求失败'
,
type
:
'error'
,
duration
:
3
*
1000
})
return
Promise
.
reject
(
res
)
}
return
res
.
data
},
error
=>
{
console
.
log
(
'err'
+
error
)
const
isCanceledError
=
error
?.
code
===
'ERR_CANCELED'
||
error
?.
name
===
'CanceledError'
||
error
?.
name
===
'AbortError'
||
(
typeof
error
?.
message
===
'string'
&&
/canceled/i
.
test
(
error
.
message
))
if
(
isCanceledError
)
return
Promise
.
reject
(
error
)
// 处理 token 过期或无效的情况
const
errUrl
=
String
(
error
.
config
?.
url
||
''
)
const
isAiAnalysisRequest
=
errUrl
.
includes
(
'aiAnalysis'
)
if
(
error
.
response
&&
(
error
.
response
.
status
===
401
||
error
.
response
.
status
===
403
)
&&
!
isAiAnalysisRequest
)
{
ElMessage
({
message
:
'Token 已过期,请重新登录'
,
type
:
'error'
,
duration
:
3
*
1000
})
const
h
=
error
.
config
?.
headers
const
hadToken
=
h
&&
(
typeof
h
.
get
===
'function'
?
Boolean
(
h
.
get
(
'token'
)
||
h
.
get
(
'Token'
)
)
:
Boolean
(
h
.
token
||
h
.
Token
))
if
(
hadToken
)
removeToken
()
}
else
{
ElMessage
({
message
:
typeof
error
?.
message
===
'string'
?
error
.
message
:
'请求失败'
,
type
:
'error'
,
duration
:
3
*
1000
})
}
return
Promise
.
reject
(
error
)
}
)
// 封装通用请求函数(支持 http(config) 和 http.get/post 等调用方式)
function
http
(
config
)
{
return
service
(
config
)
}
// 为 http 函数添加快捷方法
http
.
get
=
function
(
url
,
params
)
{
return
service
({
url
,
method
:
'get'
,
params
})
}
http
.
post
=
function
(
url
,
data
)
{
return
service
({
url
,
method
:
'post'
,
data
})
}
http
.
put
=
function
(
url
,
data
)
{
return
service
({
url
,
method
:
'put'
,
data
})
}
http
.
delete
=
function
(
url
,
params
)
{
return
service
({
url
,
method
:
'delete'
,
params
})
}
export
{
http
}
export
default
service
\ No newline at end of file
src/api/finance/service.js
浏览文件 @
0204674d
// 引入 axios 请求
// src/api/finance/service.js
import
axios
from
'axios'
// 引入 element-plus 里面的消息提示
import
{
ElMessage
}
from
'element-plus'
import
{
getToken
,
setToken
,
removeToken
,
formatBearerAuthorization
}
from
'@/api/request.js'
import
{
getToken
,
setToken
,
removeToken
}
from
'@/api/request.js'
export
{
getToken
,
setToken
,
removeToken
}
// 定义全局控制器,以便在取消后重新赋值
let
currentAbortController
=
new
AbortController
()
/**
* 获取当前有效的 AbortSignal
* 供 axios 拦截器和 fetch 请求共同使用
*/
export
const
getAbortSignal
=
()
=>
{
return
currentAbortController
.
signal
}
/**
* 取消所有正在进行的请求
* 路由守卫中调用此方法
*/
export
const
cancelAllRequests
=
()
=>
{
// 1. 终止当前控制器的所有请求
currentAbortController
.
abort
()
// 2. 创建一个新的控制器,供后续新请求使用
currentAbortController
=
new
AbortController
()
}
// 创建 axios 实例
const
service
=
axios
.
create
({
timeout
:
30
0
*
1000
// 请求超时时间
timeout
:
30
*
1000
// 请求超时时间 30s
})
// request 拦截器
:与主 request 一致,就地改 config,避免 mergeConfig 破坏 url
// request 拦截器
service
.
interceptors
.
request
.
use
(
config
=>
{
const
raw
=
getToken
()
const
token
=
raw
?
String
(
raw
).
trim
()
:
""
// 处理 Headers
if
(
!
config
.
headers
)
{
config
.
headers
=
new
axios
.
AxiosHeaders
()
}
else
if
(
!
(
config
.
headers
instanceof
axios
.
AxiosHeaders
))
{
config
.
headers
=
axios
.
AxiosHeaders
.
from
(
config
.
headers
)
}
// 设置 Token
if
(
token
)
{
config
.
headers
.
set
(
'token'
,
token
,
true
)
}
else
{
config
.
headers
.
delete
(
'token'
)
config
.
headers
.
delete
(
'Token'
)
// ===== 旧逻辑保留(勿删):Authorization: Bearer <token> =====
// config.headers.delete('Authorization')
// config.headers.delete('authorization')
}
// 处理 AI 分析接口的特殊 Header
const
reqUrl
=
String
(
config
.
url
??
''
)
if
(
reqUrl
.
includes
(
'aiAnalysis'
))
{
const
aiApiKey
=
import
.
meta
.
env
.
VITE_AI_ANALYSIS_API_KEY
if
(
aiApiKey
)
{
// 确保 headers 存在
if
(
!
config
.
headers
)
{
config
.
headers
=
new
axios
.
AxiosHeaders
()
}
else
if
(
!
(
config
.
headers
instanceof
axios
.
AxiosHeaders
))
{
...
...
@@ -42,6 +67,13 @@ service.interceptors.request.use(config => {
config
.
headers
.
set
(
'X-API-Key'
,
aiApiKey
)
}
}
// 将全局控制器的 signal 注入到 axios 请求中
// 如果用户手动传入了 signal,则优先使用用户的(虽然少见)
if
(
!
config
.
signal
)
{
config
.
signal
=
getAbortSignal
()
}
return
config
},
error
=>
{
console
.
log
(
error
)
...
...
@@ -55,7 +87,6 @@ service.interceptors.response.use(
if
(
!
res
)
{
return
Promise
.
reject
(
new
Error
(
'响应数据为空'
))
}
// 根据需求:接口返回 code 不等于 200 的时候报错
if
(
res
.
code
!==
200
)
{
ElMessage
({
message
:
res
.
message
||
'请求失败'
,
...
...
@@ -67,19 +98,25 @@ service.interceptors.response.use(
return
res
.
data
},
error
=>
{
console
.
log
(
'err'
+
error
)
// 精准识别取消错误,避免弹窗骚扰用户
const
isCanceledError
=
axios
.
isCancel
(
error
)
||
error
?.
code
===
'ERR_CANCELED'
||
error
?.
name
===
'CanceledError'
||
error
?.
name
===
'AbortError'
||
(
typeof
error
?.
message
===
'string'
&&
/canceled/i
.
test
(
error
.
message
))
if
(
isCanceledError
)
return
Promise
.
reject
(
error
)
if
(
isCanceledError
)
{
// 静默处理取消错误,不弹窗,不打印.error
return
Promise
.
reject
(
error
)
}
console
.
log
(
'err'
+
error
)
// 处理
token 过期或无效的情况
// 处理
Token 过期
const
errUrl
=
String
(
error
.
config
?.
url
||
''
)
const
isAiAnalysisRequest
=
errUrl
.
includes
(
'aiAnalysis'
)
if
(
error
.
response
&&
(
error
.
response
.
status
===
401
||
error
.
response
.
status
===
403
)
&&
...
...
@@ -94,14 +131,11 @@ service.interceptors.response.use(
const
hadToken
=
h
&&
(
typeof
h
.
get
===
'function'
?
Boolean
(
h
.
get
(
'token'
)
||
h
.
get
(
'Token'
)
)
:
Boolean
(
h
.
token
||
h
.
Token
))
?
Boolean
(
h
.
get
(
'token'
)
||
h
.
get
(
'Token'
))
:
Boolean
(
h
.
token
||
h
.
Token
))
if
(
hadToken
)
removeToken
()
}
else
{
// 只有非取消、非 Token 过期的错误才弹出通用提示
ElMessage
({
message
:
typeof
error
?.
message
===
'string'
?
error
.
message
:
'请求失败'
,
type
:
'error'
,
...
...
@@ -112,12 +146,11 @@ service.interceptors.response.use(
}
)
// 封装通用请求函数
(支持 http(config) 和 http.get/post 等调用方式)
// 封装通用请求函数
function
http
(
config
)
{
return
service
(
config
)
}
// 为 http 函数添加快捷方法
http
.
get
=
function
(
url
,
params
)
{
return
service
({
url
,
method
:
'get'
,
params
})
}
...
...
src/api/zmOverview/risk/index.js
浏览文件 @
0204674d
...
...
@@ -17,6 +17,14 @@ export function getLatestRisks() {
});
}
// 中美博弈概览V2:首页最新风险动态(10条 + 各类数量/总数)
export
function
getLatestRisk
()
{
return
request
({
method
:
"GET"
,
url
:
`/api/rivalryIndexV2/LatestRisk`
});
}
// 中美博弈概览V2:美对华制裁措施数量趋势
export
function
geDomainContainmentTrend
(
params
)
{
return
request
({
...
...
src/components/base/RiskSignalOverviewDetailDialog/risk-signal-overview-detail-dialog.scss
浏览文件 @
0204674d
...
...
@@ -132,6 +132,28 @@
position
:
relative
;
}
.risk-signal-detail-dialog
.el-dialog__headerbtn
{
top
:
11px
!
important
;
right
:
16px
!
important
;
width
:
32px
!
important
;
height
:
32px
!
important
;
display
:
inline-flex
;
align-items
:
center
;
justify-content
:
center
;
}
.risk-signal-detail-dialog
.el-dialog__headerbtn
.el-dialog__close
{
width
:
16px
;
height
:
16px
;
color
:
rgb
(
59
,
65
,
75
)
!
important
;
}
.risk-signal-detail-dialog
.el-dialog__headerbtn
.el-dialog__close
svg
,
.risk-signal-detail-dialog
.el-dialog__headerbtn
.el-dialog__close
svg
path
{
fill
:
rgb
(
59
,
65
,
75
)
!
important
;
stroke
:
rgb
(
59
,
65
,
75
)
!
important
;
}
.
risk-signal-detail-dialog
.
el-dialog__header
:
:
after
{
content
:
""
;
position
:
absolute
;
...
...
@@ -234,7 +256,7 @@
.risk-signal-detail-dialog
.risk-signal-detail-dialog__read-indicator
{
position
:
absolute
;
right
:
115
px
;
right
:
61
px
;
top
:
50%
;
transform
:
translateY
(
-50%
);
display
:
inline-flex
;
...
...
src/components/base/SummaryCardsPanel/index.vue
浏览文件 @
0204674d
...
...
@@ -25,7 +25,7 @@
<el-icon
color=
"var(--color-primary-100)"
>
<ArrowRightBold
/>
</el-icon>
<div
class=
"item-dot"
v-if=
"item.delta"
>
+
{{ item.delta }}
</div>
<div
class=
"item-dot"
v-if=
"item.delta"
>
{{ dotPrefix }}
{{ item.delta }}
</div>
</div>
<div
v-if=
"shouldShowMoreCard"
class=
"summary-item"
@
click=
"emit('more-click')"
>
...
...
@@ -100,6 +100,10 @@ const props = defineProps({
loading
:
{
type
:
Boolean
,
default
:
false
},
dotPrefix
:
{
type
:
String
,
default
:
"+"
}
});
...
...
src/components/base/moduleHeader/index.vue
浏览文件 @
0204674d
<
template
>
<div
class=
"module-header-wrapper"
>
<div
class=
"module-header-wrapper"
@
mouseleave=
"handleHideUserPanel"
>
<div
class=
"nav-content"
:class=
"
{ 'nav-content-library': isShowDataLibrary }">
<div
class=
"nav-left"
:class=
"
{ 'flex-start': isShowSearchBar }">
<div
class=
"icon"
>
...
...
@@ -24,36 +24,36 @@
<div
class=
"mail"
@
click=
"handleClickToolBox"
>
<img
src=
"@/assets/icons/overview/mail.png"
alt=
""
/>
</div>
<div
class=
"user-trigger"
>
<div
class=
"user"
@
click
.
stop
=
"handleToggleUserPanel"
>
<div
class=
"user-trigger"
@
mouseenter=
"handleShowUserPanel"
>
<div
class=
"user"
@
click
.
stop
>
<img
src=
"@/assets/icons/overview/user.png"
alt=
""
/>
</div>
</div
>
<div
v-if=
"isShowUserPanel"
class=
"user-panel"
>
<div
class=
"user-panel-row"
>
<div
class=
"blue-solid"
></div
>
<span
class=
"user-panel-value user-panel-value--nickname"
>
{{
userNickname
}}
</span
>
<div
class=
"role-box"
>
<
span
class=
"user-panel-value user-panel-value--role"
>
{{
roleName
}}
</span
>
<div
v-if=
"isShowUserPanel"
class=
"user-panel"
>
<div
class=
"user-panel-row"
>
<div
class=
"blue-solid"
></div
>
<span
class=
"user-panel-value user-panel-value--nickname"
>
{{
userNickname
}}
</span
>
<div
class=
"role-box"
>
<span
class=
"user-panel-value user-panel-value--role"
>
{{
roleName
}}
</span
>
<
/div
>
</div>
</div>
<div
class=
"user-panel-row user-panel-row--single"
>
<span
class=
"user-panel-value user-panel-value--organ"
>
{{
organName
}}
</span>
</div>
<div
class=
"solid"
></div>
<div
class=
"user-panel-row user-panel-row--single"
>
<span
class=
"user-panel-value user-panel-value--organ"
>
{{
organName
}}
</span>
</div>
<div
class=
"solid"
></div>
<div
class=
"user-panel-logout"
@
click
.
stop=
"handleUserCommand('logout')"
><img
src=
"./back.png"
class=
"back-image"
/>
{{
"退出登录"
}}
<div
class=
"user-panel-logout"
@
click
.
stop=
"handleUserCommand('logout')"
><img
src=
"./back.png"
class=
"back-image"
/>
{{
"退出登录"
}}
</div>
</div>
</div>
</div>
</div>
<div
class=
"menu-box"
v-
show
=
"isShowMenu"
@
mouseenter=
"handleHoverMenu(true)"
<div
class=
"menu-box"
v-
if
=
"isShowMenu"
@
mouseenter=
"handleHoverMenu(true)"
@
mouseleave=
"handleHoverMenu(false)"
>
<div
class=
"menu-content"
>
<div
class=
"menu-item"
v-for=
"(item, index) in menuList"
:key=
"index"
@
click=
"handleToModule(item, 1)"
>
...
...
@@ -64,9 +64,9 @@
</div>
</div>
</div>
<div
class=
"tool-box"
v-
show
=
"isShowTool"
@
mouseenter=
"handleHoverTool(true)"
<div
class=
"tool-box"
v-
if
=
"isShowTool"
@
mouseenter=
"handleHoverTool(true)"
@
mouseleave=
"handleHoverTool(false)"
>
<div
class=
"
menu
-content"
>
<div
class=
"
tool
-content"
>
<div
class=
"menu-item"
v-for=
"(item, index) in toolList"
:key=
"index"
@
click=
"handleToModule(item, 2)"
>
<div
class=
"icon"
>
<img
:src=
"item.icon"
alt=
""
/>
...
...
@@ -404,8 +404,8 @@ const handleClickToolBox = () => {
ElMessage
.
warning
(
"当前功能正在开发中,敬请期待!"
);
};
const
handle
Toggle
UserPanel
=
()
=>
{
isShowUserPanel
.
value
=
!
isShowUserPanel
.
val
ue
;
const
handle
Show
UserPanel
=
()
=>
{
isShowUserPanel
.
value
=
tr
ue
;
};
const
handleHideUserPanel
=
()
=>
{
...
...
@@ -662,10 +662,13 @@ onMounted(() => {
top
:
calc
(
32px
+
21px
);
width
:
240px
;
height
:
141px
;
// 与“中美科技博弈”下方菜单框(.menu-box)保持一致的透明/模糊效果
background
:
rgba
(
255
,
255
,
255
,
0
.8
);
border
:
1px
solid
rgba
(
255
,
255
,
255
,
1
);
border-radius
:
10px
;
backdrop-filter
:
blur
(
30px
);
-webkit-backdrop-filter
:
blur
(
30px
);
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
display
:
flex
;
flex-direction
:
column
;
...
...
@@ -785,6 +788,13 @@ onMounted(() => {
display
:
flex
;
align-items
:
center
;
margin-left
:
8px
;
transition
:
color
0
.15s
ease
,
font-size
0
.15s
ease
,
font-weight
0
.15s
ease
;
&
:hover
{
color
:
var
(
--
color-main-active
);
font-size
:
18px
;
font-weight
:
700
;
}
.back-image
{
width
:
16px
;
...
...
@@ -805,23 +815,6 @@ onMounted(() => {
}
.menu-box
{
// position: absolute;
// z-index: 999999999;
// width: 713px;
// height: 413px;
// top: 52px;
// left: 0;
// box-sizing: border-box;
// border-radius: 10px;
// backdrop-filter: blur(10px);
// -webkit-backdrop-filter: blur(10px);
// box-shadow: 0px 8px 32px 0px rgba(31, 38, 135, 0.15);
// background: rgba(255, 255, 255, 0.25);
// backdrop-filter: blur(10px);
// -webkit-backdrop-filter: blur(10px);
// border: 1px solid rgba(255, 255, 255, 0.3);
// background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.2) 100%);
// box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.2);
position
:
absolute
;
z-index
:
999999
;
width
:
713px
;
...
...
@@ -902,21 +895,17 @@ onMounted(() => {
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
background
:
rgba
(
255
,
255
,
255
,
0
.8
);
.
menu
-content
{
width
:
562
px
;
height
:
348
px
;
.
tool
-content
{
width
:
130
px
;
height
:
120
px
;
margin-top
:
8px
;
margin-left
:
72px
;
.menu-item
{
margin-top
:
36px
;
width
:
280px
;
width
:
100%
;
height
:
24px
;
display
:
flex
;
cursor
:
pointer
;
&
:hover
{
.title
{
color
:
var
(
--
color-main-active
);
...
...
src/components/base/riskSignal/index.vue
浏览文件 @
0204674d
...
...
@@ -12,14 +12,14 @@
<div
class=
"box2-main"
>
<div
class=
"box2-main-item"
v-for=
"(item, index) in showRiskSignalList"
:key=
"index"
@
click=
"handleItemClick(item, index)"
>
<div
:class=
"
{
<div
v-if=
"!isRiskLevelNoData(item?.[props.riskLevel])"
:class=
"
{
itemLeftStatus1: item[props.riskLevel] === '特别重大',
itemLeftStatus2: item[props.riskLevel] === '重大风险',
itemLeftStatus3: item[props.riskLevel] === '较大风险',
itemLeftStatus4: item[props.riskLevel] === '一般风险'
|| !item[props.riskLevel]
,
itemLeftStatus4: item[props.riskLevel] === '一般风险',
itemLeftStatus5: item[props.riskLevel] === '低风险',
}">
{{
item
[
props
.
riskLevel
]
||
"暂无数据"
}}
{{
item
[
props
.
riskLevel
]
}}
</div>
<div
class=
"item-right"
>
<div
class=
"text"
>
<span
class=
"text-inner"
>
{{
item
[
props
.
name
]
}}
</span></div>
...
...
@@ -76,6 +76,11 @@ const props = defineProps({
});
const
isRiskLevelNoData
=
(
level
)
=>
{
const
t
=
String
(
level
??
""
).
trim
();
return
!
t
||
t
===
"暂无数据"
||
t
===
"暂无数值"
;
};
const
showRiskSignalList
=
computed
(()
=>
{
return
props
.
list
.
slice
(
0
,
6
)
})
...
...
src/router/index.js
浏览文件 @
0204674d
...
...
@@ -2,6 +2,8 @@ import { createRouter, createWebHistory } from "vue-router";
import
{
setToken
,
removeToken
,
getToken
}
from
"@/api/request.js"
;
import
{
AUTH_LOGOUT_CHANNEL
}
from
"@/utils/authCrossTabLogout.js"
;
import
{
cancelAllRequests
}
from
"@/api/finance/service.js"
/** localStorage:跨标签页记录当前前端的 bootId(与 vite define 的 __APP_BOOT_ID__ 对齐) */
const
VITE_BOOT_STORAGE_KEY
=
"app_vite_boot_id"
;
/** 退出后强制回登录页(跨标签页/刷新生效) */
...
...
@@ -145,51 +147,9 @@ const router = createRouter({
// 2)登录成功回跳带 ?token=:先 setToken 并同步 bootId,再去掉 URL 中的 token(须先于 clearTokenIfNewDevBoot,避免误清刚写入的登录态)
// 3)已有本地 token:正常走前端路由
router
.
beforeEach
((
to
,
from
,
next
)
=>
{
// ===== SSO/重定向逻辑(切线上接口时停用,保留注释) =====
// const queryToken = to.query && to.query.token != null && String(to.query.token).trim() !== ""
// ? String(to.query.token).trim()
// : "";
//
// if (queryToken) {
// setToken(queryToken);
// // 成功回跳拿到 token,说明统一登录链路已完成,清除强制标记
// try {
// if (typeof window !== "undefined") {
// window.sessionStorage.removeItem(FORCE_SSO_LOGIN_KEY);
// }
// } catch {
// // ignore
// }
// persistViteBootIdOnly();
// const restQuery = { ...to.query };
// delete restQuery.token;
// const isGatewayCallback =
// to.path === "/callback" || to.path.replace(/\/$/, "") === "/callback";
// const targetPath = isGatewayCallback ? SSO_POST_LOGIN_PATH : to.path;
// next({
// path: targetPath,
// query: restQuery,
// hash: to.hash,
// replace: true,
// });
// return;
// }
//
// // 若用户点了“退出登录”,即使本地还有残留 token/或别处写回,也强制先走统一登录链路
// try {
// if (typeof window !== "undefined" && window.sessionStorage.getItem(FORCE_SSO_LOGIN_KEY) === "1") {
// removeToken();
// const targetUrl = `${SSO_GATEWAY_ORIGIN}/api/v2${to.fullPath || "/"}`;
// window.location.replace(targetUrl);
// next(false);
// return;
// }
// } catch {
// // ignore
// }
// 外网/线上版本:不因重启清登录态;仅开发环境需要此逻辑
// clearTokenIfNewDevBoot();
// 【新增】在每次路由跳转开始前,取消上一个页面所有未完成的请求
// 这能防止旧页面的数据回来覆盖新页面,也能减少服务器压力
cancelAllRequests
();
if
(
import
.
meta
.
env
.
DEV
)
{
clearTokenIfNewDevBoot
();
}
...
...
src/router/modules/bill.js
浏览文件 @
0204674d
...
...
@@ -35,7 +35,7 @@ const billRoutes = [
component
:
BillAllCommittee
,
meta
:
{
title
:
"法案委员会列表"
,
isShowHeader
:
tru
e
isShowHeader
:
fals
e
}
},
{
...
...
src/utils/goToPage.js
0 → 100644
浏览文件 @
0204674d
import
{
useRouter
}
from
"vue-router"
;
const
router
=
useRouter
()
// 跳转法案详情
export
const
goToBill
=
(
id
,
tabName
)
=>
{
window
.
sessionStorage
.
setItem
(
"billId"
,
id
);
window
.
sessionStorage
.
setItem
(
"curTabName"
,
tabName
);
const
route
=
router
.
resolve
({
path
:
"/billLayout"
,
query
:
{
billId
:
id
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
// 跳转政令详情
export
const
goToDecree
=
(
id
,
tabName
)
=>
{
window
.
sessionStorage
.
setItem
(
"decreeId"
,
id
);
window
.
sessionStorage
.
setItem
(
"curTabName"
,
tabName
);
const
route
=
router
.
resolve
({
path
:
"/decreeLayout"
,
query
:
{
id
:
id
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
// 跳转智库
export
const
goToThinkTank
=
(
id
,
tabName
)
=>
{
window
.
sessionStorage
.
setItem
(
"curTabName"
,
tabName
);
const
route
=
router
.
resolve
({
name
:
"ReportDetail"
,
params
:
{
id
:
id
}
});
window
.
open
(
route
.
href
,
"_blank"
);
}
// 跳转机构详情
export
const
goToInstitution
=
(
id
,
tabName
)
=>
{
window
.
sessionStorage
.
setItem
(
'curTabName'
,
tabName
)
const
curRoute
=
router
.
resolve
({
path
:
"/institution"
,
query
:
{
id
:
id
}
});
window
.
open
(
curRoute
.
href
,
"_blank"
);
}
\ No newline at end of file
src/utils/riskSignalOverviewDetailHelpers.js
浏览文件 @
0204674d
...
...
@@ -223,14 +223,14 @@ export function getRiskDetailLevelModifier(level) {
if
(
t
===
"低风险"
)
{
return
"lv5"
;
}
if
(
t
===
"一般风险"
||
!
t
||
t
===
"暂无数据"
)
{
if
(
t
===
"一般风险"
||
!
t
||
t
===
"暂无数据"
||
t
===
"风险信号暂无评估"
)
{
return
"lv4"
;
}
return
"lv4"
;
}
/**
与 `@/components/base/riskSignal` 左侧等级一致:空 / null 等展示「暂无数据
」 */
export
const
RISK_SIGNAL_LIST_LEVEL_EMPTY_TEXT
=
"
暂无数据
"
;
/**
详情弹窗标题区等级文案:空 / null 等展示「风险信号暂无评估
」 */
export
const
RISK_SIGNAL_LIST_LEVEL_EMPTY_TEXT
=
"
风险信号暂无评估
"
;
/**
* 列表行风险等级 → 弹窗标题区文案(null、空串与「暂无数值」等与列表「暂无数据」对齐)
...
...
@@ -241,7 +241,7 @@ export function normalizeRiskSignalListLevelText(raw) {
return
RISK_SIGNAL_LIST_LEVEL_EMPTY_TEXT
;
}
const
s
=
String
(
raw
).
trim
();
if
(
s
===
""
||
s
===
"null"
||
s
===
"undefined"
||
s
===
"暂无数值"
)
{
if
(
s
===
""
||
s
===
"null"
||
s
===
"undefined"
||
s
===
"暂无数值"
||
s
===
"暂无数据"
)
{
return
RISK_SIGNAL_LIST_LEVEL_EMPTY_TEXT
;
}
return
s
;
...
...
src/views/ZMOverView/components/newRisk/index.vue
浏览文件 @
0204674d
...
...
@@ -43,15 +43,10 @@
<div
style=
"display: flex"
>
<!-- 风险信号列表 -->
<div
class=
"risk-signals"
ref=
"riskSignalsRef"
>
<div
class=
"risk-signals-item"
v-for=
"(item, index) in warningList"
<div
class=
"risk-signals-item"
v-for=
"(item, index) in warningList"
:key=
"item.signalId != null ? String(item.signalId) : 'risk-' + index"
@
mouseenter=
"onMouseEnter(item, index)"
@
mouseleave=
"onMouseLeave"
@
click
.
stop
:class=
"['risk-signals-item',
{ 'risk-signals-item-hightLight': riskSignalActiveIndex === index }]"
>
@
mouseenter=
"onMouseEnter(item, index)"
@
mouseleave=
"onMouseLeave"
@
click
.
stop
:class=
"['risk-signals-item',
{ 'risk-signals-item-hightLight': riskSignalActiveIndex === index }]">
<div
class=
"item-left"
:class=
"
{
'item-status-1': item.signalLevel === '特别重大',
'item-status-2': item.signalLevel === '重大风险',
...
...
@@ -132,7 +127,8 @@
import
{
color
}
from
"echarts"
;
import
{
onMounted
,
ref
,
onUnmounted
,
computed
}
from
"vue"
;
import
WaveBall
from
"./WaveBall.vue"
;
import
{
getLatestRiskUpdates
,
getLatestRisks
}
from
"@/api/zmOverview/risk/index.js"
;
import
{
getLatestRisk
}
from
"@/api/zmOverview/risk/index.js"
;
import
{
getRiskSignalInfoById
}
from
"@/api/riskSignal/index.js"
;
import
router
from
"@/router/index"
;
import
{
navigateToViewRiskSignal
}
from
"@/utils/riskSignalOverviewNavigate"
;
import
icon1
from
"./icon/title-1.svg"
;
...
...
@@ -315,12 +311,14 @@ const cardShowIndex4 = ref(0);
// 最新风险动态统计
const
handleGetLatestRiskUpdates
=
async
()
=>
{
try
{
const
params
=
{
currentDate
:
"本周"
};
const
res
=
await
getLatestRiskUpdates
(
params
);
console
.
log
(
"最新风险动态统计1"
,
res
);
const
res
=
await
getLatestRisk
();
console
.
log
(
"最新风险动态"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
d
=
res
.
data
;
const
formatChange
=
(
n
)
=>
{
const
v
=
Number
(
n
)
||
0
;
return
v
===
0
?
"无新增"
:
String
(
v
);
};
sections
.
value
=
[
{
// title: res.data.policiesRegulations.hotspotTitle,
...
...
@@ -328,16 +326,16 @@ const handleGetLatestRiskUpdates = async () => {
waveBall
:
[
{
percent
:
30
,
// 估算的百分比
count
:
res
.
data
.
bill
.
total
,
change
:
res
.
data
.
bill
.
dailyIncrement
,
count
:
d
.
billRiskTotal
??
0
,
change
:
formatChange
(
d
.
billRiskNum
)
,
unit
:
"项"
,
title
:
"法案(提出)"
,
type
:
"法案"
},
{
percent
:
20
,
// 估算的百分比
count
:
res
.
data
.
administrativeOrder
.
total
,
change
:
res
.
data
.
administrativeOrder
.
dailyIncrement
,
count
:
d
.
orderRiskTotal
??
0
,
change
:
formatChange
(
d
.
orderRiskNum
)
,
unit
:
"个"
,
title
:
"政令"
,
type
:
"行政令"
...
...
@@ -350,8 +348,8 @@ const handleGetLatestRiskUpdates = async () => {
waveBall
:
[
{
percent
:
10
,
// 估算的百分比
count
:
res
.
data
.
Entities
.
total
,
change
:
res
.
data
.
Entities
.
dailyIncrement
,
count
:
d
.
entityRiskTotal
??
0
,
change
:
formatChange
(
d
.
entityRiskNum
)
,
unit
:
"次"
,
title
:
"实体清单"
,
...
...
@@ -359,8 +357,8 @@ const handleGetLatestRiskUpdates = async () => {
},
{
percent
:
20
,
// 估算的百分比
count
:
res
.
data
.
CCL
.
total
,
change
:
res
.
data
.
CCL
.
dailyIncrement
,
count
:
d
.
cclRiskTotal
??
0
,
change
:
formatChange
(
d
.
cclRiskNum
)
,
unit
:
"次"
,
title
:
"CCL"
,
type
:
"CCL"
...
...
@@ -373,16 +371,16 @@ const handleGetLatestRiskUpdates = async () => {
waveBall
:
[
{
percent
:
15
,
// 估算的百分比
count
:
res
.
data
.
SDN
.
total
,
change
:
res
.
data
.
SDN
.
dailyIncrement
,
count
:
d
.
sdnRiskTotal
??
0
,
change
:
formatChange
(
d
.
sdnRiskNum
)
,
unit
:
"次"
,
title
:
"SDN"
,
type
:
"SDN"
},
{
percent
:
5
,
// 估算的百分比
count
:
res
.
data
.
militaryInvolvement
.
total
,
change
:
res
.
data
.
militaryInvolvement
.
dailyIncrement
,
count
:
d
.
armyRiskTotal
??
0
,
change
:
formatChange
(
d
.
armyRiskNum
)
,
unit
:
"家"
,
title
:
"涉军企业"
,
type
:
"涉军企业"
...
...
@@ -395,24 +393,24 @@ const handleGetLatestRiskUpdates = async () => {
waveBall
:
[
{
percent
:
3
,
// 估算的百分比
count
:
res
.
data
[
"337Survey"
].
total
,
change
:
res
.
data
[
"337Survey"
].
dailyIncrement
,
count
:
d
.
m337RiskTotal
??
0
,
change
:
formatChange
(
d
.
m337RiskNum
)
,
unit
:
"次"
,
title
:
"337调查"
,
type
:
"337调查"
},
{
percent
:
3
,
// 估算的百分比
count
:
res
.
data
[
"232Survey"
].
total
,
change
:
res
.
data
[
"232Survey"
].
dailyIncrement
,
count
:
d
.
m232RiskTotal
??
0
,
change
:
formatChange
(
d
.
m232RiskNum
)
,
unit
:
"次"
,
title
:
"232调查"
,
type
:
"232调查"
},
{
percent
:
3
,
// 估算的百分比
count
:
res
.
data
[
"301Survey"
].
total
,
change
:
res
.
data
[
"301Survey"
].
dailyIncrement
,
count
:
d
.
m301RiskTotal
??
0
,
change
:
formatChange
(
d
.
m301RiskNum
)
,
unit
:
"次"
,
title
:
"301调查"
,
type
:
"301调查"
...
...
@@ -454,12 +452,60 @@ const hotNewsList = ref([
//最新风险信号
const
handleGetLatestRisks
=
async
()
=>
{
try
{
const
res
=
await
getLatestRisk
s
();
console
.
log
(
"最新风险
信号
"
,
res
);
const
res
=
await
getLatestRisk
();
console
.
log
(
"最新风险
动态(列表)
"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
warningList
.
value
=
res
.
data
.
riskVOS
;
hotNewsList
.
value
=
res
.
data
.
hotspotVOS
;
riskTotal
.
value
=
res
.
data
.
riskCount
;
const
d
=
res
.
data
;
const
list
=
Array
.
isArray
(
d
.
riskSignals
)
?
d
.
riskSignals
:
[];
const
getEventTypeFromModule
=
(
code
)
=>
{
const
c
=
String
(
code
??
""
).
trim
();
if
(
c
===
"0100"
)
return
"法案"
;
if
(
c
===
"0101"
)
return
"行政令"
;
if
(
c
===
"0102"
)
return
"智库报告"
;
if
(
c
===
"0103"
)
return
"出口管制"
;
if
(
c
===
"0104"
)
return
"市场准入"
;
if
(
c
===
"0105"
)
return
"创新主体"
;
if
(
c
===
"0106"
)
return
"合作限制"
;
if
(
c
===
"0107"
)
return
"科研资助体系"
;
if
(
c
===
"0108"
)
return
"规则限制"
;
if
(
c
===
"0109"
)
return
"投融资限制"
;
if
(
c
===
"01031"
)
return
"实体清单"
;
if
(
c
===
"01032"
)
return
"CCL"
;
if
(
c
===
"01091"
)
return
"SDN"
;
if
(
c
===
"01092"
)
return
"涉军企业"
;
if
(
c
===
"01041"
)
return
"337调查"
;
if
(
c
===
"01042"
)
return
"232调查"
;
if
(
c
===
"01043"
)
return
"301调查"
;
return
c
;
};
warningList
.
value
=
list
.
map
((
x
)
=>
({
signalId
:
x
.
id
,
signalTitle
:
x
.
title
,
signalTime
:
x
.
eventTime
,
signalLevel
:
x
.
riskLevel
,
signalCountryId
:
x
.
riskCountryId
,
dealStatus
:
x
.
dealStatus
,
eventType
:
getEventTypeFromModule
(
x
.
sanModuleCode
)
}));
riskTotal
.
value
=
warningList
.
value
.
length
;
// 右侧轮播:同样使用 LatestRisk 的 riskSignals(字段映射到现有模板使用的热点字段名)
hotNewsList
.
value
=
list
.
map
((
x
)
=>
({
signalId
:
x
.
id
,
hotspotID
:
x
.
id
,
hotspotType
:
getEventTypeFromModule
(
x
.
sanModuleCode
),
hotspotTitle
:
x
.
title
,
// 轮播题目右侧标签:切换轮播时用详情接口 domains 覆盖
hotspotTag
:
""
,
hotspotDesc
:
x
.
description
||
""
,
hotspotDate
:
x
.
eventTime
||
""
,
domainList
:
[],
eventTitle
:
x
.
issuingOrgId
||
""
}));
// 首次加载:主动拉取当前轮播项详情以展示题目右侧标签
await
fetchCarouselDetailForIndex
(
curHotNewsListIndex
.
value
||
0
);
cardList1
.
value
=
warningList
.
value
.
filter
(
item
=>
{
return
item
.
eventType
===
"法案"
||
item
.
eventType
===
"行政令"
;
...
...
@@ -520,11 +566,46 @@ const handleGetLatestRisks = async () => {
const
curNews
=
ref
({});
const
carouselRef
=
ref
(
null
);
const
curHotNewsListIndex
=
ref
(
0
);
const
carouselDetailCache
=
ref
({});
const
applyHotspotTagById
=
(
id
,
tagText
)
=>
{
const
sid
=
String
(
id
??
""
).
trim
();
if
(
!
sid
)
return
;
hotNewsList
.
value
=
(
hotNewsList
.
value
||
[]).
map
((
n
)
=>
{
if
(
String
(
n
.
hotspotID
??
""
).
trim
()
!==
sid
)
return
n
;
return
{
...
n
,
hotspotTag
:
tagText
};
});
};
const
fetchCarouselDetailForIndex
=
async
(
index
)
=>
{
const
item
=
hotNewsList
.
value
?.[
index
];
if
(
!
item
)
return
;
const
id
=
String
(
item
.
hotspotID
??
""
).
trim
();
if
(
!
id
)
return
;
if
(
carouselDetailCache
.
value
[
id
])
{
applyHotspotTagById
(
id
,
carouselDetailCache
.
value
[
id
]);
return
;
}
try
{
const
res
=
await
getRiskSignalInfoById
(
id
);
if
(
res
&&
res
.
code
===
200
&&
res
.
data
)
{
const
tagText
=
String
(
res
.
data
.
domains
??
""
).
trim
();
if
(
tagText
)
{
carouselDetailCache
.
value
=
{
...
carouselDetailCache
.
value
,
[
id
]:
tagText
};
applyHotspotTagById
(
id
,
tagText
);
}
}
}
catch
(
error
)
{
console
.
error
(
"轮播风险信号详情获取失败"
,
error
);
}
};
const
handleCarouselChange
=
index
=>
{
curHotNewsListIndex
.
value
=
index
;
if
(
hotNewsList
.
value
&&
hotNewsList
.
value
.
length
>
0
)
{
curNews
.
value
=
hotNewsList
.
value
[
index
];
}
fetchCarouselDetailForIndex
(
index
);
};
// 查看详情
...
...
src/views/bill/allCommittee/index.vue
浏览文件 @
0204674d
...
...
@@ -14,6 +14,12 @@
placeholder=
"搜索委员会"
/>
</div>
<div
class=
"hard-select"
>
<el-select
v-model=
"committeeInfo.metricType"
@
change=
"onAllCommittee()"
placeholder=
"统计口径"
style=
"width: 160px; margin-left: 8px"
>
<el-option
label=
"政令数据总量"
:value=
"1"
/>
<el-option
label=
"政令新增数量"
:value=
"2"
/>
</el-select>
</div>
</div>
<div
class=
"date-box"
>
...
...
@@ -30,7 +36,7 @@
<div
class=
"item-name one-line-ellipsis"
>
{{
item
.
name
}}
</div>
<div
class=
"item-chamber one-line-ellipsis"
>
{{
item
.
chamber
}}
</div>
</div>
<div
class=
"item-total"
>
{{
item
.
count
}}
项
</div>
<div
class=
"item-total"
>
{{
getDisplayCount
(
item
)
}}
项
</div>
<el-icon
color=
"var(--color-primary-100)"
>
<ArrowRightBold
/>
</el-icon>
...
...
@@ -48,6 +54,12 @@
/>
</div>
</div>
<div
class=
"back-bnt"
@
click=
"handleBack"
>
<el-icon>
<Back
/>
</el-icon>
<div
class=
"back-text"
>
返回
</div>
</div>
</div>
</
template
>
...
...
@@ -55,6 +67,7 @@
import
{
onMounted
,
reactive
,
ref
}
from
"vue"
;
import
{
Search
}
from
"@element-plus/icons-vue"
;
import
{
ArrowRightBold
}
from
"@element-plus/icons-vue"
;
import
{
Back
}
from
"@element-plus/icons-vue"
;
import
router
from
"@/router"
;
import
TimeTabPane
from
"@/components/base/TimeTabPane/index.vue"
;
import
{
getStatisticsBillCountByCommittee
}
from
"@/api/bill/billHome"
;
...
...
@@ -66,6 +79,7 @@ const committeeInfo = reactive({
pageSize
:
8
,
total
:
0
,
keyWord
:
""
,
metricType
:
1
,
dateDesc
:
"近一年"
,
list
:
[]
});
...
...
@@ -89,10 +103,11 @@ const onAllCommittee = async num => {
id
:
`
${
item
.
orgType
||
""
}
-
${
item
.
orgName
||
""
}
`
,
name
:
item
.
orgName
,
chamber
:
getChamberLabel
(
item
.
orgType
),
count
:
Number
(
item
.
count
||
0
)
totalCount
:
Number
(
item
.
count
||
0
),
recentCount
:
Number
(
item
.
countRecent
||
item
.
totalRecent
||
item
.
recentCount
||
item
.
recent
||
item
.
newCount
||
0
)
}))
.
filter
(
item
=>
!
committeeInfo
.
keyWord
||
item
.
name
?.
includes
(
committeeInfo
.
keyWord
))
.
sort
((
a
,
b
)
=>
(
b
.
count
||
0
)
-
(
a
.
count
||
0
));
.
sort
((
a
,
b
)
=>
getSortValue
(
b
)
-
getSortValue
(
a
));
committeeInfo
.
total
=
source
.
length
;
const
start
=
(
committeeInfo
.
pageNum
-
1
)
*
committeeInfo
.
pageSize
;
...
...
@@ -108,20 +123,36 @@ const onAllCommittee = async num => {
committeeInfo
.
loading
=
false
;
};
const
getSortValue
=
item
=>
{
if
(
committeeInfo
.
metricType
===
2
)
return
Number
(
item
?.
recentCount
||
0
);
return
Number
(
item
?.
totalCount
||
0
);
};
const
getDisplayCount
=
item
=>
{
return
getSortValue
(
item
);
};
const
handleDateChange
=
event
=>
{
committeeInfo
.
dateDesc
=
event
?.
time
||
"近一年"
;
onAllCommittee
();
};
const
handleToDataLibrary
=
item
=>
{
const
route
=
router
.
resolve
({
router
.
push
({
path
:
"/dataLibrary/countryBill"
,
query
:
{
selectedOrg
:
item
.
name
,
selectedCongress
:
item
.
chamber
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
const
handleBack
=
()
=>
{
if
(
window
.
history
.
length
>
1
)
{
router
.
back
();
return
;
}
router
.
push
(
"/billHome"
);
};
const
refCommittee
=
ref
();
...
...
@@ -143,6 +174,28 @@ onMounted(() => {
background-size
:
100%
100%
;
display
:
flex
;
justify-content
:
center
;
position
:
relative
;
.back-bnt
{
position
:
absolute
;
top
:
16px
;
left
:
30px
;
width
:
86px
;
height
:
38px
;
background-color
:
white
;
border-radius
:
19px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
color
:
var
(
--
text-primary-65-color
);
font-family
:
Source
Han
Sans
CN
;
font-size
:
16px
;
cursor
:
pointer
;
}
.back-text
{
margin-left
:
6px
;
}
.container-box
{
width
:
1600px
;
...
...
@@ -180,6 +233,11 @@ onMounted(() => {
width
:
180px
;
height
:
32px
;
}
.hard-select
{
height
:
42px
;
padding
:
5px
0
;
}
}
.date-box
{
...
...
src/views/bill/billHome/assets/images/box8-header-icon.png
0 → 100644
浏览文件 @
0204674d
1.2 KB
src/views/bill/billHome/index.vue
浏览文件 @
0204674d
...
...
@@ -56,7 +56,31 @@
<AreaTag
v-for=
"(item, index) in bill.hylyList"
:key=
"index"
:tagName=
"item.industryName"
>
</AreaTag>
</div>
<div
class=
"box1-main-divider"
></div>
<div
class=
"box1-main-left-info1"
>
<div
class=
"info1-box"
>
<div
class=
"icon"
></div>
<div
class=
"info1-box-left"
>
{{ "提出部门:" }}
</div>
<div
class=
"info1-box-right info1-box-right--committee"
>
<
template
v-if=
"getLimitedCommitteeList(bill.committeeList).length"
>
<div
v-for=
"committee in getLimitedCommitteeList(bill.committeeList)"
:key=
"committee.committeeId || committee.committeeName"
class=
"committee-item"
>
<img
class=
"committee-logo"
:src=
"committee.logoUrl || iconCommit"
:alt=
"committee.committeeName || '提案部门'"
/>
<div
class=
"committee-name"
>
{{
committee
.
committeeName
||
"--"
}}
</div>
</div>
</
template
>
<div
v-else
>
--
</div>
</div>
</div>
<div
class=
"info1-box"
>
<div
class=
"icon"
></div>
<div
class=
"info1-box-left"
>
{{ "提案人:" }}
</div>
...
...
@@ -70,9 +94,11 @@
</div>
</div>
</div>
<div
class=
"box1-main-divider box1-main-divider--before-list"
></div>
<div
class=
"box1-main-left-info2"
>
<div
class=
"info2-item"
v-for=
"(item, index) in bill.dyqkList"
:key=
"index"
>
<div
class=
"time-line"
v-if=
"index !== bill.dyqkList.length - 1"
></div>
<div
class=
"info2-item"
v-for=
"(item, index) in getLimitedDyqkList(bill.dyqkList)"
:key=
"index"
>
<div
class=
"time-line"
v-if=
"!isLastDyqkItem(bill.dyqkList, index)"
></div>
<div
class=
"item-icon"
>
<img
src=
"./assets/images/info2-icon.png"
alt=
""
/>
</div>
...
...
@@ -147,7 +173,7 @@
</div>
</div>
</OverviewCard>
<OverviewCard
class=
"overview-card--single box6"
title=
"领域分布情况"
:icon=
"box
6
HeaderIcon"
>
<OverviewCard
class=
"overview-card--single box6"
title=
"领域分布情况"
:icon=
"box
7
HeaderIcon"
>
<
template
#
right
>
<el-select
v-model=
"box9selectetedTime"
placeholder=
"选择时间"
style=
"width: 90px"
>
<el-option
v-for=
"item in box9YearList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
...
...
@@ -186,7 +212,7 @@
<div
v-else
id=
"box7Chart"
class=
"overview-chart"
></div>
</div>
<div
class=
"overview-tip-row"
>
<TipTab
class=
"overview-tip"
:text=
"'
提出涉华科技法
案委员会分布情况,数据来源:美国国会官网'"
/>
<TipTab
class=
"overview-tip"
:text=
"'
涉华科技法案提
案委员会分布情况,数据来源:美国国会官网'"
/>
<AiButton
class=
"overview-tip-action"
@
mouseenter=
"handleShowAiPane('box7')"
/>
</div>
<div
v-if=
"aiPaneVisible.box7"
class=
"overview-ai-pane"
@
mouseleave=
"handleHideAiPane('box7')"
>
...
...
@@ -194,7 +220,7 @@
</div>
</div>
</OverviewCard>
<OverviewCard
class=
"overview-card--single box8"
title=
"进展分布情况"
:icon=
"box
7
HeaderIcon"
>
<OverviewCard
class=
"overview-card--single box8"
title=
"进展分布情况"
:icon=
"box
8
HeaderIcon"
>
<
template
#
right
>
<el-select
v-model=
"box8selectetedTime"
placeholder=
"选择时间"
style=
"width: 90px"
>
<el-option
v-for=
"item in box8YearList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
...
...
@@ -217,7 +243,7 @@
</div>
</div>
</OverviewCard>
<OverviewCard
class=
"overview-card--single box9"
title=
"关键条款词云"
:icon=
"box
7
HeaderIcon"
>
<OverviewCard
class=
"overview-card--single box9"
title=
"关键条款词云"
:icon=
"box
6
HeaderIcon"
>
<div
class=
"overview-card-body box9-main"
>
<div
class=
"overview-chart-wrap"
v-loading=
"chartLoading.box9"
>
<el-empty
v-if=
"!wordCloudHasData"
description=
"暂无数据"
:image-size=
"100"
/>
...
...
@@ -290,6 +316,7 @@ import getDoublePieChart from "./utils/doublePieChart";
import
box5HeaderIcon
from
"./assets/images/box5-header-icon.png"
;
import
box6HeaderIcon
from
"./assets/images/box6-header-icon.png"
;
import
box7HeaderIcon
from
"./assets/images/box7-header-icon.png"
;
import
box8HeaderIcon
from
"./assets/images/box8-header-icon.png"
import
iconCommit
from
"./assets/icons/icon-commit.png"
;
import
iconILetter
from
"./assets/icons/icon-iLetter.png"
;
...
...
@@ -386,7 +413,9 @@ const committeeCards = computed(() => {
orgId
:
item
.
orgId
,
name
:
item
.
name
,
subText
:
item
.
chamber
,
count
:
item
.
count
count
:
item
.
total
,
delta
:
item
.
count
,
avatar
:
item
.
logoUrl
}));
});
...
...
@@ -403,9 +432,11 @@ const handleGetCommitteeBillCount = async () => {
orgId
:
item
.
orgId
,
name
:
item
.
orgName
,
chamber
:
getChamberLabel
(
item
.
orgType
),
count
:
Number
(
item
.
count
||
0
)
total
:
Number
(
item
.
total
||
0
),
count
:
Number
(
item
.
count
||
0
),
logoUrl
:
item
.
logoUrl
||
""
}))
.
sort
((
a
,
b
)
=>
(
b
.
count
||
0
)
-
(
a
.
count
||
0
));
.
sort
((
a
,
b
)
=>
(
b
.
total
||
0
)
-
(
a
.
total
||
0
));
committeeTotalCount
.
value
=
mappedList
.
length
;
committeeCardList
.
value
=
mappedList
.
slice
(
0
,
3
);
}
else
{
...
...
@@ -431,6 +462,7 @@ const handleToCommitteeMore = () => {
const
hotBillList
=
ref
([]);
// 热门法案列表
const
carouselRef
=
ref
(
null
);
const
MAX_DYQK_DISPLAY_COUNT
=
3
;
const
handleCarouselChange
=
index
=>
{
if
(
hotBillList
.
value
&&
hotBillList
.
value
.
length
>
0
)
{
...
...
@@ -438,6 +470,20 @@ const handleCarouselChange = index => {
}
};
const
getLimitedDyqkList
=
dyqkList
=>
{
if
(
!
Array
.
isArray
(
dyqkList
))
return
[];
return
dyqkList
.
slice
(
0
,
MAX_DYQK_DISPLAY_COUNT
);
};
const
getLimitedCommitteeList
=
committeeList
=>
{
if
(
!
Array
.
isArray
(
committeeList
))
return
[];
return
committeeList
.
slice
(
0
,
2
);
};
const
isLastDyqkItem
=
(
dyqkList
,
index
)
=>
{
return
index
===
getLimitedDyqkList
(
dyqkList
).
length
-
1
;
};
// 切换热门法案
const
handleSwithCurBill
=
name
=>
{
if
(
name
===
"left"
)
{
...
...
@@ -500,25 +546,17 @@ const handleToMoreNews = () => {
// 风险信号
const
warningList
=
ref
([]);
const
box7selectetedTime
=
ref
(
"2025"
);
const
box7YearList
=
ref
([
{
label
:
"2025"
,
value
:
"2025"
},
{
label
:
"2024"
,
value
:
"2024"
},
{
label
:
"2023"
,
value
:
"2023"
},
{
label
:
"2022"
,
value
:
"2022"
}
]);
const
currentYear
=
new
Date
().
getFullYear
();
const
recentFiveYearOptions
=
Array
.
from
({
length
:
5
},
(
_
,
index
)
=>
{
const
year
=
String
(
currentYear
-
index
);
return
{
label
:
year
,
value
:
year
};
});
const
box7selectetedTime
=
ref
(
String
(
currentYear
));
const
box7YearList
=
ref
(
recentFiveYearOptions
);
const
aiPaneVisible
=
ref
({
box5
:
false
,
...
...
@@ -684,25 +722,8 @@ const handleHideAiPane = key => {
};
};
const
box8selectetedTime
=
ref
(
"2025"
);
const
box8YearList
=
ref
([
{
label
:
"2025"
,
value
:
"2025"
},
{
label
:
"2024"
,
value
:
"2024"
},
{
label
:
"2023"
,
value
:
"2023"
},
{
label
:
"2022"
,
value
:
"2022"
}
]);
const
box8selectetedTime
=
ref
(
String
(
currentYear
));
const
box8YearList
=
ref
(
recentFiveYearOptions
);
// 涉华法案数量使用的领域分类列表
const
categoryList
=
ref
([]);
...
...
@@ -757,7 +778,7 @@ const handleGetNews = async () => {
newsList
.
value
=
res
.
data
.
map
(
item
=>
{
return
{
...
item
,
from
:
`
${
item
.
news
Org
}
·
${
item
.
newsDate
?
item
.
newsDate
.
slice
(
5
)
:
""
}
`
from
:
`
${
item
.
news
Date
?
item
.
newsDate
:
""
}
·
${
item
.
newsOrg
||
""
}
`
};
});
}
else
{
...
...
@@ -947,50 +968,70 @@ const box7HasData = ref(true);
const
box7AiData
=
ref
({
inner
:
[],
outer
:
[]
});
const
handleBox7Data
=
async
()
=>
{
chartLoading
.
value
=
{
...
chartLoading
.
value
,
box7
:
true
};
const
selectParam
=
{
moduleType
:
'国会法案'
,
key
:
3
,
selectedDate
:
box7selectetedTime
.
value
?
JSON
.
stringify
([
box7selectetedTime
.
value
+
'-01-01'
,
box7selectetedTime
.
value
+
'-12-31'
])
:
''
,
isInvolveCn
:
true
}
try
{
const
res
=
await
getBillPostOrg
({
year
:
box7selectetedTime
.
value
});
console
.
log
(
"法案提出部门"
,
res
);
const
orgBillNumList
=
res
?.
data
?.
orgBillNumList
||
[];
const
orgBillNumMap
=
res
?.
data
?.
orgBillNumMap
||
{};
if
(
res
.
code
===
200
&&
Array
.
isArray
(
orgBillNumList
)
&&
orgBillNumList
.
length
>
0
)
{
box7HasData
.
value
=
true
;
// 必须等待DOM更新,因为v-if切换可能导致元素刚被创建
await
nextTick
();
let
innerData
=
[];
let
outerData
=
[];
if
(
Array
.
isArray
(
res
?.
data
))
{
innerData
=
res
.
data
.
map
(
item
=>
({
name
:
item
?.
orgName
||
item
?.
orgType
||
""
,
value
:
Number
(
item
?.
count
||
0
)
}))
.
filter
(
item
=>
item
.
name
&&
item
.
value
>
0
);
outerData
=
res
.
data
.
flatMap
(
item
=>
{
const
typeName
=
item
?.
orgName
||
item
?.
orgType
||
""
;
const
list
=
Array
.
isArray
(
item
?.
orgBillNumList
)
?
item
.
orgBillNumList
:
[];
return
list
.
map
(
child
=>
({
name
:
child
?.
orgName
||
""
,
value
:
Number
(
child
?.
count
||
0
),
percent
:
typeof
child
?.
percent
===
"number"
?
child
.
percent
:
Number
(
child
?.
percent
||
0
),
type
:
child
?.
orgType
||
typeName
}))
.
filter
(
child
=>
child
.
name
&&
child
.
value
>
0
);
});
}
else
{
const
orgBillNumList
=
res
?.
data
?.
orgBillNumList
||
[];
const
orgBillNumMap
=
res
?.
data
?.
orgBillNumMap
||
{};
const
data1
=
[];
const
houseTotal
=
Number
(
orgBillNumMap
?.
House
||
0
);
const
senateTotal
=
Number
(
orgBillNumMap
?.
Senate
||
0
);
if
(
houseTotal
>
0
)
data1
.
push
({
name
:
"众议院"
,
value
:
houseTotal
});
if
(
senateTotal
>
0
)
data1
.
push
({
name
:
"参议院"
,
value
:
senateTotal
});
const
getOrgTypeLabel
=
orgType
=>
(
orgType
===
"Senate"
?
"参议院"
:
"众议院"
);
const
typeOrderMap
=
{
众议院
:
0
,
参议院
:
1
};
const
data2
=
orgBillNumList
innerData
=
data1
;
outerData
=
orgBillNumList
.
map
(
item
=>
({
name
:
item
.
orgName
,
value
:
Number
(
item
.
count
||
0
),
percent
:
typeof
item
.
percent
===
"number"
?
item
.
percent
:
Number
(
item
.
percent
||
0
),
type
:
getOrgTypeLabel
(
item
.
orgType
)
type
:
item
.
orgType
===
"Senate"
?
"参议院"
:
"众议院"
}))
// 关键:外环顺序必须按内环(众→参)分组,否则扇区角度会交错导致“不对应”
.
sort
((
a
,
b
)
=>
{
const
t1
=
typeOrderMap
[
a
.
type
]
??
99
;
const
t2
=
typeOrderMap
[
b
.
type
]
??
99
;
if
(
t1
!==
t2
)
return
t1
-
t2
;
return
(
b
.
value
??
0
)
-
(
a
.
value
??
0
);
});
.
filter
(
item
=>
item
.
name
&&
item
.
value
>
0
);
}
if
(
res
.
code
===
200
&&
innerData
.
length
>
0
&&
outerData
.
length
>
0
)
{
box7HasData
.
value
=
true
;
// 必须等待DOM更新,因为v-if切换可能导致元素刚被创建
await
nextTick
();
const
selectParam
=
{
moduleType
:
'国会法案'
,
key
:
3
,
selectedDate
:
box7selectetedTime
.
value
?
JSON
.
stringify
([
box7selectetedTime
.
value
+
'-01-01'
,
box7selectetedTime
.
value
+
'-12-31'
])
:
''
,
isInvolveCn
:
true
}
const
typeOrderMap
=
new
Map
(
innerData
.
map
((
item
,
index
)
=>
[
item
.
name
,
index
]));
const
data2
=
outerData
.
sort
((
a
,
b
)
=>
{
const
t1
=
typeOrderMap
.
get
(
a
.
type
)
??
99
;
const
t2
=
typeOrderMap
.
get
(
b
.
type
)
??
99
;
if
(
t1
!==
t2
)
return
t1
-
t2
;
return
(
b
.
value
??
0
)
-
(
a
.
value
??
0
);
});
const
box7Chart
=
getDoublePieChart
(
data1
,
data2
);
const
box7Chart
=
getDoublePieChart
(
innerData
,
data2
);
setChart
(
box7Chart
,
"box7Chart"
,
true
,
selectParam
);
box7AiData
.
value
=
{
inner
:
data1
,
outer
:
data2
};
box7AiData
.
value
=
{
inner
:
innerData
,
outer
:
data2
};
}
else
{
// 接口异常(如500)时,清空图表数据以避免报错或显示错误信息
box7HasData
.
value
=
false
;
...
...
@@ -1057,7 +1098,7 @@ const handleBox6 = async () => {
// 涉华领域分布
const
box9ChartData
=
ref
([]);
const
box9selectetedTime
=
ref
(
"2025"
);
const
box9selectetedTime
=
ref
(
String
(
currentYear
)
);
// 立法状态下拉:提出法案、众议院通过、参议院通过、解决分歧、呈交总统、完成立法
// v-model 存储的是接口需要的 status 值(直接作为接口参数)
const
box9LegislativeStatus
=
ref
(
"提出法案"
);
...
...
@@ -1069,28 +1110,7 @@ const box9LegislativeStatusList = ref([
{
label
:
"呈交总统"
,
value
:
"呈交总统"
},
{
label
:
"完成立法"
,
value
:
"完成立法"
}
]);
const
box9YearList
=
ref
([
{
label
:
"2026"
,
value
:
"2026"
},
{
label
:
"2025"
,
value
:
"2025"
},
{
label
:
"2024"
,
value
:
"2024"
},
{
label
:
"2023"
,
value
:
"2023"
},
{
label
:
"2022"
,
value
:
"2022"
}
]);
const
box9YearList
=
ref
(
recentFiveYearOptions
);
const
box9HasData
=
ref
(
true
);
let
box9ChartInstance
=
null
;
const
BOX9_MAX_DOMAIN_COUNT
=
7
;
...
...
@@ -1149,7 +1169,7 @@ const handleBox9Data = async () => {
};
}),
null
,
{
showCount
:
false
}
{
showCount
:
true
,
countUnit
:
"项"
}
);
// 记录埋点时,将当前选中的立法状态映射为序号(0-4)
const
selectedIndex
=
box9LegislativeStatusList
.
value
.
findIndex
(
...
...
@@ -2076,12 +2096,22 @@ onUnmounted(() => {
gap
:
8px
;
}
.box1-main-divider
{
margin-top
:
18px
;
margin-bottom
:
18px
;
width
:
468px
;
height
:
1px
;
background
:
var
(
--
bg-black-5
);
}
.box1-main-left-info1
{
margin-top
:
25px
;
margin-top
:
0
;
margin-left
:
4px
;
.info1-box
{
display
:
flex
;
min-height
:
30px
;
align-items
:
flex-start
;
.icon
{
margin-top
:
15px
;
...
...
@@ -2104,18 +2134,60 @@ onUnmounted(() => {
.info1-box-right
{
margin-left
:
40px
;
height
:
30px
;
min-
height
:
30px
;
color
:
var
(
--
text-primary-65-color
);
font-family
:
Microsoft
YaHei
;
font-size
:
var
(
--
font-size-base
);
font-weight
:
400
;
line-height
:
30px
;
}
.info1-box-right--committee
{
display
:
flex
;
flex-direction
:
column
;
justify-content
:
flex-start
;
gap
:
4px
;
height
:
auto
;
min-height
:
30px
;
line-height
:
22px
;
padding-top
:
4px
;
.committee-item
{
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
min-width
:
0
;
}
.committee-logo
{
width
:
18px
;
height
:
18px
;
min-width
:
18px
;
border-radius
:
50%
;
object-fit
:
cover
;
background
:
var
(
--
bg-black-5
);
}
.committee-name
{
color
:
var
(
--
text-primary-65-color
);
font-family
:
Microsoft
YaHei
;
font-size
:
var
(
--
font-size-base
);
font-weight
:
400
;
line-height
:
22px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
}
}
.box1-main-divider--before-list
{
margin-top
:
18px
;
}
.box1-main-left-info2
{
margin-top
:
21px
;
margin-top
:
0
;
height
:
200px
;
width
:
440px
;
position
:
relative
;
...
...
@@ -2216,7 +2288,7 @@ onUnmounted(() => {
left
:
0
;
bottom
:
0
;
box-sizing
:
border-box
;
padding
:
9px
10px
12px
1
0px
;
padding
:
9px
20px
12px
2
0px
;
.inner-box-header
{
height
:
30px
;
...
...
src/views/bill/billHome/utils/doublePieChart.js
浏览文件 @
0204674d
...
...
@@ -69,7 +69,7 @@ const getDoublePieChart = (data1, data2) => {
const
name
=
truncateLabel
(
params
?.
name
,
6
)
const
value
=
params
?.
value
??
0
const
percent
=
typeof
params
?.
percent
===
'number'
?
params
.
percent
:
0
return
`{name|
${
name
}
}\n{time|
${
value
}
条
${
percent
}
%}`
return
`{name|
${
name
}
}\n{time|
${
value
}
项
${
percent
}
%}`
},
minMargin
:
5
,
edgeDistance
:
10
,
...
...
src/views/bill/billHome/utils/piechart.js
浏览文件 @
0204674d
...
...
@@ -10,6 +10,7 @@ const truncateLabel = (value, maxLen = 6) => {
const
getPieChart
=
(
data
,
colorList
,
options
=
{})
=>
{
const
showCount
=
options
.
showCount
!==
false
const
countUnit
=
options
.
countUnit
||
'条'
const
chartColors
=
Array
.
isArray
(
colorList
)
&&
colorList
.
length
?
colorList
:
MUTICHARTCOLORS
let
option
=
{
color
:
chartColors
,
...
...
@@ -38,7 +39,7 @@ const getPieChart = (data, colorList, options = {}) => {
const
name
=
truncateLabel
(
params
?.
name
,
6
)
const
value
=
params
?.
value
??
0
const
percent
=
typeof
params
?.
percent
===
'number'
?
params
.
percent
:
0
const
labelText
=
showCount
?
`
${
value
}
条
${
percent
}
%`
:
`
${
percent
}
%`
const
labelText
=
showCount
?
`
${
value
}
${
countUnit
}
${
percent
}
%`
:
`
${
percent
}
%`
return
`{name|
${
name
}
}\n{time|
${
labelText
}
}`
},
minMargin
:
5
,
...
...
src/views/comprehensiveSearch/searchResults/index.vue
浏览文件 @
0204674d
<
template
>
<div
class=
"wrapper"
>
<div
class=
"wrapper"
ref=
"container"
v-loading=
"isLoading"
element-loading-text=
"数据加载中,请稍候..."
>
<div
class=
"header"
>
<div
class=
"search-box"
>
<div
class=
"left"
>
<div
class=
"icon"
>
<img
src=
"./assets/images/search-icon1.png"
alt=
""
/>
</div>
<el-input
v-model=
"keyword"
:border=
"false"
style=
"width: 900px"
@
keyup
.
enter=
"handleSearch"
/>
<el-input
v-model=
"keyword"
:border=
"false"
style=
"width: 900px"
@
keyup
.
enter=
"handleSearch
(true)
"
/>
</div>
<div
class=
"right"
@
click=
"handleToAi"
>
<img
src=
"./assets/images/ai-icon.png"
alt=
""
/>
...
...
@@ -14,13 +14,8 @@
</div>
<div
class=
"tab-box"
>
<div
class=
"tab-left"
>
<div
class=
"tab"
:class=
"
{ tabActive: activeTabId === item.id }"
v-for="(item, index) in tabList"
:key="index"
@click="handleClickTab(item.name, item.id)"
>
<div
class=
"tab"
:class=
"
{ tabActive: activeTabId === item.id }" v-for="(item, index) in tabList" :key="index"
@click="handleClickTab(item.name, item.id)">
{{
item
.
name
}}
</div>
</div>
...
...
@@ -32,21 +27,15 @@
</div>
-->
</div>
<div
class=
"tag-box"
>
<div
class=
"tag"
:class=
"
{ tagActive: item.selected }"
@click="handleClickDomains(item)"
v-for="item in domains"
:key="item.id"
>
<div
class=
"tag"
:class=
"
{ tagActive: item.selected }" @click="handleClickDomains(item)" v-for="item in domains"
:key="item.id">
{{
item
.
name
}}
</div>
</div>
<div
class=
"info-box"
>
<div
class=
"info-left"
>
<div
class=
"text-box"
>
搜索结果
<span
class=
"text-1"
>
{{
totalNum
}}
</span
>
条
搜索结果
<span
class=
"text-1"
>
{{
totalNum
}}
</span>
条
</div>
<div
class=
"text-box"
>
搜索关键词:
<span
class=
"text-2"
>
{{
keyword
}}
</span>
...
...
@@ -55,14 +44,14 @@
当前领域:
<span
class=
"text-2"
>
{{
curArea
}}
</span>
</div>
-->
</div>
<
!--
<
div
class=
"info-right"
>
<el-select
v-model=
"select
Time"
placeholder=
"选择时间"
style=
"width: 125px
"
>
<el-option
v-for=
"item in
time
List"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
<div
class=
"info-right"
>
<el-select
v-model=
"select
Order"
placeholder=
"请选择排序条件"
style=
"width: 125px"
@
change=
"handleOrderChange
"
>
<el-option
v-for=
"item in
order
List"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
<el-select
v-model=
"selectRelation"
placeholder=
"选择相关度"
style=
"width: 125px"
>
<
!--
<
el-select
v-model=
"selectRelation"
placeholder=
"选择相关度"
style=
"width: 125px"
>
<el-option
v-for=
"item in relationList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</div>
-->
</el-select>
-->
</div>
</div>
<!--
<div
class=
"summary-box"
>
<div
class=
"summary-header"
>
...
...
@@ -86,7 +75,7 @@
</div>
</div>
-->
</div>
<div
class=
"main"
v-if=
"curArea !== '实体清单'"
>
<div
class=
"main"
v-if=
"curArea !== '实体清单'"
>
<div
class=
"item"
v-for=
"(item, index) in searchResults"
:key=
"index"
@
click=
"handleToPage(item)"
>
<div
class=
"item-left"
v-if=
"item.img"
>
<img
:src=
"item?.img"
alt=
""
/>
...
...
@@ -102,8 +91,9 @@
</div>
</div>
</div>
<el-empty
v-if=
"!searchResults.length"
></el-empty>
</div>
<div
class=
"main1"
v-if=
"curArea === '实体清单'"
>
<div
class=
"main1"
v-if=
"curArea === '实体清单'"
>
<div
class=
"item"
v-for=
"(item, index) in searchResults"
:key=
"index"
@
click=
"handleToPage(item)"
>
<div
class=
"main-header"
>
<div
class=
"title"
v-html=
"item?.originalTitle"
></div>
...
...
@@ -112,7 +102,7 @@
</div>
</div>
<div
class=
"entity-box"
>
<div
class=
"entity"
v-for=
"val,
idx in item.sanctionList"
:key=
"idx"
@
click
.
prevent=
"handleCompClick(val)
"
>
<div
class=
"entity"
v-for=
"val,
idx in item.sanctionList"
:key=
"idx
"
>
<div
class=
"icon"
>
<img
src=
"./assets/images/warning.png"
alt=
""
>
</div>
...
...
@@ -122,16 +112,11 @@
<div
class=
"content"
v-html=
"item?.originalDescription"
></div>
<div
class=
"time"
v-if=
"item.date"
>
{{
item
?.
date
}}
</div>
</div>
<el-empty
v-if=
"!searchResults.length"
></el-empty>
</div>
<div
class=
"footer"
>
<el-pagination
@
current-change=
"handleChangeCurrentPage"
:size=
"pageSize"
:current-page=
"currentPage"
background
layout=
"prev, pager, next"
:total=
"totalNum"
/>
<el-pagination
@
current-change=
"handleChangeCurrentPage"
:size=
"pageSize"
:current-page=
"currentPage"
background
layout=
"prev, pager, next"
:total=
"totalNum
<
500
?
totalNum
:
500
"
/>
</div>
</div>
</
template
>
...
...
@@ -148,10 +133,43 @@ import Img3 from "./assets/images/img3.png";
import
{
ElMessage
}
from
"element-plus"
;
const
route
=
useRoute
();
const
container
=
ref
(
null
)
const
isLoading
=
ref
(
false
)
const
select
Time
=
ref
(
"全部时间"
);
const
select
Order
=
ref
(
2
);
const
selectRelation
=
ref
(
"相关度优先"
);
const
handleOrderChange
=
()
=>
{
// alert(selectOrder.value)
currentPage
.
value
=
1
handleSearch
(
true
)
}
const
orderList
=
ref
([
{
label
:
"按时间倒序"
,
value
:
2
},
{
label
:
"按评分倒序"
,
value
:
0
},
]);
const
relationList
=
ref
([
{
label
:
"相关度优先"
,
value
:
"相关度优先"
},
{
label
:
"相关度优先1"
,
value
:
"相关度优先1"
},
{
label
:
"相关度优先2"
,
value
:
"相关度优先2"
}
]);
const
keyword
=
ref
(
""
);
const
tabList
=
ref
([
...
...
@@ -167,17 +185,30 @@ const tabList = ref([
name
:
"政令"
,
id
:
2
},
{
name
:
"智库"
,
id
:
3
},
//
{
//
name: "智库",
//
id: 3
//
},
{
name
:
"智库报告"
,
id
:
4
},
{
name
:
"实体清单"
,
id
:
5
// id: 5,
id
:
10
,
},
{
name
:
"商业管制清单"
,
id
:
11
},
{
name
:
"SDN清单"
,
id
:
14
},
{
name
:
"涉军企业清单"
,
id
:
15
},
{
name
:
"人物"
,
...
...
@@ -205,39 +236,10 @@ const handleClickTab = (name, id) => {
curArea
.
value
=
name
;
domains
.
value
=
[];
selectedDomains
.
value
=
[];
handleSearch
();
currentPage
.
value
=
1
handleSearch
(
true
);
};
const
timeList
=
ref
([
{
label
:
"全部时间"
,
value
:
"全部时间"
},
{
label
:
"2025年"
,
value
:
"2025年"
},
{
label
:
"2024年"
,
value
:
"2024年"
}
]);
const
relationList
=
ref
([
{
label
:
"相关度优先"
,
value
:
"相关度优先"
},
{
label
:
"相关度优先1"
,
value
:
"相关度优先1"
},
{
label
:
"相关度优先2"
,
value
:
"相关度优先2"
}
]);
// 关联检索
const
relatedSearchList
=
ref
([
"金融制度是如何建立的?"
,
...
...
@@ -263,7 +265,11 @@ const totalNum = ref(0);
const
handleChangeCurrentPage
=
page
=>
{
currentPage
.
value
=
page
;
handleSearch
();
container
.
value
?.
scrollTo
({
top
:
0
,
behavior
:
'smooth'
// 平滑滚动
})
handleSearch
(
false
);
};
const
domains
=
ref
([
...
...
@@ -282,8 +288,11 @@ const handleClickDomains = domain => {
return
item
.
selected
;
})
.
map
(
item
=>
item
.
name
);
console
.
log
(
"selectedDomains"
,
selectedDomains
.
value
);
handleSearch
();
// 页码初始化为1
currentPage
.
value
=
1
handleSearch
(
true
);
};
function
highlightText
(
text
,
keyword
)
{
...
...
@@ -293,22 +302,25 @@ function highlightText(text, keyword) {
return
text
.
replace
(
regex
,
'<span style="color: red; font-weight: bold;">$1</span>'
);
}
const
handleSearch
=
async
()
=>
{
const
handleSearch
=
async
(
isShowResultTip
)
=>
{
isLoading
.
value
=
true
let
params
;
if
(
activeTabId
.
value
)
{
params
=
{
size
:
pageSize
.
value
,
page
:
currentPage
.
value
,
keyword
:
keyword
.
value
,
// "出口"
keyword
:
keyword
.
value
,
type
:
activeTabId
.
value
==
100
?
''
:
activeTabId
.
value
,
domains
:
selectedDomains
.
value
domains
:
selectedDomains
.
value
,
sort
:
selectOrder
.
value
};
}
else
{
params
=
{
size
:
pageSize
.
value
,
page
:
currentPage
.
value
,
keyword
:
keyword
.
value
,
// "出口"
domains
:
selectedDomains
.
value
keyword
:
keyword
.
value
,
domains
:
selectedDomains
.
value
,
sort
:
selectOrder
.
value
};
}
try
{
...
...
@@ -321,23 +333,37 @@ const handleSearch = async () => {
id
,
selected
:
false
}));
}
}
searchResults
.
value
=
res
.
data
.
records
;
searchResults
.
value
.
forEach
(
item
=>
{
item
.
titleText
=
item
.
originalTitle
item
.
originalTitle
=
highlightText
(
item
.
originalTitle
,
keyword
.
value
);
item
.
originalDescription
=
highlightText
(
item
.
originalDescription
,
keyword
.
value
);
});
totalNum
.
value
=
res
.
data
.
total
;
totalNum
.
value
=
res
.
data
.
total
if
(
totalNum
.
value
)
{
ElMessage
.
success
(
`共计搜索到
${
totalNum
.
value
}
条结果`
);
if
(
isShowResultTip
)
{
ElMessage
.
success
(
`共计搜索到
${
totalNum
.
value
}
条结果`
);
}
}
else
{
ElMessage
.
warning
(
`共计搜索到
${
totalNum
.
value
}
条结果`
);
if
(
isShowResultTip
)
{
ElMessage
.
warning
(
`共计搜索到
${
totalNum
.
value
}
条结果`
);
}
}
}
else
{
ElMessage
.
warning
(
"当前条件共搜索到0条结果!"
);
if
(
isShowResultTip
)
{
ElMessage
.
warning
(
"当前条件共搜索到0条结果!"
);
}
}
}
catch
(
error
)
{}
}
catch
(
error
)
{
console
.
error
(
'error'
,
error
);
}
finally
{
isLoading
.
value
=
false
}
};
const
handleToPage
=
async
item
=>
{
...
...
@@ -392,9 +418,13 @@ const handleToPage = async item => {
ElMessage
.
warning
(
"获取人物全局信息错误"
);
return
;
}
}
catch
(
error
)
{}
}
catch
(
error
)
{
}
}
window
.
sessionStorage
.
setItem
(
"curTabName"
,
item
.
titleText
);
// window.sessionStorage.setItem(
// "curTabName",
// item.date + item.title
// );
let
curRoute
;
switch
(
item
.
typeStr
)
{
case
"法案"
:
...
...
@@ -430,42 +460,109 @@ const handleToPage = async item => {
});
break
;
case
"实体清单"
:
if
(
!
item
.
organizationId
)
{
ElMessage
.
warning
(
'当前条目没有相关实体,无法跳转'
)
return
}
curRoute
=
router
.
resolve
({
name
:
"companyPages"
,
params
:
{
id
:
item
.
organizationId
}
});
break
;
case
"商业管制清单"
:
if
(
!
item
.
organizationId
)
{
ElMessage
.
warning
(
'当前条目没有相关实体,无法跳转'
)
return
}
curRoute
=
router
.
resolve
({
name
:
"companyPages"
,
params
:
{
id
:
item
.
organizationId
}
});
break
;
case
"SDN清单"
:
if
(
!
item
.
organizationId
)
{
ElMessage
.
warning
(
'当前条目没有相关实体,无法跳转'
)
return
}
curRoute
=
router
.
resolve
({
name
:
"companyPages"
,
params
:
{
id
:
item
.
organizationId
}
});
break
;
case
"涉军企业清单"
:
if
(
!
item
.
organizationId
)
{
ElMessage
.
warning
(
'当前条目没有相关实体,无法跳转'
)
return
}
curRoute
=
router
.
resolve
({
name
:
"companyPages"
,
params
:
{
id
:
item
.
organizationId
}
});
break
;
case
"实体清单事件"
:
curRoute
=
router
.
resolve
({
path
:
"/exportControl/singleSanction"
,
query
:
{
id
:
item
.
id
id
:
item
.
id
,
sanTypeId
:
2
,
date
:
item
.
date
}
});
break
;
// case "人物":
// curRoute = router.resolve({
// path: "/decreeLayout",
// query: {
// id: id
// }
// });
// break;
break
case
"商业管制清单事件"
:
curRoute
=
router
.
resolve
({
path
:
"/exportControl/singleSanction"
,
query
:
{
id
:
item
.
id
,
sanTypeId
:
2
,
date
:
item
.
date
}
});
break
case
"SDN清单事件"
:
curRoute
=
router
.
resolve
({
path
:
"/exportControl/singleSanction"
,
query
:
{
id
:
item
.
id
,
sanTypeId
:
2
,
date
:
item
.
date
}
});
break
case
"涉军企业清单事件"
:
curRoute
=
router
.
resolve
({
path
:
"/exportControl/singleSanction"
,
query
:
{
id
:
item
.
id
,
sanTypeId
:
2
,
date
:
item
.
date
}
});
break
case
"机构"
:
curRoute
=
router
.
resolve
({
path
:
"/newsModeule/"
+
item
.
id
path
:
"/institution"
,
query
:
{
id
:
item
.
id
}
});
break
;
case
"新闻"
:
curRoute
=
router
.
resolve
({
name
:
"newsDetail"
,
query
:
{
newsI
d
:
item
.
id
params
:
{
i
d
:
item
.
id
}
});
break
;
// case "社媒":
// curRoute = router.resolve({
// path: "/decreeLayout",
// query: {
// id: id
// }
// });
// break;
}
window
.
open
(
curRoute
.
href
,
"_blank"
);
...
...
@@ -487,15 +584,9 @@ onMounted(() => {
case
"政令"
:
activeTabId
.
value
=
2
;
break
;
case
"智库"
:
activeTabId
.
value
=
3
;
break
;
case
"智库报告"
:
activeTabId
.
value
=
4
;
break
;
case
"社媒"
:
activeTabId
.
value
=
9
;
break
;
case
"人物"
:
activeTabId
.
value
=
6
;
break
;
...
...
@@ -505,14 +596,24 @@ onMounted(() => {
case
"新闻"
:
activeTabId
.
value
=
8
;
break
;
default
:
activeTabId
.
value
=
5
;
case
"实体清单"
:
activeTabId
.
value
=
10
;
break
;
case
"商业管制清单"
:
activeTabId
.
value
=
11
;
break
;
case
"SDN清单"
:
activeTabId
.
value
=
14
;
break
;
case
"SDN清单"
:
activeTabId
.
value
=
15
;
break
;
}
}
else
{
curArea
.
value
=
"全部"
activeTabId
.
value
=
100
;
}
handleSearch
();
handleSearch
(
true
);
});
const
handleToAi
=
()
=>
{
...
...
@@ -543,8 +644,10 @@ const handleCompClick = item => {
background
:
url("../assets/images/background.png")
no-repeat
;
background-size
:
100%
100%
;
overflow-y
:
auto
;
.header
{
margin-top
:
24px
;
// position: sticky;
// top: 24px;
.header-right
{
...
...
@@ -552,6 +655,7 @@ const handleCompClick = item => {
width
:
360px
;
top
:
134px
;
left
:
1300px
;
.header-right-header
{
height
:
30px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
...
...
@@ -562,9 +666,11 @@ const handleCompClick = item => {
letter-spacing
:
0px
;
text-align
:
left
;
}
.header-right-main
{
margin-top
:
24px
;
height
:
300px
;
.header-right-main-item
{
width
:
360px
;
height
:
40px
;
...
...
@@ -574,19 +680,24 @@ const handleCompClick = item => {
gap
:
8px
;
margin-bottom
:
8px
;
cursor
:
pointer
;
&
:hover
{
background
:
rgb
(
234
,
234
,
234
);
}
.icon
{
width
:
16px
;
height
:
16px
;
img
{
width
:
100%
;
height
:
100%
;
}
margin-left
:
16px
;
margin-top
:
12px
;
}
.text
{
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
...
...
@@ -597,8 +708,10 @@ const handleCompClick = item => {
}
}
}
.search-box
{
display
:
flex
;
.left
{
margin-left
:
240px
;
width
:
960px
;
...
...
@@ -609,44 +722,52 @@ const handleCompClick = item => {
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
background
:
rgba
(
255
,
255
,
255
,
0
.65
);
display
:
flex
;
&
:hover
{
border
:
1px
solid
var
(
--
color-main-active
);
}
.icon
{
width
:
20px
;
height
:
20px
;
margin-top
:
14px
;
margin-left
:
16px
;
margin-right
:
10px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
.right
{
margin-left
:
2px
;
margin-top
:
-16px
;
width
:
80px
;
height
:
80px
;
cursor
:
pointer
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
.tab-box
{
margin-top
:
12px
;
height
:
48px
;
display
:
flex
;
margin-left
:
240px
;
.tab-left
{
width
:
726
px
;
width
:
1000
px
;
height
:
48px
;
display
:
flex
;
justify-content
:
flex-start
;
gap
:
32px
;
gap
:
24px
;
.tab
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
...
...
@@ -656,10 +777,12 @@ const handleCompClick = item => {
box-sizing
:
border-box
;
border-bottom
:
3px
solid
transparent
;
cursor
:
pointer
;
&
:hover
{
color
:
var
(
--
color-main-active
);
}
}
.tabActive
{
color
:
var
(
--
color-main-active
);
font-size
:
18px
;
...
...
@@ -667,6 +790,7 @@ const handleCompClick = item => {
border-bottom
:
3px
solid
var
(
--
color-main-active
);
}
}
.tab-right
{
margin-left
:
74px
;
width
:
120px
;
...
...
@@ -678,6 +802,7 @@ const handleCompClick = item => {
display
:
flex
;
justify-content
:
center
;
gap
:
8px
;
.text
{
margin-top
:
4px
;
height
:
24px
;
...
...
@@ -687,10 +812,12 @@ const handleCompClick = item => {
font-weight
:
700
;
line-height
:
24px
;
}
.icon
{
margin-top
:
3px
;
width
:
8px
;
height
:
5px
;
img
{
width
:
100%
;
height
:
100%
;
...
...
@@ -698,6 +825,7 @@ const handleCompClick = item => {
}
}
}
.tag-box
{
margin-top
:
16px
;
width
:
908px
;
...
...
@@ -707,6 +835,7 @@ const handleCompClick = item => {
flex-wrap
:
wrap
;
gap
:
12px
;
margin-left
:
240px
;
.tag
{
height
:
32px
;
line-height
:
30px
;
...
...
@@ -721,12 +850,14 @@ const handleCompClick = item => {
font-weight
:
400
;
cursor
:
pointer
;
}
.tagActive
{
color
:
var
(
--
color-main-active
);
border
:
1px
solid
var
(
--
color-main-active
);
background
:
rgba
(
231
,
243
,
255
,
1
);
}
}
.info-box
{
margin-top
:
26px
;
margin-left
:
240px
;
...
...
@@ -734,9 +865,11 @@ const handleCompClick = item => {
height
:
32px
;
display
:
flex
;
justify-content
:
space-between
;
.info-left
{
display
:
flex
;
gap
:
24px
;
.text-box
{
height
:
32px
;
line-height
:
32px
;
...
...
@@ -744,12 +877,14 @@ const handleCompClick = item => {
font-size
:
16px
;
font-weight
:
400
;
color
:
rgba
(
59
,
65
,
75
,
1
);
.text-1
{
color
:
var
(
--
color-main-active
);
font-weight
:
700
;
font-size
:
20px
;
margin
:
0
5px
;
}
.text-2
{
color
:
var
(
--
color-main-active
);
font-size
:
18px
;
...
...
@@ -757,11 +892,13 @@ const handleCompClick = item => {
}
}
}
.info-right
{
display
:
flex
;
gap
:
13px
;
}
}
.summary-box
{
width
:
960px
;
height
:
260px
;
...
...
@@ -771,16 +908,19 @@ const handleCompClick = item => {
border
:
1px
solid
rgba
(
231
,
243
,
255
,
1
);
border-radius
:
10px
;
background
:
linear-gradient
(
180deg
,
rgba
(
246
,
250
,
255
,
1
)
,
rgba
(
246
,
250
,
255
,
0
)
100%
);
.summary-header
{
width
:
135px
;
height
:
32px
;
margin-top
:
16px
;
margin-left
:
24px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.summary-content
{
width
:
912px
;
height
:
180px
;
...
...
@@ -795,11 +935,13 @@ const handleCompClick = item => {
}
}
}
.main
{
width
:
913px
;
// height: 1464px;
margin-top
:
36px
;
margin-left
:
240px
;
.item
{
width
:
913px
;
min-height
:
108px
;
...
...
@@ -809,17 +951,21 @@ const handleCompClick = item => {
border-bottom
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
display
:
flex
;
cursor
:
pointer
;
&
:hover
{
background
:
var
(
--
color-bg-hover
);
}
.item-left
{
width
:
170px
;
height
:
115px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.item-right
{
// width: 731px;
flex
:
1
;
...
...
@@ -835,7 +981,11 @@ const handleCompClick = item => {
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.content
{
margin-top
:
10px
;
min-height
:
0
;
...
...
@@ -849,9 +999,11 @@ const handleCompClick = item => {
text-align
:
left
;
overflow
:
hidden
;
}
.item-right-footer
{
margin-top
:
10px
;
display
:
flex
;
.time
{
height
:
24px
;
color
:
rgba
(
132
,
136
,
142
,
1
);
...
...
@@ -863,6 +1015,7 @@ const handleCompClick = item => {
text-align
:
left
;
margin-right
:
16px
;
}
.tag
{
height
:
24px
;
line-height
:
24px
;
...
...
@@ -870,16 +1023,19 @@ const handleCompClick = item => {
padding
:
0
8px
;
border-radius
:
4px
;
}
.tag1
{
border
:
1px
solid
rgba
(
255
,
204
,
199
,
1
);
background
:
rgba
(
255
,
241
,
240
,
1
);
color
:
rgba
(
255
,
77
,
79
,
1
);
}
.tag2
{
color
:
rgba
(
250
,
173
,
20
,
1
);
border
:
1px
solid
rgba
(
255
,
241
,
184
,
1
);
background
:
rgba
(
255
,
251
,
230
,
1
);
}
.tag3
{
color
:
rgba
(
22
,
119
,
255
,
1
);
border
:
1px
solid
rgba
(
186
,
224
,
255
,
1
);
...
...
@@ -889,10 +1045,12 @@ const handleCompClick = item => {
}
}
}
.main1
{
width
:
913px
;
margin-top
:
36px
;
margin-left
:
240px
;
.item
{
width
:
913px
;
min-height
:
108px
;
...
...
@@ -901,14 +1059,17 @@ const handleCompClick = item => {
padding-top
:
16px
;
border-bottom
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
cursor
:
pointer
;
// &:hover {
// background: var(--color-bg-hover);
// }
&
:hover
{
background
:
var
(
--
color-bg-hover
);
}
.main-header
{
min-height
:
24px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
.title
{
width
:
820px
;
// height: 24px;
...
...
@@ -920,8 +1081,11 @@ const handleCompClick = item => {
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.tag
{
height
:
24px
;
line-height
:
24px
;
...
...
@@ -929,27 +1093,32 @@ const handleCompClick = item => {
padding
:
0
8px
;
border-radius
:
4px
;
}
.tag1
{
border
:
1px
solid
rgba
(
255
,
204
,
199
,
1
);
background
:
rgba
(
255
,
241
,
240
,
1
);
color
:
rgba
(
255
,
77
,
79
,
1
);
}
.tag2
{
color
:
rgba
(
250
,
173
,
20
,
1
);
border
:
1px
solid
rgba
(
255
,
241
,
184
,
1
);
background
:
rgba
(
255
,
251
,
230
,
1
);
}
.tag3
{
color
:
rgba
(
22
,
119
,
255
,
1
);
border
:
1px
solid
rgba
(
186
,
224
,
255
,
1
);
background
:
rgba
(
230
,
244
,
255
,
1
);
}
}
.entity-box
{
margin-top
:
12px
;
display
:
flex
;
gap
:
8px
;
flex-wrap
:
wrap
;
.entity
{
display
:
flex
;
justify-content
:
space-between
;
...
...
@@ -960,19 +1129,23 @@ const handleCompClick = item => {
border-radius
:
20px
;
background
:
rgba
(
255
,
241
,
240
,
1
);
cursor
:
pointer
;
&
:hover
{
.name
{
&
:hover
{
.name
{
font-weight
:
bold
;
}
}
.icon
{
width
:
12px
;
height
:
12px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.name
{
margin-top
:
4px
;
height
:
24px
;
...
...
@@ -1001,6 +1174,7 @@ const handleCompClick = item => {
text-align
:
left
;
overflow
:
hidden
;
}
.time
{
margin-top
:
10px
;
height
:
24px
;
...
...
@@ -1015,6 +1189,7 @@ const handleCompClick = item => {
}
}
}
.footer
{
width
:
913px
;
margin-left
:
264px
;
...
...
@@ -1025,10 +1200,12 @@ const handleCompClick = item => {
justify-content
:
center
;
}
}
:deep
(
.el-input__wrapper
)
{
box-shadow
:
none
;
height
:
46px
;
}
:deep
(
.el-input__wrapper
:hover
)
{
box-shadow
:
none
!
important
;
}
...
...
@@ -1036,6 +1213,7 @@ const handleCompClick = item => {
:deep
(
.el-input__wrapper.is-focus
)
{
box-shadow
:
none
!
important
;
}
:deep
(
.el-input__inner
)
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
...
...
src/views/coopRestriction/components/dataSub/index.vue
浏览文件 @
0204674d
...
...
@@ -602,9 +602,7 @@ const initRightChart = () => {
const
domains
=
Array
.
from
(
domainsSet
);
const
types
=
Array
.
from
(
typesSet
);
const
legendSplitAt
=
Math
.
ceil
(
types
.
length
/
2
);
const
legendFirstLine
=
types
.
slice
(
0
,
legendSplitAt
);
const
legendSecondLine
=
types
.
slice
(
legendSplitAt
);
const
legendData
=
types
;
const
indicators
=
domains
.
map
((
domain
)
=>
{
const
domainData
=
rawData
.
filter
((
item
)
=>
item
.
AREA
===
domain
);
...
...
@@ -630,57 +628,56 @@ const initRightChart = () => {
const
option
=
{
color
:
colorMap
,
// 避免自动换行导致“第二行不居中”:拆成两行 legend,每行各自居中
legend
:
[
{
show
:
true
,
type
:
"plain"
,
data
:
legendFirstLine
,
top
:
8
,
left
:
"center"
,
icon
:
"circle"
,
itemWidth
:
12
,
itemHeight
:
12
,
itemGap
:
24
,
textStyle
:
{
color
:
"rgb(95, 101, 108)"
,
fontSize
:
16
,
fontFamily
:
"Microsoft YaHei"
,
fontWeight
:
400
,
lineHeight
:
24
}
// 图例尽量单行居中;放不下则横向滚动(不换行)
legend
:
{
show
:
true
,
type
:
"scroll"
,
orient
:
"horizontal"
,
data
:
legendData
,
top
:
8
,
left
:
"center"
,
width
:
"90%"
,
height
:
24
,
icon
:
"circle"
,
itemWidth
:
12
,
itemHeight
:
12
,
itemGap
:
24
,
pageButtonPosition
:
"end"
,
pageIconSize
:
12
,
pageTextStyle
:
{
color
:
"rgb(95, 101, 108)"
,
fontSize
:
12
,
fontFamily
:
"Microsoft YaHei"
},
{
show
:
legendSecondLine
.
length
>
0
,
type
:
"plain"
,
data
:
legendSecondLine
,
top
:
32
,
left
:
"center"
,
icon
:
"circle"
,
itemWidth
:
12
,
itemHeight
:
12
,
itemGap
:
24
,
textStyle
:
{
color
:
"rgb(95, 101, 108)"
,
fontSize
:
16
,
fontFamily
:
"Microsoft YaHei"
,
fontWeight
:
400
,
lineHeight
:
24
}
textStyle
:
{
color
:
"rgb(95, 101, 108)"
,
fontSize
:
16
,
fontFamily
:
"Microsoft YaHei"
,
fontWeight
:
400
,
lineHeight
:
24
}
]
,
}
,
radar
:
{
// 对齐左侧折线图(grid top=34%)的“图例到图形”间距:下移雷达中心并略缩半径
center
:
[
"50%"
,
"
62
%"
],
radius
:
"
60
%"
,
center
:
[
"50%"
,
"
57
%"
],
radius
:
"
58
%"
,
indicator
:
indicators
,
axisName
:
{
color
:
"rgba(132, 136, 142, 1)"
,
fontSize
:
14
,
fontWeight
:
400
fontFamily
:
"Source Han Sans CN"
,
fontWeight
:
700
,
fontSize
:
16
,
lineHeight
:
24
,
letterSpacing
:
1
,
color
:
"rgb(59, 65, 75)"
},
splitLine
:
{
lineStyle
:
{
color
:
[
"#e6e6e6"
]
}
},
splitArea
:
{
show
:
false
}
splitArea
:
{
show
:
true
,
areaStyle
:
{
// 从最内圈白色开始,向外层交替浅灰
color
:
[
"#ffffff"
,
"rgb(247, 248, 249)"
]
}
}
},
series
:
[
{
...
...
src/views/coopRestriction/components/resLib/index.vue
浏览文件 @
0204674d
...
...
@@ -7,8 +7,7 @@
</div>
</div>
<el-select
v-model=
"sortModel"
placeholder=
"发布时间"
class=
"select"
popper-class=
"coop-select-dropdown"
:teleported=
"true"
placement=
"bottom-start"
:popper-options=
"sortPopperOptions"
@
change=
"handleSortChange"
>
:teleported=
"true"
placement=
"bottom-start"
:popper-options=
"sortPopperOptions"
@
change=
"handleSortChange"
>
<template
#
prefix
>
<img
v-if=
"sortModel !== true"
src=
"@/views/thinkTank/ThinkTankDetail/thinkDynamics/images/image down.png"
class=
"select-prefix-img"
alt=
""
@
click
.
stop=
"toggleSortPrefix"
/>
...
...
@@ -37,35 +36,42 @@
</div>
</div>
</div>
<div
class=
"right"
>
<div
class=
"right"
:class=
"{ 'right--empty': !(mainDataList && mainDataList.length) }"
>
<div
class=
"right-title"
>
<img
src=
"./assets/icon01.png"
alt=
""
/>
<div>
合作限制历程
</div>
</div>
<div
class=
"right-main"
>
<div
class=
"main-content"
>
<div
v-for=
"item in mainDataList"
:key=
"item.id"
class=
"main-item"
>
<div
class=
"date"
>
{{ formatDateCn(item.date) }}
</div>
<img
:src=
"item.img"
alt=
""
class=
"img"
/>
<div
class=
"box"
>
<div
class=
"title"
@
click=
"handleClick(item)"
>
{{ item.title }}
</div>
<div
class=
"content"
@
click=
"handleClick(item)"
>
{{ item.content }}
</div>
<div
class=
"domain"
>
<AreaTag
v-for=
"(domain, i) in item.domain"
:key=
"i"
"
:tagName=
"domain"
>
</AreaTag>
</div>
<div
class=
"type"
:class=
"getTypeClass(item.type)"
>
{{ item.type }}
<
template
v-if=
"mainDataList && mainDataList.length"
>
<div
class=
"main-content"
>
<div
v-for=
"item in mainDataList"
:key=
"item.id"
class=
"main-item"
>
<div
class=
"date"
>
{{
formatDateCn
(
item
.
date
)
}}
</div>
<img
:src=
"item.img"
alt=
""
class=
"img"
/>
<div
class=
"box"
>
<div
class=
"title"
@
click=
"handleClick(item)"
>
{{
item
.
title
}}
</div>
<div
class=
"content"
@
click=
"handleClick(item)"
>
{{
item
.
content
}}
</div>
<div
class=
"domain"
>
<AreaTag
v-for=
"(domain, i) in item.domain"
:key=
"i"
"
:tagName=
"domain"
>
</AreaTag>
</div>
<div
class=
"type"
:class=
"getTypeClass(item.type)"
>
{{
item
.
type
}}
</div>
</div>
</div>
</div>
</div>
<div
class=
"page"
>
<div
class=
"count"
>
共 {{ total }} 项调查
</div>
<el-pagination
v-model:current-page=
"currentPage"
:page-size=
"pageSize"
:total=
"total"
layout=
"prev, pager, next"
background
@
current-change=
"handlePageChange"
/>
</div>
<div
class=
"page"
>
<div
class=
"count"
>
共
{{
total
}}
项调查
</div>
<el-pagination
v-model:current-page=
"currentPage"
:page-size=
"pageSize"
:total=
"total"
layout=
"prev, pager, next"
background
@
current-change=
"handlePageChange"
/>
</div>
</
template
>
<
template
v-else
>
<div
class=
"right-main-empty"
>
<el-empty
class=
"right-el-empty"
description=
"暂无数据"
:image-size=
"100"
/>
</div>
</
template
>
</div>
</div>
</div>
...
...
@@ -533,6 +539,13 @@ watch(currentPage, () => {
border-radius
:
10px
;
background-color
:
#fff
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
display
:
flex
;
flex-direction
:
column
;
&
.right--empty
{
// 与左侧筛选框等高
height
:
432px
;
}
.right-title
{
width
:
1224px
;
...
...
@@ -563,10 +576,28 @@ watch(currentPage, () => {
.right-main
{
width
:
1224px
;
flex
:
1
;
padding
:
12px
0px
80px
0px
;
position
:
relative
;
.right-main-empty
{
height
:
100%
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
padding
:
24px
;
:deep
(
.el-empty__image
)
{
margin-bottom
:
0
;
}
.right-el-empty
{
padding
:
0
;
margin
:
0
;
}
}
.main-content
{
width
:
1224px
;
...
...
@@ -594,15 +625,7 @@ watch(currentPage, () => {
}
&
:last-child::after
{
content
:
""
;
position
:
absolute
;
top
:
37px
;
bottom
:
-37px
;
left
:
108px
;
width
:
2px
;
background-color
:
rgb
(
230
,
231
,
232
);
z-index
:
1
;
height
:
calc
(
100%
-
37px
);
content
:
none
;
}
.date
{
...
...
@@ -635,6 +658,7 @@ watch(currentPage, () => {
.title
{
font-size
:
20px
;
width
:
950px
;
font-weight
:
700
;
font-family
:
"Microsoft YaHei"
;
line-height
:
26px
;
...
...
src/views/coopRestriction/detail/index.vue
浏览文件 @
0204674d
...
...
@@ -5,13 +5,13 @@
<img
:src=
"coopData?.IMAGEURL || defaultImg"
alt=
""
/>
<div
class=
"content"
>
<div
class=
"cl1"
>
{{
coopData
?.
LIMITNAMEZH
}}
</div>
<div
class=
"cl2"
>
{{
coopData
?.
LIMITNAME
}}
</div>
<div
v-if=
"hasLimitNameEn"
class=
"cl2"
>
{{
coopData
?.
LIMITNAME
}}
</div>
<div
class=
"cl3"
>
{{
coopData
?.
LIMITDATE
}}
·
{{
coopData
?.
LIMITORGNAME
}}
</div>
</div>
<div
class=
"btn"
>
<button
class=
"btn1"
><img
src=
"./assets/icon01.png"
alt=
""
/>
查看原文
</button>
<!--
<button
class=
"btn1"
><img
src=
"./assets/icon02.png"
alt=
""
/>
查看官网
</button>
-->
<button
class=
"btn1 active"
><img
src=
"./assets/icon03.png"
alt=
""
/>
分析报告
</button>
<button
class=
"btn1 active"
@
click=
"handleOpenWrittingAsstaint"
><img
src=
"./assets/icon03.png"
alt=
""
/>
分析报告
</button>
</div>
</div>
</div>
...
...
@@ -81,7 +81,8 @@
<img
src=
"./assets/打开按钮.png"
alt=
""
>
</div>
<!-- contentList:单条按原样式展示;多条则逐条展示并加 1.2.3. 前缀 -->
<div
v-if=
"Array.isArray(item.contentList) && item.contentList.length > 1"
class=
"clause-item-content-list"
>
<div
v-if=
"Array.isArray(item.contentList) && item.contentList.length > 1"
class=
"clause-item-content-list"
>
<div
v-for=
"(row, i) in item.contentList"
:key=
"i"
class=
"clause-item-content-row"
>
<span
class=
"row-index"
>
{{
i
+
1
}}
.
</span>
<span
class=
"row-text"
>
{{
row
.
CONTENT
}}
</span>
...
...
@@ -117,6 +118,15 @@ import Rubio from "./assets/卢比奥.png";
import
Bondi
from
"./assets/邦迪.png"
;
import
Nome
from
"./assets/诺姆.png"
;
const
hasLimitNameEn
=
computed
(()
=>
{
return
Boolean
(
String
(
coopData
.
value
?.
LIMITNAME
??
""
).
trim
());
});
const
handleOpenWrittingAsstaint
=
()
=>
{
const
{
href
}
=
router
.
resolve
({
path
:
"/writtingAsstaint"
});
window
.
open
(
href
,
"_blank"
);
};
// 合作限制-查询限制条款
const
limitClauseData
=
ref
([]);
const
getlimitClauseData
=
async
()
=>
{
...
...
@@ -474,9 +484,13 @@ const dataList3 = ref([
.btn
{
width
:
376px
;
height
:
36
px
;
height
:
48
px
;
display
:
flex
;
justify-content
:
right
;
position
:
absolute
;
bottom
:
0
;
margin-left
:
1224px
;
.btn1
{
border-radius
:
6px
;
...
...
src/views/coopRestriction/index.vue
浏览文件 @
0204674d
...
...
@@ -164,6 +164,7 @@ const handleToPosi = id => {
background-size
:
100%
100%
;
position
:
absolute
;
width
:
100%
;
height
:
100%
;
z-index
:
-100
;
top
:
-64px
;
...
...
src/views/dataLibrary/bill/countryBill/index.vue
浏览文件 @
0204674d
...
...
@@ -124,7 +124,7 @@
<
el
-
table
ref
=
"tableRef"
:
data
=
"tableData"
row
-
key
=
"id"
@
selection
-
change
=
"handleSelectionChange"
@
select
=
"handleSelect"
@
select
-
all
=
"handleSelectAll"
style
=
"width: 100%"
:
row
-
style
=
"{ height: '52px'
}
"
>
<
el
-
table
-
column
type
=
"selection"
width
=
"40"
/>
<
el
-
table
-
column
label
=
"法案名称"
width
=
"
455
"
>
<
el
-
table
-
column
label
=
"法案名称"
width
=
"
600
"
>
<
template
#
default
=
"scope"
>
<
span
class
=
"title-item text-compact-bold"
@
click
=
"handleClickToDetail(scope.row)"
>
{{
scope
.
row
.
originalTitle
...
...
@@ -134,14 +134,14 @@
<
el
-
table
-
column
label
=
"日期"
width
=
"120"
class
-
name
=
"date-column"
>
<
template
#
default
=
"scope"
>
{{
scope
.
row
.
date
}}
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"提案人"
width
=
"
48
0"
>
<
el
-
table
-
column
label
=
"提案人"
width
=
"
30
0"
>
<
template
#
default
=
"scope"
>
<
span
class
=
"person-item text-compact"
@
click
=
"handlePerClick(scope.row)"
>
{{
scope
.
row
.
sponsorPersonName
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
property
=
"affiliation"
label
=
"所属党派"
width
=
"120"
/>
<
el
-
table
-
column
property
=
"originDepart"
label
=
"提出委员会"
width
=
"180"
/>
<
el
-
table
-
column
property
=
"originDepart"
label
=
"提出委员会"
/>
<
el
-
table
-
column
property
=
"status"
label
=
"所处阶段"
width
=
"120"
/>
<
/el-table
>
<
/div
>
...
...
src/views/dataLibrary/components/LineChart/lineChart.js
浏览文件 @
0204674d
...
...
@@ -23,6 +23,7 @@ const getLineChart = (dataX, dataY) => {
},
yAxis
:
{
type
:
'value'
,
name
:
'数量'
,
splitLine
:
{
show
:
true
,
lineStyle
:
{
...
...
src/views/dataLibrary/components/PieChart/piechart.js
浏览文件 @
0204674d
...
...
@@ -2,8 +2,8 @@ import { MUTICHARTCOLORS } from "@/common/constant";
const
getPieChart
=
(
data
)
=>
{
const
colorList
=
MUTICHARTCOLORS
let
showData
=
data
if
(
data
.
length
>
1
4
)
{
showData
=
data
.
slice
(
0
,
1
3
)
if
(
data
.
length
>
1
2
)
{
showData
=
data
.
slice
(
0
,
1
1
)
let
num
=
0
data
.
slice
(
13
,).
forEach
(
item
=>
{
num
=
num
+
item
.
value
...
...
@@ -22,8 +22,9 @@ const getPieChart = (data) => {
radius
:
[
150
,
180
],
// height: '96%',
left
:
'center'
,
top
:
24
,
top
:
60
,
width
:
'98%'
,
height
:
'90%'
,
itemStyle
:
{
borderColor
:
'#fff'
,
borderWidth
:
1
...
...
src/views/dataLibrary/index.vue
浏览文件 @
0204674d
...
...
@@ -134,16 +134,15 @@ const siderList = ref([
active
:
false
},
{
name
:
"
实体清单事件
"
,
path
:
"/dataLibrary/data
EntityListEven
t"
,
name
:
"
商业管制清单
"
,
path
:
"/dataLibrary/data
CommerceControlLis
t"
,
active
:
false
},
{
name
:
"
商业管制清单
"
,
path
:
"/dataLibrary/data
CommerceControlLis
t"
,
name
:
"
实体清单事件
"
,
path
:
"/dataLibrary/data
EntityListEven
t"
,
active
:
false
},
{
name
:
"商业管制清单事件"
,
path
:
"/dataLibrary/dataCommerceControlListEvent"
,
...
...
@@ -257,6 +256,10 @@ const siderList = ref([
]);
const
handleSiderItem
=
item
=>
{
if
(
item
.
name
===
'风险信号'
||
item
.
name
===
'市场准入限制'
)
{
ElMessage
.
warning
(
'当前模块开发中,敬请期待!'
)
return
}
siderList
.
value
.
forEach
(
val
=>
{
val
.
active
=
false
;
val
.
isExpanded
=
false
;
...
...
@@ -282,6 +285,10 @@ const handleSiderItem = item => {
};
const
handleSiderSecondItem
=
item
=>
{
if
(
item
.
name
===
'州法案'
||
item
.
name
===
'研究型大学'
||
item
.
name
===
'重点实验室'
)
{
ElMessage
.
warning
(
'当前模块开发中,敬请期待!'
)
return
}
siderList
.
value
.
forEach
(
item
=>
{
if
(
item
.
children
.
length
)
{
item
.
children
.
forEach
(
val
=>
{
...
...
@@ -437,17 +444,16 @@ onMounted(() => {
siderList
.
value
[
3
].
isExpanded
=
true
;
siderList
.
value
[
3
].
children
[
0
].
active
=
true
;
break
;
case
"/dataLibrary/data
EntityListEven
t"
:
case
"/dataLibrary/data
CommerceControlLis
t"
:
siderList
.
value
[
3
].
active
=
true
;
siderList
.
value
[
3
].
isExpanded
=
true
;
siderList
.
value
[
3
].
children
[
1
].
active
=
true
;
break
;
case
"/dataLibrary/data
CommerceControlLis
t"
:
case
"/dataLibrary/data
EntityListEven
t"
:
siderList
.
value
[
3
].
active
=
true
;
siderList
.
value
[
3
].
isExpanded
=
true
;
siderList
.
value
[
3
].
children
[
2
].
active
=
true
;
break
;
case
"/dataLibrary/dataCommerceControlListEvent"
:
siderList
.
value
[
3
].
active
=
true
;
siderList
.
value
[
3
].
isExpanded
=
true
;
...
...
@@ -559,6 +565,7 @@ onBeforeUnmount(() => {
height
:
100%
;
}
}
.title
{
color
:
var
(
--
color-primary-100
);
}
...
...
@@ -737,6 +744,7 @@ onBeforeUnmount(() => {
.tab-item-active
{
border-bottom
:
2px
solid
var
(
--
color-primary-100
)
!
important
;
background
:
var
(
--
color-primary-2
);
}
}
...
...
src/views/dataLibrary/news/index.vue
浏览文件 @
0204674d
...
...
@@ -105,7 +105,7 @@
<
el
-
table
ref
=
"tableRef"
:
data
=
"tableData"
row
-
key
=
"id"
@
selection
-
change
=
"handleSelectionChange"
@
select
=
"handleSelect"
@
select
-
all
=
"handleSelectAll"
style
=
"width: 100%"
:
row
-
style
=
"{ height: '52px'
}
"
>
<
el
-
table
-
column
type
=
"selection"
width
=
"40"
/>
<
el
-
table
-
column
label
=
"新闻标题"
width
=
"
60
0"
>
<
el
-
table
-
column
label
=
"新闻标题"
width
=
"
42
0"
>
<
template
#
default
=
"scope"
>
<
span
class
=
"title-item text-compact-bold"
@
click
=
"handleClickToDetail(scope.row)"
>
{{
scope
.
row
.
originalTitle
...
...
src/views/decree/institution/index.vue
浏览文件 @
0204674d
...
...
@@ -9,7 +9,7 @@
<div
class=
"en-title"
>
{{
institutionInfo
.
enName
}}
</div>
<div
class=
"desc"
>
{{
institutionInfo
.
desc
}}
</div>
<div
class=
"tag-box"
>
<div
class=
"tag"
v-for=
"(tag, index) in
institutionInfo.t
agList"
:key=
"index"
>
<div
class=
"tag"
v-for=
"(tag, index) in
showT
agList"
:key=
"index"
>
{{
tag
}}
</div>
</div>
...
...
@@ -22,13 +22,8 @@
</div>
-->
</div>
<div
class=
"tab-box"
>
<div
class=
"tab"
@
click=
"handleClickTab(item)"
:class=
"
{ tabActive: activeTabName == item.name }"
v-for="(item, index) in tabList"
:key="index"
>
<div
class=
"tab"
@
click=
"handleClickTab(item)"
:class=
"
{ tabActive: activeTabName == item.name }"
v-for="(item, index) in tabList" :key="index">
{{
item
.
name
}}
</div>
</div>
...
...
@@ -61,6 +56,14 @@ const institutionInfo = ref({
logo
:
""
});
const
showTagList
=
computed
(()
=>
{
if
(
institutionInfo
.
value
.
tagList
.
length
>
10
)
{
return
institutionInfo
.
value
.
tagList
.
slice
(
0
,
10
)
}
else
{
return
institutionInfo
.
value
.
tagList
}
})
const
handleGetInfo
=
async
()
=>
{
const
params
=
{
id
:
route
.
query
.
id
...
...
@@ -75,7 +78,7 @@ const handleGetInfo = async () => {
institutionInfo
.
value
.
desc
=
res
.
data
.
orgIntroduction
;
institutionInfo
.
value
.
name
=
res
.
data
.
orgName
;
}
}
catch
(
error
)
{}
}
catch
(
error
)
{
}
};
handleGetInfo
();
...
...
@@ -95,7 +98,7 @@ const tabList = ref([
]);
const
handleClickTab
=
val
=>
{
if
(
val
.
name
===
'深度挖掘'
||
val
.
name
===
'对华制裁'
)
{
if
(
val
.
name
===
'深度挖掘'
||
val
.
name
===
'对华制裁'
)
{
ElMessage
.
warning
(
'当前功能开发中,敬请期待!'
)
return
}
...
...
@@ -125,6 +128,7 @@ onUnmounted(() => {
background-repeat
:
no-repeat
;
background-size
:
100%
100%
;
padding-top
:
16px
;
.header
{
width
:
1600px
;
height
:
200px
;
...
...
@@ -136,20 +140,23 @@ onUnmounted(() => {
background
:
rgba
(
255
,
255
,
255
,
0
.8
);
display
:
flex
;
position
:
relative
;
.header-left
{
width
:
160px
;
height
:
160px
;
margin
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.header-right
{
margin-left
:
24px
;
width
:
1350px
;
overflow
:
hidden
;
overflow-y
:
auto
;
.title
{
margin-top
:
26px
;
height
:
42px
;
...
...
@@ -164,6 +171,7 @@ onUnmounted(() => {
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.en-title
{
margin-top
:
8px
;
height
:
24px
;
...
...
@@ -178,7 +186,9 @@ onUnmounted(() => {
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.desc
{
height
:
48px
;
margin-top
:
6px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
...
...
@@ -187,11 +197,25 @@ onUnmounted(() => {
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
justify
;
overflow
:
hidden
;
display
:
-
webkit-box
;
/* 3. 限制显示的行数(修改数字即可改变行数) */
-webkit-line-clamp
:
2
;
/* 4. 设置文字垂直排列方向 */
-webkit-box-orient
:
vertical
;
/* 5. 隐藏超出部分 */
overflow
:
hidden
;
/* 6. 显示省略号 */
text-overflow
:
ellipsis
;
/* 可选:修复文字间距/换行问题 */
word-break
:
break-all
;
}
.tag-box
{
margin-top
:
14px
;
display
:
flex
;
gap
:
8px
;
.tag
{
height
:
24px
;
padding
:
0px
8px
;
...
...
@@ -206,6 +230,7 @@ onUnmounted(() => {
}
}
}
.header-btn
{
position
:
absolute
;
top
:
26px
;
...
...
@@ -219,14 +244,17 @@ onUnmounted(() => {
justify-content
:
center
;
align-items
:
center
;
cursor
:
pointer
;
.icon
{
width
:
16px
;
height
:
16px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
height
:
22px
;
color
:
rgba
(
255
,
255
,
255
,
1
);
...
...
@@ -237,6 +265,7 @@ onUnmounted(() => {
}
}
}
.tab-box
{
width
:
1600px
;
height
:
64px
;
...
...
@@ -249,6 +278,7 @@ onUnmounted(() => {
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
.tab
{
width
:
526px
;
height
:
54px
;
...
...
@@ -263,10 +293,12 @@ onUnmounted(() => {
font-weight
:
400
;
letter-spacing
:
0px
;
cursor
:
pointer
;
&
:hover
{
background
:
rgba
(
231
,
243
,
255
,
1
);
}
}
.tabActive
{
border
:
2px
solid
rgba
(
174
,
214
,
255
,
1
);
background
:
rgba
(
231
,
243
,
255
,
1
);
...
...
@@ -275,6 +307,7 @@ onUnmounted(() => {
font-weight
:
700
;
}
}
.main
{
height
:
800px
;
width
:
1600px
;
...
...
src/views/exportControl/index.vue
浏览文件 @
0204674d
...
...
@@ -50,7 +50,7 @@
<el-carousel
ref=
"carouselRef"
height=
"370px"
:autoplay=
"
tru
e"
:autoplay=
"
fals
e"
:interval=
"3000"
arrow=
"never"
indicator-position=
"none"
...
...
@@ -59,9 +59,7 @@
<el-carousel-item
v-for=
"(item, index) in entitiesDataInfoList"
:key=
"item.id + index"
>
<div>
<div
class=
"box1-top"
>
<div
class=
"box1-top-title"
>
{{
item
.
postDate
}}
——BIS《实体清单增列与修订条目》
</div>
<div
class=
"box1-top-title"
>
{{
item
.
postDate
}}
——
{{
item
.
name
}}
</div>
<div
class=
"box1-top-content"
>
<div
class=
"box1-top-content-item"
>
<span
class=
"box1-top-content-item-title"
>
· 发布机构:
</span>
...
...
@@ -73,13 +71,7 @@
</div>
<div
class=
"box1-top-content-item"
>
<span
class=
"box1-top-content-item-title"
>
· 涉及领域:
</span>
<!--
<div
class=
"box1-top-content-item-tags"
v-for=
"(domainItem, index) in item.domains"
:key=
"index"
>
<el-tag
:type=
"getTagType(domainItem)"
>
{{
domainItem
}}
</el-tag>
</div>
-->
<AreaTag
v-for=
"(domainItem, index) in item.domains"
:key=
"index"
...
...
@@ -146,7 +138,7 @@
}}
</span>
</div>
<div
class=
"box1-absolute-num"
>
{{
item
.
cnEntityCount
}}{{
item
.
sanTypeId
==
allSanTypeIds
[
0
]
?
"家"
:
"
类
"
}}
{{
item
.
cnEntityCount
}}{{
item
.
sanTypeId
==
allSanTypeIds
[
0
]
?
"家"
:
"
项
"
}}
</div>
</div>
</div>
...
...
@@ -1961,11 +1953,12 @@ const handleMediaClick = item => {
flex-direction
:
column
;
gap
:
20px
;
position
:
relative
;
width
:
1036px
;
.box1-left-arrow
{
position
:
absolute
;
z-index
:
9999
;
left
:
-2
0
px
;
left
:
-2
4
px
;
top
:
135px
;
width
:
24px
!
important
;
height
:
48px
;
...
...
@@ -1989,7 +1982,7 @@ const handleMediaClick = item => {
.box1-right-arrow
{
position
:
absolute
;
z-index
:
9999
;
right
:
-2
0px
;
right
:
0px
;
top
:
135px
;
width
:
24px
;
height
:
48px
;
...
...
@@ -2053,6 +2046,10 @@ const handleMediaClick = item => {
color
:
$base-color
;
margin-top
:
10px
;
margin-bottom
:
15px
;
max-width
:
80%
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
&
-content
{
...
...
@@ -2079,7 +2076,7 @@ const handleMediaClick = item => {
height
:
172px
;
padding-top
:
16px
;
box-sizing
:
border-box
;
padding-right
:
24px
;
&
-title
{
font-size
:
16px
;
font-weight
:
700
;
...
...
src/views/finance/index.vue
浏览文件 @
0204674d
...
...
@@ -60,9 +60,10 @@
<div>
<div
class=
"box1-top"
>
<div
class=
"box1-top-title"
>
{{
item
.
postDate
}}
——
{{
<!--
{{
item
.
postDate
}}
——
{{
item
.
sanTypeId
==
allSanTypeIds
[
0
]
?
"OFAC"
:
"DoD"
}}
《实体清单增列与修订条目》
}}
《实体清单增列与修订条目》 -->
{{
item
.
postDate
}}
——
{{
item
.
name
}}
</div>
<div
class=
"box1-top-content"
>
<div
class=
"box1-top-content-item"
>
...
...
@@ -1073,7 +1074,7 @@ const handleToEntityList = item => {
console
.
log
(
"这是什么数据1 =>"
,
item
);
let
id
=
item
?.
id
;
let
sanTypeId
=
item
?.
sanTypeId
||
1
;
let
date
=
entitiesDataInfoList
.
value
[
currentCarouselIndex
.
value
].
postDate
let
date
=
entitiesDataInfoList
.
value
[
currentCarouselIndex
.
value
].
postDate
;
if
(
!
id
)
{
const
currentItem
=
entitiesDataInfoList
.
value
[
currentCarouselIndex
.
value
];
id
=
currentItem
?.
id
;
...
...
@@ -1826,14 +1827,20 @@ const handleToDataLibrary = item => {
onMounted
(
async
()
=>
{
console
.
log
(
"finance 页面 mounted"
);
try
{
// 获取趋势图数据
fetchTrendData
();
fetchRiskSignals
(
"0109"
);
// 获取社交媒体信息
fetchSocialMediaInfo
();
// 获取新闻资讯
fetchNewsInfo
();
const
[
dataCount
,
entitiesDataInfo
,
industryCountByYear
,
cclList
]
=
await
Promise
.
all
([
getDataCount
(),
getLatestEntityListInfo
(),
getReleaseCount
(
2
)
// getReleaseCount(3)
]);
// 交换第二个和第三个元素
// [dataCount[1], dataCount[2]] = [dataCount[2], dataCount[1]];
console
.
log
(
"dataCount"
,
dataCount
);
infoList
.
value
=
dataCount
.
slice
(
0
,
2
).
map
((
item
,
idx
)
=>
{
return
{
...
...
@@ -1874,6 +1881,11 @@ onMounted(async () => {
tags
:
item
.
domain
};
});
await
fetchSanctionProcess
(
sanctionPage
.
value
,
10
);
// 获取雷达图数据
await
fetchRadarData
(
domainChecked
.
value
);
// 获取出口管制制裁措施
await
fetchSanctionList
();
entityListReleaseFreqChart
.
interpret
({
type
:
"柱状图"
,
name
:
"美国商务部发布实体清单的频次"
,
...
...
@@ -1892,21 +1904,6 @@ onMounted(async () => {
name
:
"美国商务部发布商业管制清单的频次"
,
data
:
commerceControlListReleaseFreq
.
value
});
// 获取趋势图数据
fetchTrendData
();
fetchRiskSignals
(
"0109"
);
// 获取社交媒体信息
fetchSocialMediaInfo
();
// 获取新闻资讯
fetchNewsInfo
();
// fetchEntitiesList(currentPage.value, pageSize.value);
await
fetchSanctionProcess
(
sanctionPage
.
value
,
10
);
// 获取雷达图数据
await
fetchRadarData
(
domainChecked
.
value
);
// 获取出口管制制裁措施
await
fetchSanctionList
();
}
catch
(
err
)
{
console
.
log
(
"此处报错?"
);
console
.
log
(
err
);
...
...
@@ -1957,11 +1954,12 @@ const handleMediaClick = item => {
flex-direction
:
column
;
gap
:
20px
;
position
:
relative
;
width
:
1036px
;
.box1-left-arrow
{
position
:
absolute
;
z-index
:
9999
;
left
:
-2
0
px
;
left
:
-2
4
px
;
top
:
135px
;
width
:
24px
!
important
;
height
:
48px
;
...
...
@@ -1985,7 +1983,7 @@ const handleMediaClick = item => {
.box1-right-arrow
{
position
:
absolute
;
z-index
:
9999
;
right
:
-2
0px
;
right
:
0px
;
top
:
135px
;
width
:
24px
;
height
:
48px
;
...
...
@@ -2050,6 +2048,10 @@ const handleMediaClick = item => {
color
:
$base-color
;
margin-top
:
10px
;
margin-bottom
:
15px
;
max-width
:
80%
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
&
-content
{
...
...
src/views/finance/utils/common-back.js
0 → 100644
浏览文件 @
0204674d
import
{
ref
}
from
"vue"
;
export
const
useChartInterpretation
=
()
=>
{
const
loading
=
ref
(
false
);
const
interpretation
=
ref
(
""
);
const
error
=
ref
(
null
);
const
interpret
=
async
text
=>
{
loading
.
value
=
true
;
error
.
value
=
null
;
interpretation
.
value
=
""
;
try
{
const
response
=
await
fetch
(
"/aiAnalysis/chart_interpretation"
,
{
method
:
"POST"
,
headers
:
{
"X-API-Key"
:
"aircasKEY19491001"
,
"Content-Type"
:
"application/json"
},
body
:
JSON
.
stringify
({
text
})
});
if
(
!
response
.
ok
)
{
throw
new
Error
(
`HTTP error! status:
${
response
.
status
}
`
);
}
const
reader
=
response
.
body
.
getReader
();
const
decoder
=
new
TextDecoder
();
let
buffer
=
""
;
while
(
true
)
{
const
{
done
,
value
}
=
await
reader
.
read
();
if
(
done
)
break
;
buffer
+=
decoder
.
decode
(
value
,
{
stream
:
true
});
const
lines
=
buffer
.
split
(
"
\
n"
);
buffer
=
lines
.
pop
()
||
""
;
for
(
const
line
of
lines
)
{
if
(
line
.
startsWith
(
"data: "
))
{
const
content
=
line
.
substring
(
6
);
const
textMatch
=
content
.
match
(
/"解读":
\s
*"
([^
"
]
*
)
"/
);
if
(
textMatch
&&
textMatch
[
1
])
{
interpretation
.
value
=
textMatch
[
1
];
}
}
}
}
}
catch
(
err
)
{
error
.
value
=
err
.
message
||
"AI 解读失败"
;
console
.
error
(
"AI Chart Interpretation Error:"
,
err
);
}
finally
{
loading
.
value
=
false
;
}
};
return
{
loading
,
interpretation
,
error
,
interpret
};
};
src/views/finance/utils/common.js
浏览文件 @
0204674d
// src/views/finance/utils/common.js
import
{
ref
}
from
"vue"
;
// 【新增】引入获取全局 Signal 的方法
import
{
getAbortSignal
}
from
"@/api/finance/service.js"
;
export
const
useChartInterpretation
=
()
=>
{
const
loading
=
ref
(
false
);
...
...
@@ -10,14 +14,20 @@ export const useChartInterpretation = () => {
error
.
value
=
null
;
interpretation
.
value
=
""
;
// 【新增】在请求发起前获取当前的 Signal
// 注意:必须在每次调用 interpret 时重新获取,以确保拿到最新的 controller 的 signal
const
signal
=
getAbortSignal
();
try
{
// 【修改】在 fetch 中传入 signal
const
response
=
await
fetch
(
"/aiAnalysis/chart_interpretation"
,
{
method
:
"POST"
,
headers
:
{
"X-API-Key"
:
"aircasKEY19491001"
,
"X-API-Key"
:
"aircasKEY19491001"
,
"Content-Type"
:
"application/json"
},
body
:
JSON
.
stringify
({
text
})
body
:
JSON
.
stringify
({
text
}),
signal
:
signal
// 【关键】绑定取消信号
});
if
(
!
response
.
ok
)
{
...
...
@@ -29,6 +39,7 @@ export const useChartInterpretation = () => {
let
buffer
=
""
;
while
(
true
)
{
// reader.read() 会在 signal abort 时抛出 AbortError
const
{
done
,
value
}
=
await
reader
.
read
();
if
(
done
)
break
;
...
...
@@ -39,18 +50,43 @@ export const useChartInterpretation = () => {
for
(
const
line
of
lines
)
{
if
(
line
.
startsWith
(
"data: "
))
{
const
content
=
line
.
substring
(
6
);
const
textMatch
=
content
.
match
(
/"解读":
\s
*"
([^
"
]
*
)
"/
);
if
(
textMatch
&&
textMatch
[
1
])
{
interpretation
.
value
=
textMatch
[
1
];
}
// 尝试解析 JSON
try
{
const
jsonMatch
=
content
.
match
(
/
\{
.*
\}
/
);
if
(
jsonMatch
)
{
const
parsed
=
JSON
.
parse
(
jsonMatch
[
0
]);
if
(
parsed
[
"解读"
])
{
interpretation
.
value
=
parsed
[
"解读"
];
}
}
else
{
// 兼容旧的正则匹配
const
textMatch
=
content
.
match
(
/"解读":
\s
*"
([^
"
]
*
)
"/
);
if
(
textMatch
&&
textMatch
[
1
])
{
interpretation
.
value
=
textMatch
[
1
];
}
}
}
catch
(
e
)
{
// 忽略解析错误
}
}
}
}
}
catch
(
err
)
{
// 【关键】判断是否是因路由切换导致的取消
if
(
err
.
name
===
'AbortError'
)
{
console
.
log
(
'AI 解读请求已取消'
);
loading
.
value
=
false
;
// 关闭 loading
return
;
// 直接返回,不设置 error,不弹窗
}
error
.
value
=
err
.
message
||
"AI 解读失败"
;
console
.
error
(
"AI Chart Interpretation Error:"
,
err
);
}
finally
{
loading
.
value
=
false
;
// 只有在非 AbortError 的情况下,才由 finally 统一关闭 loading
// 如果上面 catch 中已经 return 了,这里不会执行
if
(
err
?.
name
!==
'AbortError'
)
{
loading
.
value
=
false
;
}
}
};
...
...
@@ -60,4 +96,4 @@ export const useChartInterpretation = () => {
error
,
interpret
};
};
};
\ No newline at end of file
src/views/marketAccessRestrictions/marketAccessHome/index.vue
浏览文件 @
0204674d
...
...
@@ -2029,6 +2029,7 @@ onMounted(async () => {
font
-
family
:
Source
Han
Sans
CN
;
font
-
size
:
16
px
;
color
:
var
(
--
text
-
primary
-
65
-
color
);
font
-
weight
:
400
;
}
}
}
...
...
src/views/newsBrief/ModeuleNews.vue
浏览文件 @
0204674d
<
template
>
<el-space
direction=
"vertical"
class=
"full-width news-image-background"
>
<el-button
class=
"float-btn"
@
click=
"gotoNewsBrief(false)"
><el-icon>
<back
/>
</el-icon>
返回
</el-button>
<el-space
style=
"width: 993px;"
direction=
"vertical"
alignment=
"flex-start"
>
<div
id=
"ref-news-list"
style=
"margin-top: 50px; margin-bottom: 24px; margin-left: 24px;"
>
<common-text
class=
"text-title-0-show"
color=
"var(--text-primary-90-color)"
>
{{
moduleName
}}
</common-text>
<common-text
class=
"text-regular"
color=
"var(--text-primary-65-color)"
>
基于情报价值评估预测算法,掌握全球重要潜在动向
</common-text>
</div>
<el-space
direction=
"vertical"
fill
alignment=
"flex-start"
class=
"background-as-card common-padding"
>
<el-radio-group
v-model=
"currentAreaId"
class=
"radio-group-as-gap-btn"
>
<el-space
direction=
"horizontal"
wrap
alignment=
"center"
>
<el-radio-button
:label=
"''"
@
click=
"changeArea('')"
>
全部
</el-radio-button>
<el-radio-button
v-for=
"(t, i) in AreaList"
:key=
"i"
:label=
"t.id"
@
click=
"changeArea(t.id)"
>
{{
t
.
name
}}
</el-radio-button>
</el-space>
</el-radio-group>
<el-divider
style=
"margin: 10px 0px;"
></el-divider>
<div
v-if=
"NewsData?.content?.length > 0"
>
<news-list
:news=
"NewsData.content"
/>
</div>
<el-empty
v-else
></el-empty>
<el-pagination
background
layout=
"total, ->, prev, pager, next"
:current-page=
"modulePage"
:total=
"NewsData?.totalElements ?? 0"
v-on:current-change=
"onCurrentChange"
/>
</el-space>
</el-space>
</el-space>
<el-space
direction=
"vertical"
class=
"full-width news-image-background"
>
<el-button
class=
"float-btn"
@
click=
"gotoNewsBrief(false)"
><el-icon>
<Back
/>
</el-icon>
返回
</el-button
>
<el-space
style=
"width: 993px"
direction=
"vertical"
alignment=
"flex-start"
>
<div
id=
"ref-news-list"
style=
"margin-top: 50px; margin-bottom: 24px; margin-left: 24px"
>
<common-text
class=
"text-title-0-show"
color=
"var(--text-primary-90-color)"
>
{{
moduleName
}}
</common-text>
<common-text
class=
"text-regular"
color=
"var(--text-primary-65-color)"
>
基于情报价值评估预测算法,掌握全球重要潜在动向
</common-text
>
</div>
<el-space
direction=
"vertical"
fill
alignment=
"flex-start"
class=
"background-as-card common-padding"
>
<el-radio-group
v-model=
"currentAreaId"
class=
"radio-group-as-gap-btn"
>
<el-space
direction=
"horizontal"
wrap
alignment=
"center"
>
<el-radio-button
:label=
"''"
@
click=
"changeArea('')"
>
全部
</el-radio-button>
<el-radio-button
v-for=
"(t, i) in AreaList"
:key=
"i"
:label=
"t.id"
@
click=
"changeArea(t.id)"
>
{{
t
.
name
}}
</el-radio-button>
</el-space>
</el-radio-group>
<el-divider
style=
"margin: 10px 0px"
></el-divider>
<div
v-if=
"NewsData?.content?.length > 0"
>
<news-list
:news=
"NewsData.content"
/>
</div>
<el-empty
v-else
></el-empty>
<el-pagination
background
layout=
"total, ->, prev, pager, next"
:current-page=
"modulePage"
:total=
"NewsData?.totalElements ?? 0"
v-on:current-change=
"onCurrentChange"
/>
</el-space>
</el-space>
</el-space>
</
template
>
<
script
setup
>
import
{
ref
,
onMounted
}
from
"vue"
;
import
{
useRoute
}
from
'vue-router'
;
import
'@/styles/container.scss'
;
import
'@/styles/radio.scss'
;
import
{
useRoute
}
from
"vue-router"
;
import
"@/styles/container.scss"
;
import
"@/styles/radio.scss"
;
import
NewsList
from
"./NewsList.vue"
;
import
{
getAreaList
,
getHotNewsByArea
}
from
"@/api/news/newsBrief"
;
import
{
ElSpace
,
ElDivider
,
ElRadioButton
,
ElRadioGroup
,
ElButton
,
ElIcon
,
ElEmpty
,
ElPagination
}
from
"element-plus"
;
import
{
Back
}
from
"@element-plus/icons-vue"
;
import
CommonText
from
"@/components/base/texts/CommonText.vue"
;
import
{
useGotoNewsBrief
}
from
"@/router/modules/news"
;
import
{
scrollToElement
}
from
"@/router/common"
;
import
{
number
}
from
"echarts"
;
const
route
=
useRoute
();
const
gotoNewsBrief
=
useGotoNewsBrief
();
const
moduleId
=
ref
(
route
.
params
.
id
);
...
...
@@ -54,52 +61,50 @@ const AreaList = ref([]);
const
currentAreaId
=
ref
(
""
);
onMounted
(
async
()
=>
{
console
.
log
(
route
.
query
.
name
,
moduleId
.
value
,
moduleName
.
value
);
const
{
data
:
areaList
}
=
await
getAreaList
();
AreaList
.
value
=
areaList
??
[];
await
updateDate
(
""
)
console
.
log
(
route
.
query
.
name
,
moduleId
.
value
,
moduleName
.
value
);
const
{
data
:
areaList
}
=
await
getAreaList
();
AreaList
.
value
=
areaList
??
[];
await
updateDate
(
""
);
});
const
onCurrentChange
=
async
e
=>
{
await
updateDate
(
currentAreaId
.
value
,
e
-
1
)
scrollToElement
(
"ref-news-list"
);
}
await
updateDate
(
currentAreaId
.
value
,
e
-
1
);
scrollToElement
(
"ref-news-list"
);
}
;
async
function
updateDate
(
id
,
page
=
0
)
{
const
{
data
}
=
await
getHotNewsByArea
({
moduleId
:
moduleId
.
value
,
industryId
:
id
?
id
:
null
,
currentPage
:
page
,
});
data
?.
content
?.
forEach
(
item
=>
{
item
.
newsImage
=
item
.
coverUrl
??
""
})
NewsData
.
value
=
data
??
[];
modulePage
.
value
=
(
data
?.
number
??
0
)
+
1
;
const
{
data
}
=
await
getHotNewsByArea
({
moduleId
:
moduleId
.
value
,
industryId
:
id
?
id
:
null
,
currentPage
:
page
});
data
?.
content
?.
forEach
(
item
=>
{
item
.
newsImage
=
item
.
coverUrl
??
""
;
});
NewsData
.
value
=
data
??
[];
modulePage
.
value
=
(
data
?.
number
??
0
)
+
1
;
}
async
function
changeArea
(
id
)
{
await
updateDate
(
id
,
0
)
await
updateDate
(
id
,
0
);
}
</
script
>
<
style
lang=
"scss"
scoped
>
@use
'@/styles/common.scss'
as
*
;
@use
"@/styles/common.scss"
as
*
;
@import
url("./style.css")
;
.float-btn
{
position
:
absolute
;
top
:
24px
;
left
:
40px
;
width
:
92px
;
height
:
40px
;
display
:
flex
;
gap
:
4px
;
align-items
:
center
;
justify-content
:
center
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
255
,
255
,
255
,
1
);
border-radius
:
32px
;
@extend
.text-regular
;
color
:
var
(
--
text-primary-65-color
);
position
:
absolute
;
top
:
24px
;
left
:
40px
;
width
:
92px
;
height
:
40px
;
display
:
flex
;
gap
:
4px
;
align-items
:
center
;
justify-content
:
center
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
255
,
255
,
255
,
1
);
border-radius
:
32px
;
@extend
.text-regular
;
color
:
var
(
--
text-primary-65-color
);
}
</
style
>
\ No newline at end of file
</
style
>
src/views/ruleRestriction/detail/index.vue
浏览文件 @
0204674d
...
...
@@ -132,10 +132,7 @@
<img
:src=
"item.IMAGEURL"
alt
/>
<div
class=
"name"
>
{{
item
.
RELATIONNAME
}}
</div>
<div
class=
"time"
>
{{
getTime
(
item
.
RELATIONDATE
)
}}
</div>
<div
class=
"type"
:class=
"
{ type1: item.TYPE === '行政令', type2: item.TYPE === '法案' }"
>
{{
item
.
TYPE
}}
</div>
<div
class=
"type"
:class=
"
{ type1: item.TYPE === '行政令', type2: item.TYPE === '法案' }">
{{
item
.
TYPE
}}
</div>
<div
class=
"content"
>
{{
item
.
RELATIONCONTENT
}}
</div>
</div>
</div>
...
...
@@ -158,226 +155,226 @@ import gh from "./assets/国会.png";
import
{
getSanctionOverview
,
getBackGround
,
getLimitClause
,
getRelevantMeasures
}
from
'@/api/ruleRestriction/index.js'
const
dataList
=
ref
([
{
id
:
1
,
name
:
"中国检验认证集团(宁波)有限公司"
,
type
:
""
,
img
:
ningbo
},
{
id
:
2
,
name
:
"德国莱茵 TÜV 集团"
,
type
:
""
,
img
:
deguo
}
{
id
:
1
,
name
:
"中国检验认证集团(宁波)有限公司"
,
type
:
""
,
img
:
ningbo
},
{
id
:
2
,
name
:
"德国莱茵 TÜV 集团"
,
type
:
""
,
img
:
deguo
}
]);
const
objList
=
ref
([
{
id
:
1
,
name
:
"撤销多家中国实验室对进入美国市场电子产品的测试认证许可。"
,
time
:
"2025-08-30"
,
img
:
cycle
},
{
id
:
2
,
name
:
"禁止被认定存在“国家安全风险”的中国实验室为进入美国市场的电子设备(如手机、电脑)提供FCC要求的合规性测试与认..."
,
time
:
"2025-08-30"
,
img
:
cycle
},
{
id
:
3
,
name
:
"禁止授权进口或销售任何新设备。新规进一步禁止新设备中使用这些清单内公司的零部件,并允许FCC撤销已授权设备的许可。"
,
time
:
"2025-08-30"
,
img
:
cycle
},
{
id
:
4
,
name
:
"撤销或终止中国电信运营商在美国提供国际电信服务的授权。"
,
time
:
"2025-08-30"
,
img
:
cycle
},
{
id
:
5
,
name
:
"禁止使用特定中国技术和设备的公司建造或运营连接美国的通信电缆。"
,
time
:
"2025-08-30"
,
img
:
cycle
}
{
id
:
1
,
name
:
"撤销多家中国实验室对进入美国市场电子产品的测试认证许可。"
,
time
:
"2025-08-30"
,
img
:
cycle
},
{
id
:
2
,
name
:
"禁止被认定存在“国家安全风险”的中国实验室为进入美国市场的电子设备(如手机、电脑)提供FCC要求的合规性测试与认..."
,
time
:
"2025-08-30"
,
img
:
cycle
},
{
id
:
3
,
name
:
"禁止授权进口或销售任何新设备。新规进一步禁止新设备中使用这些清单内公司的零部件,并允许FCC撤销已授权设备的许可。"
,
time
:
"2025-08-30"
,
img
:
cycle
},
{
id
:
4
,
name
:
"撤销或终止中国电信运营商在美国提供国际电信服务的授权。"
,
time
:
"2025-08-30"
,
img
:
cycle
},
{
id
:
5
,
name
:
"禁止使用特定中国技术和设备的公司建造或运营连接美国的通信电缆。"
,
time
:
"2025-08-30"
,
img
:
cycle
}
]);
const
dataList2
=
ref
([
{
id
:
1
,
name
:
"根据本命令,OET认定TUV/宁波没有说明委员会为何不应开始撤销其作为认可测试实验室资格的程序。在其回应中,TUV/宁波声称其不受委员会规则下的禁止实体控制或指挥,但未说明其被禁止实体持有的股权。TUV/宁波的公司治理文件显示,CCIC是公司的股东,并出资占公司创立资本的49%."
},
{
id
:
2
,
name
:
"TUV/宁波必须在本命令发布后三十五(35)天内提交回复,说明委员会为何不应撤销其认可。如果未能及时回复或提交说明委员会不应撤销其认可的合理依据的回复,可能会导致撤销认可。公司的回复必须包含一份书面详细事实说明,充分说明公司是否由中华人民共和国拥有、控制或受其指示。"
},
{
id
:
3
,
name
:
"OET 根据《法案》第302(e)条以及委员会规则第2.951(d)和(e)条启动了一个程序,以最终确定是否撤销对TUV/Ningbo作为认可测试实验室的认可。此程序为公司提供了额外的通知和机会,以提交书面回应,说明委员会为何不应撤销其当前的认可。"
}
{
id
:
1
,
name
:
"根据本命令,OET认定TUV/宁波没有说明委员会为何不应开始撤销其作为认可测试实验室资格的程序。在其回应中,TUV/宁波声称其不受委员会规则下的禁止实体控制或指挥,但未说明其被禁止实体持有的股权。TUV/宁波的公司治理文件显示,CCIC是公司的股东,并出资占公司创立资本的49%."
},
{
id
:
2
,
name
:
"TUV/宁波必须在本命令发布后三十五(35)天内提交回复,说明委员会为何不应撤销其认可。如果未能及时回复或提交说明委员会不应撤销其认可的合理依据的回复,可能会导致撤销认可。公司的回复必须包含一份书面详细事实说明,充分说明公司是否由中华人民共和国拥有、控制或受其指示。"
},
{
id
:
3
,
name
:
"OET 根据《法案》第302(e)条以及委员会规则第2.951(d)和(e)条启动了一个程序,以最终确定是否撤销对TUV/Ningbo作为认可测试实验室的认可。此程序为公司提供了额外的通知和机会,以提交书面回应,说明委员会为何不应撤销其当前的认可。"
}
]);
const
dataList3
=
ref
([
{
id
:
1
,
name
:
"美国商务部工业与安全局发布实体清单,涉及多家中国半导体企业"
,
time
:
"2025年9月12日"
,
content
:
"23家中国实体,包括复旦微电旗下多家公司、华岭股份等,指控这些实体“违背美国国家安全或外交政策利益”,包括为中国的..."
,
type
:
"行政令"
,
img
:
swb
},
{
id
:
2
,
name
:
"美国白宫发布总统政令,提出将发展美国人工智能产业硬件支持放在新任期的科技首要地位"
,
time
:
"2025年9月11日"
,
content
:
"9个中国实体(8家企业和1名个人),例如湖北奇卡工业有限公司、广州雅凯国际货运代理有限公司等,指控这些实体为也门胡塞..."
,
type
:
"行政令"
,
img
:
bg
},
{
id
:
3
,
name
:
"美国财政部外国资产控制办公室指控中国企业及船只"
,
time
:
"2025年3月13日"
,
content
:
"4家中国企业和3艘关联船只(如香港和顺运贸有限公司、华夏贸易有限公司等),指控这些公司拥有或运营向中国运送伊朗石油或..."
,
type
:
"行政令"
,
img
:
czb
},
{
id
:
4
,
name
:
"美国国会通过《芯片科学》法案"
,
time
:
"2025年1月3日"
,
content
:
"多家中国实体,包括成都雷电微力科技股份有限公司、中国科学院长春光学精密机械与物理研究所等,指控这些实体与中国高超音..."
,
type
:
"法案"
,
img
:
gh
}
{
id
:
1
,
name
:
"美国商务部工业与安全局发布实体清单,涉及多家中国半导体企业"
,
time
:
"2025年9月12日"
,
content
:
"23家中国实体,包括复旦微电旗下多家公司、华岭股份等,指控这些实体“违背美国国家安全或外交政策利益”,包括为中国的..."
,
type
:
"行政令"
,
img
:
swb
},
{
id
:
2
,
name
:
"美国白宫发布总统政令,提出将发展美国人工智能产业硬件支持放在新任期的科技首要地位"
,
time
:
"2025年9月11日"
,
content
:
"9个中国实体(8家企业和1名个人),例如湖北奇卡工业有限公司、广州雅凯国际货运代理有限公司等,指控这些实体为也门胡塞..."
,
type
:
"行政令"
,
img
:
bg
},
{
id
:
3
,
name
:
"美国财政部外国资产控制办公室指控中国企业及船只"
,
time
:
"2025年3月13日"
,
content
:
"4家中国企业和3艘关联船只(如香港和顺运贸有限公司、华夏贸易有限公司等),指控这些公司拥有或运营向中国运送伊朗石油或..."
,
type
:
"行政令"
,
img
:
czb
},
{
id
:
4
,
name
:
"美国国会通过《芯片科学》法案"
,
time
:
"2025年1月3日"
,
content
:
"多家中国实体,包括成都雷电微力科技股份有限公司、中国科学院长春光学精密机械与物理研究所等,指控这些实体与中国高超音..."
,
type
:
"法案"
,
img
:
gh
}
]);
const
overviewInfo
=
ref
({})
const
sanRecordId
=
ref
(
''
)
const
backgroundInfo
=
ref
([])
const
limitClauseInfo
=
ref
([])
const
backgroundInfo
=
ref
([])
const
limitClauseInfo
=
ref
([])
const
relevantMeasureInfo
=
ref
([])
const
getUrlParams
=
()
=>
{
const
urlParams
=
new
URLSearchParams
(
window
.
location
.
search
);
sanRecordId
.
value
=
urlParams
.
get
(
"id"
)
||
""
const
urlParams
=
new
URLSearchParams
(
window
.
location
.
search
);
sanRecordId
.
value
=
urlParams
.
get
(
"id"
)
||
""
}
const
getSanctionOverviewInfo
=
async
()
=>
{
try
{
const
res
=
await
getSanctionOverview
(
sanRecordId
.
value
);
console
.
log
(
'------getSanctionOverviewInfo res'
,
res
)
if
(
res
&&
res
.
code
===
200
)
{
console
.
log
(
'----getSanctionOverviewInfo'
,
res
.
data
)
overviewInfo
.
value
=
res
.
data
}
}
catch
(
error
)
{
console
.
error
(
"获取规则限制基本详情接口失败:"
,
error
);
}
try
{
const
res
=
await
getSanctionOverview
(
sanRecordId
.
value
);
console
.
log
(
'------getSanctionOverviewInfo res'
,
res
)
if
(
res
&&
res
.
code
===
200
)
{
console
.
log
(
'----getSanctionOverviewInfo'
,
res
.
data
)
overviewInfo
.
value
=
res
.
data
}
}
catch
(
error
)
{
console
.
error
(
"获取规则限制基本详情接口失败:"
,
error
);
}
}
const
getBackGroundInfo
=
async
()
=>
{
try
{
const
res
=
await
getBackGround
(
sanRecordId
.
value
);
console
.
log
(
'------getBackGroundInfo res'
,
res
)
if
(
res
&&
res
.
code
===
200
)
{
console
.
log
(
'----getBackGroundInfo'
,
res
.
data
)
backgroundInfo
.
value
=
res
.
data
}
}
catch
(
error
)
{
console
.
error
(
"获取背景分析接口失败:"
,
error
);
}
try
{
const
res
=
await
getBackGround
(
sanRecordId
.
value
);
console
.
log
(
'------getBackGroundInfo res'
,
res
)
if
(
res
&&
res
.
code
===
200
)
{
console
.
log
(
'----getBackGroundInfo'
,
res
.
data
)
backgroundInfo
.
value
=
res
.
data
}
}
catch
(
error
)
{
console
.
error
(
"获取背景分析接口失败:"
,
error
);
}
}
const
getLimitClauseInfo
=
async
()
=>
{
try
{
const
res
=
await
getLimitClause
(
sanRecordId
.
value
);
console
.
log
(
'------getLimitClauseInfo res'
,
res
)
if
(
res
&&
res
.
code
===
200
)
{
console
.
log
(
'----getLimitClauseInfo'
,
res
.
data
)
limitClauseInfo
.
value
=
res
.
data
}
}
catch
(
error
)
{
console
.
error
(
"获取限制条款接口失败:"
,
error
);
}
try
{
const
res
=
await
getLimitClause
(
sanRecordId
.
value
);
console
.
log
(
'------getLimitClauseInfo res'
,
res
)
if
(
res
&&
res
.
code
===
200
)
{
console
.
log
(
'----getLimitClauseInfo'
,
res
.
data
)
limitClauseInfo
.
value
=
res
.
data
}
}
catch
(
error
)
{
console
.
error
(
"获取限制条款接口失败:"
,
error
);
}
}
const
getRelevantMeasuresInfo
=
async
()
=>
{
try
{
const
res
=
await
getRelevantMeasures
(
sanRecordId
.
value
);
console
.
log
(
'------getRelevantMeasuresInfo res'
,
res
)
if
(
res
&&
res
.
code
===
200
)
{
console
.
log
(
'----getRelevantMeasuresInfo'
,
res
.
data
)
relevantMeasureInfo
.
value
=
res
.
data
}
}
catch
(
error
)
{
console
.
error
(
"获取限制条款接口失败:"
,
error
);
}
try
{
const
res
=
await
getRelevantMeasures
(
sanRecordId
.
value
);
console
.
log
(
'------getRelevantMeasuresInfo res'
,
res
)
if
(
res
&&
res
.
code
===
200
)
{
console
.
log
(
'----getRelevantMeasuresInfo'
,
res
.
data
)
relevantMeasureInfo
.
value
=
res
.
data
}
}
catch
(
error
)
{
console
.
error
(
"获取限制条款接口失败:"
,
error
);
}
}
const
getTime
=
(
time
)
=>
{
if
(
time
)
{
const
array
=
time
.
split
(
'-'
)
return
`
${
array
[
0
]}
年
${
array
[
1
]}
月
${
array
[
2
]}
日`
}
if
(
time
)
{
const
array
=
time
.
split
(
'-'
)
return
`
${
array
[
0
]}
年
${
array
[
1
]}
月
${
array
[
2
]}
日`
}
}
const
getClassName
=
(
type
)
=>
{
let
className
=
''
switch
(
type
)
{
case
'人工智能'
:
className
=
'ai'
break
case
'新材料'
:
className
=
'material'
break
case
'量子科技'
:
className
=
'technology'
break
case
'生物科技'
:
className
=
'organism'
break
case
'航空航天'
:
className
=
'aerospace'
break
case
'能源'
:
className
=
'energy'
break
case
'集成电路'
:
className
=
'integrated'
break
case
''
:
className
=
'none-class'
break
default
:
className
=
'other'
}
return
className
let
className
=
''
switch
(
type
)
{
case
'人工智能'
:
className
=
'ai'
break
case
'新材料'
:
className
=
'material'
break
case
'量子科技'
:
className
=
'technology'
break
case
'生物科技'
:
className
=
'organism'
break
case
'航空航天'
:
className
=
'aerospace'
break
case
'能源'
:
className
=
'energy'
break
case
'集成电路'
:
className
=
'integrated'
break
case
''
:
className
=
'none-class'
break
default
:
className
=
'other'
}
return
className
}
const
getRelation
=
ref
({})
watch
(
overviewInfo
,
()
=>
{
getRelation
.
value
=
overviewInfo
.
value
?.
Relation
?
overviewInfo
.
value
?.
Relation
[
0
]
:
{}
getRelation
.
value
=
overviewInfo
.
value
?.
Relation
?
overviewInfo
.
value
?.
Relation
[
0
]
:
{}
},
{
deep
:
true
deep
:
true
})
onMounted
(
async
()
=>
{
getUrlParams
()
await
getSanctionOverviewInfo
()
await
getBackGroundInfo
()
await
getLimitClauseInfo
()
await
getRelevantMeasuresInfo
()
getUrlParams
()
await
getSanctionOverviewInfo
()
await
getBackGroundInfo
()
await
getLimitClauseInfo
()
await
getRelevantMeasuresInfo
()
})
</
script
>
...
...
@@ -386,12 +383,14 @@ onMounted(async () => {
margin
:
0
;
padding
:
0
;
}
.cooperation-restrictions-detail
{
width
:
100%
;
height
:
100%
;
background
:
rgba
(
243
,
243
,
244
,
1
);
overflow
:
auto
;
padding-bottom
:
50px
;
// 领域样式
// 人工智能
.ai
{
...
...
@@ -399,42 +398,49 @@ onMounted(async () => {
background
:
rgba
(
255
,
241
,
240
,
1
);
color
:
rgba
(
245
,
34
,
45
,
1
);
}
// 新材料
.material
{
border
:
1px
solid
rgba
(
135
,
232
,
222
,
1
);
background
:
rgba
(
230
,
255
,
251
,
1
);
color
:
rgba
(
19
,
168
,
168
,
1
);
}
// 量子科技
.technology
{
border
:
1px
solid
rgba
(
211
,
173
,
247
,
1
);
background
:
rgba
(
249
,
240
,
255
,
1
);
color
:
rgba
(
114
,
46
,
209
,
1
);
}
// 生物科技
.organism
{
border
:
1px
solid
rgba
(
145
,
202
,
255
,
1
);
background
:
rgba
(
230
,
244
,
255
,
1
);
color
:
rgba
(
22
,
119
,
255
,
1
);
}
// 航空航天
.aerospace
{
border
:
1px
solid
rgba
(
173
,
198
,
255
,
1
);
background
:
rgba
(
240
,
245
,
255
,
1
);
color
:
rgba
(
22
,
119
,
255
,
1
);
}
// 能源
.energy
{
border
:
1px
solid
rgba
(
217
,
247
,
190
,
1
);
background
:
rgba
(
246
,
255
,
237
,
1
);
color
:
rgba
(
56
,
158
,
13
,
1
);
}
// 集成电路
.integrated
{
border
:
1px
solid
rgba
(
186
,
224
,
255
,
1
);
background
:
rgba
(
230
,
244
,
255
,
1
);
color
:
rgba
(
9
,
88
,
217
,
1
);
}
// 其他
.other
{
border
:
1px
solid
rgba
(
186
,
224
,
255
,
1
);
...
...
@@ -447,6 +453,7 @@ onMounted(async () => {
background
:
transparent
;
border
:
none
;
}
.nav
{
width
:
100%
;
height
:
120px
;
...
...
@@ -456,6 +463,7 @@ onMounted(async () => {
position
:
sticky
;
top
:
0
;
z-index
:
99999999
;
.nav-main
{
width
:
1600px
;
height
:
81px
;
...
...
@@ -463,14 +471,17 @@ onMounted(async () => {
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
img
{
width
:
72px
;
height
:
72px
;
margin-right
:
16px
;
}
.content
{
// width: 758px;
height
:
81px
;
// margin-right: 378px;
.cl1
{
font-size
:
24px
;
...
...
@@ -480,6 +491,7 @@ onMounted(async () => {
color
:
rgb
(
59
,
65
,
75
);
margin-bottom
:
1px
;
}
.cl2
{
font-size
:
16px
;
font-weight
:
400
;
...
...
@@ -488,6 +500,7 @@ onMounted(async () => {
color
:
rgb
(
59
,
65
,
75
);
margin-bottom
:
1px
;
}
.cl3
{
font-size
:
16px
;
font-weight
:
400
;
...
...
@@ -496,10 +509,12 @@ onMounted(async () => {
color
:
rgb
(
95
,
101
,
108
);
}
}
.btn
{
width
:
376px
;
height
:
36px
;
display
:
flex
;
.btn1
{
border-radius
:
6px
;
border
:
1px
solid
rgb
(
230
,
231
,
232
);
...
...
@@ -511,17 +526,20 @@ onMounted(async () => {
align-items
:
center
;
justify-content
:
center
;
cursor
:
pointer
;
img
{
width
:
16px
;
height
:
16px
;
margin-right
:
8px
;
}
font-size
:
16px
;
font-weight
:
400
;
line-height
:
22px
;
font-family
:
"Microsoft YaHei"
;
color
:
rgb
(
95
,
101
,
108
);
}
.active
{
background-color
:
rgb
(
5
,
95
,
194
);
color
:
#fff
;
...
...
@@ -529,6 +547,7 @@ onMounted(async () => {
}
}
}
.title
{
width
:
1600px
;
height
:
50px
;
...
...
@@ -540,6 +559,7 @@ onMounted(async () => {
display
:
flex
;
align-items
:
center
;
position
:
relative
;
.title-one
{
margin-left
:
23px
;
font-size
:
16px
;
...
...
@@ -548,6 +568,7 @@ onMounted(async () => {
font-family
:
"Microsoft YaHei"
;
color
:
rgb
(
59
,
65
,
75
);
}
.title-two
{
font-size
:
16px
;
font-weight
:
700
;
...
...
@@ -556,6 +577,7 @@ onMounted(async () => {
color
:
rgb
(
5
,
95
,
194
);
cursor
:
pointer
;
}
img
{
width
:
24px
;
height
:
24px
;
...
...
@@ -565,15 +587,18 @@ onMounted(async () => {
cursor
:
pointer
;
}
}
.main
{
width
:
1600px
;
height
:
1373px
;
margin
:
0
auto
;
display
:
flex
;
.left
{
width
:
520px
;
height
:
1157px
;
margin-right
:
17px
;
.left-top
{
margin-bottom
:
16px
;
width
:
520px
;
...
...
@@ -582,6 +607,7 @@ onMounted(async () => {
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
position
:
relative
;
.left-top-title
{
font-size
:
20px
;
font-weight
:
700
;
...
...
@@ -592,6 +618,7 @@ onMounted(async () => {
top
:
14px
;
left
:
22px
;
}
.img1
{
width
:
8px
;
height
:
20px
;
...
...
@@ -599,6 +626,7 @@ onMounted(async () => {
left
:
0px
;
top
:
18px
;
}
.img2
{
width
:
28px
;
height
:
28px
;
...
...
@@ -607,6 +635,7 @@ onMounted(async () => {
right
:
44px
;
cursor
:
pointer
;
}
.img3
{
width
:
28px
;
height
:
28px
;
...
...
@@ -615,6 +644,7 @@ onMounted(async () => {
right
:
12px
;
cursor
:
pointer
;
}
.left-top-content
{
width
:
470px
;
height
:
122px
;
...
...
@@ -628,6 +658,7 @@ onMounted(async () => {
justify-content
:
center
;
align-items
:
center
;
padding
:
16px
24px
;
span
{
font-size
:
16px
;
font-weight
:
700
;
...
...
@@ -636,15 +667,18 @@ onMounted(async () => {
color
:
rgb
(
5
,
95
,
194
);
}
}
.left-top-bottom
{
width
:
460px
;
height
:
144px
;
position
:
absolute
;
top
:
200px
;
left
:
26px
;
div
{
height
:
24px
;
margin-bottom
:
16px
;
.tit
{
display
:
inline-block
;
width
:
120px
;
...
...
@@ -654,6 +688,7 @@ onMounted(async () => {
line-height
:
24px
;
color
:
rgb
(
59
,
65
,
75
);
}
.tit1
{
font-size
:
16px
;
font-weight
:
400
;
...
...
@@ -661,10 +696,12 @@ onMounted(async () => {
line-height
:
30px
;
color
:
rgb
(
59
,
65
,
75
);
}
.tit2
{
color
:
rgb
(
5
,
95
,
194
);
cursor
:
pointer
;
}
.tit3
{
display
:
inline-block
;
border-radius
:
4px
;
...
...
@@ -677,6 +714,7 @@ onMounted(async () => {
}
}
}
.left-bottom
{
width
:
520px
;
height
:
190px
;
...
...
@@ -685,6 +723,7 @@ onMounted(async () => {
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
position
:
relative
;
margin-bottom
:
16px
;
.left-bottom-title
{
font-size
:
20px
;
font-weight
:
700
;
...
...
@@ -695,6 +734,7 @@ onMounted(async () => {
top
:
14px
;
left
:
22px
;
}
.img1
{
width
:
8px
;
height
:
20px
;
...
...
@@ -702,6 +742,7 @@ onMounted(async () => {
left
:
0px
;
top
:
18px
;
}
.img2
{
width
:
28px
;
height
:
28px
;
...
...
@@ -710,6 +751,7 @@ onMounted(async () => {
right
:
44px
;
cursor
:
pointer
;
}
.img3
{
width
:
28px
;
height
:
28px
;
...
...
@@ -718,17 +760,20 @@ onMounted(async () => {
right
:
12px
;
cursor
:
pointer
;
}
.left-bottom-main
{
width
:
478px
;
height
:
108px
;
position
:
absolute
;
top
:
60px
;
left
:
21px
;
img
{
position
:
absolute
;
top
:
12px
;
right
:
12px
;
}
.main-box
{
width
:
480px
;
height
:
48px
;
...
...
@@ -737,6 +782,7 @@ onMounted(async () => {
margin-bottom
:
12px
;
position
:
relative
;
cursor
:
pointer
;
img
{
width
:
24px
;
height
:
24px
;
...
...
@@ -744,6 +790,7 @@ onMounted(async () => {
top
:
12px
;
left
:
16px
;
}
.name
{
position
:
absolute
;
top
:
12px
;
...
...
@@ -754,6 +801,7 @@ onMounted(async () => {
line-height
:
24px
;
color
:
rgb
(
59
,
65
,
75
);
}
.type
{
position
:
absolute
;
top
:
12px
;
...
...
@@ -767,6 +815,7 @@ onMounted(async () => {
}
}
}
.left-bottom-B
{
width
:
520px
;
height
:
567px
;
...
...
@@ -774,6 +823,7 @@ onMounted(async () => {
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
position
:
relative
;
.left-bottom-title
{
font-size
:
20px
;
font-weight
:
700
;
...
...
@@ -784,6 +834,7 @@ onMounted(async () => {
top
:
14px
;
left
:
22px
;
}
.img1
{
width
:
8px
;
height
:
20px
;
...
...
@@ -791,6 +842,7 @@ onMounted(async () => {
left
:
0px
;
top
:
18px
;
}
.img2
{
width
:
28px
;
height
:
28px
;
...
...
@@ -799,6 +851,7 @@ onMounted(async () => {
right
:
44px
;
cursor
:
pointer
;
}
.img3
{
width
:
28px
;
height
:
28px
;
...
...
@@ -807,17 +860,20 @@ onMounted(async () => {
right
:
12px
;
cursor
:
pointer
;
}
.left-bottom-main
{
width
:
478px
;
height
:
446px
;
position
:
absolute
;
top
:
60px
;
left
:
24px
;
.main-box
{
width
:
495px
;
margin-bottom
:
16px
;
padding
:
0
22px
0
0px
;
position
:
relative
;
img
{
width
:
10px
;
height
:
10px
;
...
...
@@ -826,6 +882,7 @@ onMounted(async () => {
left
:
0
;
z-index
:
100
;
}
.time
{
margin-left
:
21px
;
margin-bottom
:
4px
;
...
...
@@ -835,6 +892,7 @@ onMounted(async () => {
line-height
:
24px
;
color
:
rgb
(
5
,
95
,
194
);
}
.name
{
margin-left
:
21px
;
font-size
:
16px
;
...
...
@@ -844,6 +902,7 @@ onMounted(async () => {
color
:
rgb
(
59
,
65
,
75
);
}
}
.btn
{
cursor
:
pointer
;
width
:
100%
;
...
...
@@ -854,11 +913,13 @@ onMounted(async () => {
font-family
:
"Microsoft YaHei"
;
line-height
:
22px
;
color
:
rgb
(
5
,
95
,
194
);
img
{
width
:
16px
;
height
:
16px
;
}
}
.line
{
position
:
absolute
;
height
:
360px
;
...
...
@@ -869,9 +930,11 @@ onMounted(async () => {
}
}
}
.right
{
width
:
1063px
;
height
:
1800px
;
.right-top
{
margin-bottom
:
16px
;
width
:
1063px
;
...
...
@@ -881,6 +944,7 @@ onMounted(async () => {
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
position
:
relative
;
padding
:
60px
19px
24px
22px
;
.right-top-title
{
font-size
:
20px
;
font-weight
:
700
;
...
...
@@ -891,6 +955,7 @@ onMounted(async () => {
top
:
14px
;
left
:
22px
;
}
.img1
{
width
:
8px
;
height
:
20px
;
...
...
@@ -898,11 +963,13 @@ onMounted(async () => {
left
:
0px
;
top
:
18px
;
}
.right-top-content
{
width
:
1022px
;
height
:
312px
;
overflow-y
:
auto
;
overflow-x
:
hidden
;
overflow-y
:
auto
;
overflow-x
:
hidden
;
.right-top-item
{
width
:
1022px
;
padding
:
12px
0px
;
...
...
@@ -912,6 +979,7 @@ onMounted(async () => {
border-top
:
1px
solid
rgb
(
234
,
236
,
238
);
border-bottom
:
1px
solid
rgb
(
234
,
236
,
238
);
}
// .right-top-item:nth-child(odd) {
// background-color: rgb(247, 248, 249);
// border-top: 1px solid rgb(234, 236, 238);
...
...
@@ -933,6 +1001,7 @@ onMounted(async () => {
top
:
16px
;
left
:
24px
;
}
.right-top-item
.name
{
display
:
inline-block
;
width
:
902px
;
...
...
@@ -943,6 +1012,7 @@ onMounted(async () => {
color
:
rgb
(
59
,
65
,
75
);
margin-left
:
64px
;
}
.right-top-item
img
{
width
:
16px
;
height
:
31px
;
...
...
@@ -952,6 +1022,7 @@ onMounted(async () => {
cursor
:
pointer
;
}
}
.btn
{
padding
:
2px
8px
;
font-size
:
16px
;
...
...
@@ -966,20 +1037,24 @@ onMounted(async () => {
position
:
absolute
;
z-index
:
100
;
}
.cl1
{
top
:
14px
;
right
:
107px
;
}
.cl2
{
top
:
14px
;
right
:
19px
;
}
.active
{
color
:
rgb
(
5
,
95
,
194
);
background-color
:
rgba
(
246
,
250
,
255
,
1
);
border-color
:
rgb
(
5
,
95
,
194
);
}
}
.right-bottom
{
width
:
1063px
;
height
:
817px
;
...
...
@@ -988,6 +1063,7 @@ onMounted(async () => {
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
position
:
relative
;
margin-bottom
:
16px
;
.right-bottom-title
{
font-size
:
20px
;
font-weight
:
700
;
...
...
@@ -998,6 +1074,7 @@ onMounted(async () => {
top
:
14px
;
left
:
22px
;
}
.img1
{
width
:
8px
;
height
:
20px
;
...
...
@@ -1005,6 +1082,7 @@ onMounted(async () => {
left
:
0px
;
top
:
18px
;
}
.img2
{
width
:
28px
;
height
:
28px
;
...
...
@@ -1013,6 +1091,7 @@ onMounted(async () => {
right
:
12px
;
cursor
:
pointer
;
}
.btn
{
padding
:
2px
8px
;
font-size
:
16px
;
...
...
@@ -1027,19 +1106,23 @@ onMounted(async () => {
position
:
absolute
;
z-index
:
100
;
}
.cl1
{
top
:
14px
;
right
:
107px
;
}
.cl2
{
top
:
14px
;
right
:
19px
;
}
.active
{
color
:
rgb
(
5
,
95
,
194
);
background-color
:
rgba
(
246
,
250
,
255
,
1
);
border-color
:
rgb
(
5
,
95
,
194
);
}
.right-bottom-content1
{
width
:
1022px
;
height
:
auto
;
...
...
@@ -1047,6 +1130,7 @@ onMounted(async () => {
// top: 60px;
// left: 22px;
margin-bottom
:
16px
;
.right-bottom-content1-title
{
width
:
1022px
;
height
:
55px
;
...
...
@@ -1057,6 +1141,7 @@ onMounted(async () => {
background-color
:
rgb
(
247
,
248
,
249
);
border-top
:
1px
solid
rgb
(
234
,
236
,
238
);
border-bottom
:
1px
solid
rgb
(
234
,
236
,
238
);
span
{
font-size
:
18px
;
font-weight
:
700
;
...
...
@@ -1064,6 +1149,7 @@ onMounted(async () => {
line-height
:
24px
;
color
:
rgb
(
59
,
65
,
75
);
}
img
{
width
:
16px
;
height
:
31px
;
...
...
@@ -1073,6 +1159,7 @@ onMounted(async () => {
cursor
:
pointer
;
}
}
.right-bottom-content1-content
{
width
:
1022px
;
// height: 144px;
...
...
@@ -1085,6 +1172,7 @@ onMounted(async () => {
border-bottom
:
1px
solid
rgb
(
234
,
236
,
238
);
}
}
.right-bottom-content2
{
width
:
1022px
;
height
:
229px
;
...
...
@@ -1092,6 +1180,7 @@ onMounted(async () => {
top
:
283px
;
left
:
22px
;
margin-bottom
:
24px
;
.right-bottom-content2-title
{
width
:
1022px
;
height
:
55px
;
...
...
@@ -1102,6 +1191,7 @@ onMounted(async () => {
background-color
:
rgb
(
247
,
248
,
249
);
border-top
:
1px
solid
rgb
(
234
,
236
,
238
);
border-bottom
:
1px
solid
rgb
(
234
,
236
,
238
);
span
{
font-size
:
18px
;
font-weight
:
700
;
...
...
@@ -1109,6 +1199,7 @@ onMounted(async () => {
line-height
:
24px
;
color
:
rgb
(
59
,
65
,
75
);
}
img
{
width
:
16px
;
height
:
31px
;
...
...
@@ -1118,6 +1209,7 @@ onMounted(async () => {
cursor
:
pointer
;
}
}
.right-bottom-content2-content
{
width
:
1022px
;
height
:
174px
;
...
...
@@ -1130,6 +1222,7 @@ onMounted(async () => {
border-bottom
:
1px
solid
rgb
(
234
,
236
,
238
);
}
}
.right-bottom-content3
{
width
:
1022px
;
height
:
169px
;
...
...
@@ -1137,6 +1230,7 @@ onMounted(async () => {
top
:
536px
;
left
:
22px
;
margin-bottom
:
24px
;
.right-bottom-content3-title
{
width
:
1022px
;
height
:
55px
;
...
...
@@ -1147,6 +1241,7 @@ onMounted(async () => {
background-color
:
rgb
(
247
,
248
,
249
);
border-top
:
1px
solid
rgb
(
234
,
236
,
238
);
border-bottom
:
1px
solid
rgb
(
234
,
236
,
238
);
span
{
font-size
:
18px
;
font-weight
:
700
;
...
...
@@ -1154,6 +1249,7 @@ onMounted(async () => {
line-height
:
24px
;
color
:
rgb
(
59
,
65
,
75
);
}
img
{
width
:
16px
;
height
:
31px
;
...
...
@@ -1163,6 +1259,7 @@ onMounted(async () => {
cursor
:
pointer
;
}
}
.right-bottom-content3-content
{
width
:
1022px
;
height
:
114px
;
...
...
@@ -1176,6 +1273,7 @@ onMounted(async () => {
}
}
}
.right-top-b
{
margin-bottom
:
50px
;
width
:
1063px
;
...
...
@@ -1185,6 +1283,7 @@ onMounted(async () => {
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
position
:
relative
;
padding
:
60px
19px
28px
22px
;
.right-top-title
{
font-size
:
20px
;
font-weight
:
700
;
...
...
@@ -1195,6 +1294,7 @@ onMounted(async () => {
top
:
14px
;
left
:
22px
;
}
.img1
{
width
:
8px
;
height
:
20px
;
...
...
@@ -1202,11 +1302,13 @@ onMounted(async () => {
left
:
0px
;
top
:
18px
;
}
.right-top-content
{
width
:
1022px
;
height
:
421px
;
overflow-y
:
auto
;
overflow-x
:
hidden
;
overflow-y
:
auto
;
overflow-x
:
hidden
;
.right-top-item
{
width
:
1022px
;
height
:
104px
;
...
...
@@ -1214,6 +1316,7 @@ onMounted(async () => {
border-top
:
1px
solid
rgb
(
234
,
236
,
238
);
padding
:
12px
0
;
position
:
relative
;
img
{
width
:
24px
;
height
:
24px
;
...
...
@@ -1221,6 +1324,7 @@ onMounted(async () => {
left
:
26px
;
top
:
12px
;
}
.type
{
position
:
absolute
;
right
:
48px
;
...
...
@@ -1232,14 +1336,17 @@ onMounted(async () => {
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
}
.type1
{
background-color
:
rgba
(
232
,
189
,
11
,
0
.1
);
color
:
rgb
(
232
,
189
,
11
);
}
.type2
{
background-color
:
rgba
(
231
,
243
,
255
,
1
);
color
:
rgb
(
5
,
95
,
194
);
}
.name
{
font-size
:
16px
;
font-weight
:
700
;
...
...
@@ -1249,6 +1356,7 @@ onMounted(async () => {
margin-left
:
65px
;
margin-bottom
:
4px
;
}
.time
{
font-size
:
16px
;
font-weight
:
400
;
...
...
@@ -1257,6 +1365,7 @@ onMounted(async () => {
color
:
rgb
(
95
,
101
,
108
);
margin-left
:
65px
;
}
.content
{
font-size
:
16px
;
font-weight
:
400
;
...
...
src/views/thinkTank/index.vue
浏览文件 @
0204674d
...
...
@@ -14,7 +14,7 @@
<div
class=
"home-main-header-center"
>
<SearchContainer
class=
"think-tank-search"
style=
"margin-bottom: 0; margin-top: 51px; height: fit-content;"
v-if=
"containerRef"
placeholder=
"搜索智库、报告或政策建议"
:containerRef=
"containerRef"
areaName=
"智库"
/>
v-if=
"containerRef"
placeholder=
"搜索智库、报告或政策建议"
:containerRef=
"containerRef"
areaName=
"智库
报告
"
/>
<!--
<el-input
v-model=
"searchThinktankText"
@
keyup
.
enter=
"handleSearch"
style=
"width: 838px; height: 100%"
placeholder=
"搜索智库报告"
/>
<div
class=
"search"
>
...
...
src/views/viewRiskSignal/assets/images/danger.svg
0 → 100644
浏览文件 @
0204674d
<svg
viewBox=
"0 0 15.0039 14.5"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"15.003906"
height=
"14.500000"
fill=
"none"
customFrame=
"#000000"
>
<rect
id=
"容器 239"
width=
"14.000000"
height=
"14.000000"
x=
"0.501953"
y=
"0.500000"
/>
<path
id=
"矢量 467"
d=
"M0.501953 4.81104L4.27116 2.65573L8.0404 4.81118L14.502 0.5"
stroke=
"rgb(255,255,255)"
stroke-linecap=
"round"
stroke-linejoin=
"round"
stroke-width=
"1.000000"
/>
<path
id=
"矢量 468"
d=
"M4.27118 6.96812L0.501953 9.12357L0.50198 14.5015L14.502 14.5013L14.502 4.8125L8.04045 9.12354L4.27118 6.96812Z"
fill=
"rgb(255,255,255)"
fill-rule=
"evenodd"
/>
</svg>
src/views/viewRiskSignal/assets/images/warning.svg
0 → 100644
浏览文件 @
0204674d
<svg
viewBox=
"0 0 26.1548 23.3789"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"26.154785"
height=
"23.378906"
fill=
"none"
customFrame=
"#000000"
>
<defs>
<linearGradient
id=
"paint_linear_0"
x1=
"12.260066"
x2=
"21.2057495"
y1=
"1.21773767"
y2=
"18.4094753"
gradientUnits=
"userSpaceOnUse"
>
<stop
stop-color=
"rgb(206,79,81)"
offset=
"0"
stop-opacity=
"1"
/>
<stop
stop-color=
"rgb(240,202,202)"
offset=
"1"
stop-opacity=
"1"
/>
</linearGradient>
</defs>
<path
id=
"减去顶层"
d=
"M25.8883 20.3883L14.8139 1.00773C14.0461 -0.335911 12.1087 -0.335911 11.3409 1.00773L0.266462 20.3883C-0.495419 21.7216 0.467316 23.3806 2.00295 23.3806L24.1519 23.3806C25.6875 23.3806 26.6502 21.7216 25.8883 20.3883ZM14.2931 14.8346C14.2711 15.4323 13.7802 15.9054 13.1821 15.9054C12.5832 15.9054 12.0919 15.4311 12.0709 14.8326L11.8462 8.42741C11.8196 7.66793 12.428 7.03775 13.188 7.03775C13.9489 7.03775 14.5578 7.66948 14.5297 8.42989L14.2931 14.8346ZM11.7811 18.0226C11.8557 17.8691 11.9621 17.7314 12.1004 17.6094C12.1956 17.5255 12.2977 17.4548 12.4066 17.3975C12.6412 17.2741 12.9075 17.2124 13.2057 17.2124C13.5225 17.2124 13.8007 17.2811 14.0405 17.4184C14.1353 17.4727 14.2241 17.5378 14.3068 17.6136C14.442 17.7374 14.5458 17.8762 14.6184 18.0301C14.7027 18.2087 14.7448 18.4077 14.7448 18.6269C14.7448 18.8242 14.7098 19.0065 14.6397 19.1738C14.5688 19.3433 14.4619 19.4974 14.3191 19.6361C14.1832 19.7681 14.0342 19.8685 13.8721 19.9373C13.6955 20.0122 13.5034 20.0497 13.2957 20.0497C12.8581 20.0497 12.4982 19.945 12.216 19.7355C12.2122 19.7327 12.2085 19.7299 12.2047 19.7271C12.1672 19.6986 12.131 19.6683 12.0963 19.6361C11.9352 19.4868 11.8178 19.3197 11.7439 19.1349C11.6814 18.9783 11.6501 18.809 11.6501 18.6269C11.6501 18.4038 11.6938 18.2024 11.7811 18.0226Z"
fill=
"url(#paint_linear_0)"
fill-rule=
"evenodd"
/>
</svg>
src/views/viewRiskSignal/index.vue
浏览文件 @
0204674d
...
...
@@ -5,11 +5,11 @@
<div
class=
"center-center"
>
<div
class=
"center-header"
>
<div
class=
"center-header-left"
>
<img
class=
"iconstyle"
src=
"./assets/images/warning.
pn
g"
/>
<img
class=
"iconstyle"
src=
"./assets/images/warning.
sv
g"
/>
<div
class=
"center-header-title"
>
风险信号管理
</div>
</div>
<div
class=
"center-header-right"
>
<img
class=
"img"
src=
"./assets/images/danger.
pn
g"
/>
<img
class=
"img"
src=
"./assets/images/danger.
sv
g"
/>
<div
class=
"text"
>
风险统计
</div>
</div>
</div>
...
...
@@ -22,7 +22,7 @@
<div
class=
"text1"
>
本年新增风险
</div>
</div>
<div
class=
"text2"
style=
"color: rgba(95, 101, 108, 1)"
>
{{
basicInfo
.
yearAdded
+
" 项"
}}
<span
class=
"text2-inner"
>
{{
basicInfo
.
yearAdded
+
" 项"
}}
</span>
</div>
</div>
<div
class=
"item"
>
...
...
@@ -31,7 +31,7 @@
<div
class=
"text1"
>
本月新增风险
</div>
</div>
<div
class=
"text2"
style=
"color: rgba(95, 101, 108, 1)"
>
{{
basicInfo
.
monthAdded
+
" 项"
}}
<span
class=
"text2-inner"
>
{{
basicInfo
.
monthAdded
+
" 项"
}}
</span>
</div>
</div>
</div>
...
...
@@ -41,7 +41,8 @@
<div
class=
"dot"
style=
"background-color: rgba(5, 95, 194, 1)"
></div>
<div
class=
"text1"
>
已处理风险
</div>
</div>
<div
class=
"text2"
style=
"color: rgba(5, 95, 194, 1)"
>
{{
basicInfo
.
dealCount
+
" 项"
}}
</div>
<div
class=
"text2"
style=
"color: rgba(5, 95, 194, 1)"
><span
class=
"text2-inner"
>
{{
basicInfo
.
dealCount
+
" 项"
}}
</span></div>
</div>
<div
class=
"item"
>
<div
class=
"top"
>
...
...
@@ -49,7 +50,7 @@
<div
class=
"text1"
>
待处理风险
</div>
</div>
<div
class=
"text2"
style=
"color: rgba(206, 79, 81, 1)"
>
{{
basicInfo
.
pendingCount
+
" 项"
}}
<span
class=
"text2-inner"
>
{{
basicInfo
.
pendingCount
+
" 项"
}}
</span>
</div>
</div>
</div>
...
...
@@ -125,7 +126,7 @@
<div
class=
"title"
>
{{
"风险类型"
}}
</div>
</div>
<div
class=
"select-main"
>
<el-checkbox-group
class=
"checkbox-group"
:model-value=
"selectedRiskTypeModel"
<el-checkbox-group
class=
"checkbox-group
risk-type-checkbox-group
"
:model-value=
"selectedRiskTypeModel"
@
change=
"handleRiskTypeGroupChange"
>
<el-checkbox
class=
"filter-checkbox all-checkbox"
:label=
"RISK_FILTER_ALL_TYPE"
>
{{
RISK_FILTER_ALL_TYPE
}}
...
...
@@ -188,35 +189,43 @@
</div>
</div>
</div>
<div
class=
"right-main"
>
<div
class=
"itemlist itemlist--clickable"
v-for=
"(val, idx) in riskList"
:key=
"val.rowKey"
@
click=
"handleOpenRiskDetail(val)"
>
<div
class=
"box-title"
>
<div
class=
"risktitle"
v-html=
"highlightRiskText(val.title)"
/>
<div
class=
"risktype"
:class=
"'risktype--' + getRiskListItemLevelKey(val.risktype)"
>
<div
class=
"icon"
:class=
"'icon--' + getRiskListItemLevelKey(val.risktype)"
/>
<div
class=
"text"
>
{{ getRiskListItemLevelLabel(val.risktype) }}
</div>
<
template
v-if=
"riskList && riskList.length"
>
<div
class=
"right-main"
>
<div
class=
"itemlist itemlist--clickable"
v-for=
"(val, idx) in riskList"
:key=
"val.rowKey"
@
click=
"handleOpenRiskDetail(val)"
>
<div
class=
"box-title"
>
<div
class=
"risktitle"
v-html=
"highlightRiskText(val.title)"
/>
<div
v-if=
"!isRiskLevelNoData(val.risktype)"
class=
"risktype"
:class=
"'risktype--' + getRiskListItemLevelKey(val.risktype)"
>
<div
class=
"icon"
:class=
"'icon--' + getRiskListItemLevelKey(val.risktype)"
/>
<div
class=
"text"
>
{{
getRiskListItemLevelLabel
(
val
.
risktype
)
}}
</div>
</div>
</div>
<div
class=
"box-source"
>
<img
class=
"source-pic"
:src=
"val.pic || DefaultIcon2"
alt=
""
/>
<div
class=
"source-text"
>
{{
formatRiskSourceLine
(
val
)
}}
</div>
</div>
<div
class=
"desc-box"
v-html=
"highlightRiskText(val.dsc)"
/>
<div
class=
"tag-box"
v-if=
"val.tag.length"
>
<AreaTag
v-for=
"(tag, index) in val.tag"
:key=
"index"
:tagName=
"tag"
>
{{
tag
}}
</AreaTag>
</div>
</div>
<div
class=
"box-source"
>
<img
class=
"source-pic"
:src=
"val.pic || DefaultIcon2"
alt=
""
/>
<div
class=
"source-text"
>
{{ formatRiskSourceLine(val) }}
</div>
</div>
<div
class=
"right-footer"
>
<div
class=
"footer-left"
>
{{
`共 ${totalNum
}
项调查`
}}
<
/div
>
<div
class=
"
desc-box"
v-html=
"highlightRiskText(val.dsc)"
/
>
<div
class=
"tag-box"
v-if=
"val.tag.length"
>
<AreaTag
v-for=
"(tag, index) in val.tag"
:key=
"index"
:tagName=
"tag"
>
{{ tag }}
</AreaTag
>
<
div
class
=
"
footer-right"
>
<
el
-
pagination
@
current
-
change
=
"handleCurrentChange"
:
pageSize
=
"pageSize"
:
current
-
page
=
"currentPage"
:
total
=
"totalNum"
background
layout
=
"prev, pager, next"
/
>
<
/div
>
<
/div
>
</div>
<div
class=
"right-footer"
>
<div
class=
"footer-left"
>
{{ `共 ${totalNum} 项调查` }}
</div>
<div
class=
"footer-right"
>
<el-pagination
@
current-change=
"handleCurrentChange"
:pageSize=
"pageSize"
:current-page=
"currentPage"
:total=
"totalNum"
background
layout=
"prev, pager, next"
/>
<
/template
>
<
template
v
-
else
>
<
div
class
=
"right-empty"
>
<
el
-
empty
class
=
"right-el-empty"
description
=
"暂无数据"
:
image
-
size
=
"100"
/>
<
/div
>
</
div
>
<
/
template
>
<
/div
>
<
/div
>
<
/div
>
...
...
@@ -606,6 +615,11 @@ const getRiskListItemLevelLabel = (level) => {
return
t
;
}
;
const
isRiskLevelNoData
=
(
level
)
=>
{
const
t
=
String
(
level
??
""
).
trim
();
return
!
t
||
t
===
"暂无数值"
||
t
===
"暂无数据"
;
}
;
const
route
=
useRoute
();
const
router
=
useRouter
();
...
...
@@ -935,6 +949,15 @@ onMounted(async () => {
vertical
-
align
:
middle
;
}
.
risk
-
type
-
checkbox
-
group
:
deep
(.
el
-
checkbox__label
)
{
display
:
inline
-
block
;
max
-
width
:
8
em
;
overflow
:
hidden
;
text
-
overflow
:
ellipsis
;
white
-
space
:
nowrap
;
vertical
-
align
:
middle
;
}
.
home
-
wrapper
{
width
:
100
%
;
height
:
100
%
;
...
...
@@ -997,8 +1020,8 @@ onMounted(async () => {
cursor
:
pointer
;
.
img
{
width
:
1
6
px
;
height
:
1
5
px
;
width
:
1
4
px
;
height
:
1
4
px
;
}
.
text
{
...
...
@@ -1051,6 +1074,7 @@ onMounted(async () => {
line
-
height
:
24
px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
text
-
align
:
right
;
white
-
space
:
nowrap
;
}
}
...
...
@@ -1061,6 +1085,14 @@ onMounted(async () => {
text
-
align
:
right
;
/* 强制不换行 */
white
-
space
:
nowrap
;
// 让右边界固定在块内,超长只会向左溢出(且不省略、完整显示)
width
:
100
%
;
direction
:
rtl
;
}
.
text2
-
inner
{
direction
:
ltr
;
unicode
-
bidi
:
isolate
;
}
}
}
...
...
@@ -1188,6 +1220,8 @@ onMounted(async () => {
margin
-
bottom
:
24
px
;
width
:
1224
px
;
position
:
relative
;
display
:
flex
;
flex
-
direction
:
column
;
border
-
radius
:
10
px
;
box
-
shadow
:
0
px
0
px
15
px
0
px
rgba
(
60
,
87
,
126
,
0.2
);
...
...
@@ -1277,6 +1311,7 @@ onMounted(async () => {
.
right
-
main
{
width
:
1224
px
;
flex
:
1
;
padding
-
left
:
24
px
;
padding
-
top
:
6
px
;
...
...
@@ -1451,6 +1486,24 @@ onMounted(async () => {
margin
-
right
:
58
px
;
}
}
.
right
-
empty
{
flex
:
1
;
min
-
height
:
520
px
;
display
:
flex
;
align
-
items
:
center
;
justify
-
content
:
center
;
padding
:
24
px
;
:
deep
(.
el
-
empty__image
)
{
margin
-
bottom
:
0
;
}
.
right
-
el
-
empty
{
padding
:
0
;
margin
:
0
;
}
}
}
}
}
...
...
@@ -1839,7 +1892,7 @@ onMounted(async () => {
.
risk
-
signal
-
detail
-
dialog
.
risk
-
signal
-
detail
-
dialog__header
-
badge
-
close
{
position
:
absolute
;
right
:
115
px
;
right
:
61
px
;
top
:
50
%
;
transform
:
translateY
(
-
50
%
);
width
:
16
px
;
...
...
@@ -1864,7 +1917,7 @@ onMounted(async () => {
.
risk
-
signal
-
detail
-
dialog
.
risk
-
signal
-
detail
-
dialog__read
-
indicator
{
position
:
absolute
;
right
:
115
px
;
right
:
61
px
;
top
:
50
%
;
transform
:
translateY
(
-
50
%
);
display
:
inline
-
flex
;
...
...
src/views/viewRiskSignal/utils/cleandarHeat.js
浏览文件 @
0204674d
...
...
@@ -206,7 +206,7 @@ const getCalendarHeatChart = (rawData) => {
return
""
;
}
const
v
=
p
.
data
?.[
3
]
??
0
;
return
`
${
dateStr
}
<br/>
数值
:
${
v
}
`
;
return
`
${
dateStr
}
<br/>
风险数量
:
${
v
}
`
;
}
}
};
...
...
vite.config.js
浏览文件 @
0204674d
...
...
@@ -19,14 +19,8 @@ export default defineConfig({
resolvers
:
[
ElementPlusResolver
()],
}),
],
build
:
{
// minify: 'terser',
terserOptions
:
{
compress
:
{
drop_console
:
true
,
// 移除所有 console.*
drop_debugger
:
true
,
// 移除 debugger
},
},
esbuild
:
{
drop
:
process
.
env
.
NODE_ENV
===
'production'
?
[
'console'
,
'debugger'
]
:
[]
// 正式环境去除掉console
},
resolve
:
{
alias
:
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论