Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
8fb13448
提交
8fb13448
authored
3月 24, 2026
作者:
张伊明
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix 修复bug#20 #21
上级
f9cc4c39
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
722 行增加
和
246 行删除
+722
-246
influence.js
src/api/influence.js
+5
-3
index.vue
src/views/bill/deepDig/processAnalysis/index.vue
+204
-24
boxplot.js
src/views/bill/deepDig/processAnalysis/utils/boxplot.js
+32
-2
index.vue
src/views/bill/influence/industry/index.vue
+447
-211
index.vue
src/views/bill/introdoction/index.vue
+34
-6
没有找到文件。
src/api/influence.js
浏览文件 @
8fb13448
import
request
from
"@/api/request.js"
;
//
根据行业领域id获取公司列表
//
获取实体列表(按行业/公司名筛选)
/**
* @param {id}
* @param {Object} params
* @param {string} [params.id] - 行业领域id(全部领域不传)
* @param {string} [params.companyName] - 公司名称(搜索框为空不传)
*/
export
function
getCompanyList
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/billImpactAnalysis/industry/company
/
${
params
.
id
}
`
,
url
:
`/api/billImpactAnalysis/industry/company`
,
params
,
})
}
...
...
src/views/bill/deepDig/processAnalysis/index.vue
浏览文件 @
8fb13448
...
...
@@ -32,19 +32,28 @@
</div>
</div>
-->
<AnalysisBox
title=
"典型阶段耗时"
>
<div
class=
"box1-main"
:class=
"
{ 'box1-main--full': !timeFooterText }">
<div
class=
"box1-main-center"
id=
"chart1"
></div>
<div
v-if=
"timeFooterText"
class=
"box1-main-footer"
>
<div
class=
"box-footer-left"
>
<img
src=
"@/assets/icons/box-footer-left-icon.png"
alt=
""
/>
</div>
<div
class=
"box-footer-center"
>
{{
timeFooterText
}}
</div>
<div
class=
"box-footer-right"
>
<img
src=
"../assets/icons/arrow-right.png"
alt=
""
/>
<div
class=
"analysis-ai-wrapper analysis-ai-wrapper--box1"
>
<div
class=
"box1-main"
:class=
"
{ 'box1-main--full': !timeFooterText }">
<div
class=
"box1-main-center"
id=
"chart1"
></div>
<div
v-if=
"timeFooterText"
class=
"box1-main-footer"
>
<div
class=
"box-footer-left"
>
<img
src=
"@/assets/icons/box-footer-left-icon.png"
alt=
""
/>
</div>
<div
class=
"box-footer-center"
>
{{
timeFooterText
}}
</div>
<div
class=
"box-footer-right"
>
<img
src=
"../assets/icons/arrow-right.png"
alt=
""
/>
</div>
</div>
</div>
<div
v-if=
"!aiPaneVisible.box1"
class=
"analysis-ai-tip-row"
>
<TipTab
class=
"analysis-ai-tip"
/>
<AiButton
class=
"analysis-ai-tip-action"
@
mouseenter=
"handleShowAiPane('box1')"
/>
</div>
<div
v-if=
"aiPaneVisible.box1"
class=
"analysis-ai-pane"
@
mouseleave=
"handleHideAiPane('box1')"
>
<AiPane
:aiContent=
"overviewAiContent.box1"
/>
</div>
</div>
</AnalysisBox>
</div>
...
...
@@ -80,19 +89,28 @@
</div>
</div>
-->
<AnalysisBox
title=
"修正案次数分析"
>
<div
class=
"box2-main"
:class=
"
{ 'box2-main--full': !amendFooterText }">
<div
class=
"box2-main-center"
id=
"chart2"
></div>
<div
v-if=
"amendFooterText"
class=
"box2-main-footer"
>
<div
class=
"box-footer-left"
>
<img
src=
"@/assets/icons/box-footer-left-icon.png"
alt=
""
/>
</div>
<div
class=
"box-footer-center"
>
{{
amendFooterText
}}
</div>
<div
class=
"box-footer-right"
>
<img
src=
"../assets/icons/arrow-right.png"
alt=
""
/>
<div
class=
"analysis-ai-wrapper analysis-ai-wrapper--box2"
>
<div
class=
"box2-main"
:class=
"
{ 'box2-main--full': !amendFooterText }">
<div
class=
"box2-main-center"
id=
"chart2"
></div>
<div
v-if=
"amendFooterText"
class=
"box2-main-footer"
>
<div
class=
"box-footer-left"
>
<img
src=
"@/assets/icons/box-footer-left-icon.png"
alt=
""
/>
</div>
<div
class=
"box-footer-center"
>
{{
amendFooterText
}}
</div>
<div
class=
"box-footer-right"
>
<img
src=
"../assets/icons/arrow-right.png"
alt=
""
/>
</div>
</div>
</div>
<div
v-if=
"!aiPaneVisible.box2"
class=
"analysis-ai-tip-row"
>
<TipTab
class=
"analysis-ai-tip"
/>
<AiButton
class=
"analysis-ai-tip-action"
@
mouseenter=
"handleShowAiPane('box2')"
/>
</div>
<div
v-if=
"aiPaneVisible.box2"
class=
"analysis-ai-pane"
@
mouseleave=
"handleHideAiPane('box2')"
>
<AiPane
:aiContent=
"overviewAiContent.box2"
/>
</div>
</div>
</AnalysisBox>
</div>
...
...
@@ -366,7 +384,8 @@
<
/div
>
<
/div> --
>
<
AnalysisBox
title
=
"投票分析"
>
<
div
class
=
"vote-legend"
>
<
div
class
=
"analysis-ai-wrapper analysis-ai-wrapper--box3"
>
<
div
class
=
"vote-legend"
>
<
div
class
=
"vote-legend-item"
>
<
span
class
=
"vote-legend-dot agree"
><
/span
>
<
span
>
赞成票
<
/span
>
...
...
@@ -375,7 +394,7 @@
<
span
class
=
"vote-legend-dot against"
><
/span
>
<
span
>
反对票
<
/span
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"box3-main"
:
class
=
"{ 'box3-main--full': !voteFooterText
}
"
>
<
div
class
=
"box3-main-center"
>
<
div
class
=
"box3-main-center-header"
>
...
...
@@ -678,7 +697,15 @@
<
img
src
=
"../assets/icons/arrow-right.png"
alt
=
""
/>
<
/div
>
<
/div
>
<
div
v
-
if
=
"!aiPaneVisible.box3"
class
=
"analysis-ai-tip-row"
>
<
TipTab
class
=
"analysis-ai-tip"
/>
<
AiButton
class
=
"analysis-ai-tip-action"
@
mouseenter
=
"handleShowAiPane('box3')"
/>
<
/div
>
<
div
v
-
if
=
"aiPaneVisible.box3"
class
=
"analysis-ai-pane"
@
mouseleave
=
"handleHideAiPane('box3')"
>
<
AiPane
:
aiContent
=
"overviewAiContent.box3"
/>
<
/div
>
<
/div
>
<
/div
>
<
/AnalysisBox
>
<
/div
>
<
/div
>
...
...
@@ -690,6 +717,10 @@ import { ref, onMounted } from "vue";
import
{
getBillTimeAnalyze
,
getBillAmeAnalyzeCount
,
getBillTp
}
from
"@/api/deepdig"
;
import
getBoxPlotChcart
from
"./utils/boxplot"
;
import
*
as
echarts
from
"echarts"
;
import
{
getChartAnalysis
}
from
"@/api/aiAnalysis/index"
;
import
TipTab
from
"@/components/base/TipTab/index.vue"
;
import
AiButton
from
"@/components/base/Ai/AiButton/index.vue"
;
import
AiPane
from
"@/components/base/Ai/AiPane/index.vue"
;
import
icon1
from
"./assets/images/icon1.png"
;
import
icon2
from
"./assets/images/icon2.png"
;
...
...
@@ -895,6 +926,31 @@ const timeFooterText = ref("");
const
amendFooterText
=
ref
(
""
);
const
voteFooterText
=
ref
(
""
);
// AI面板显示状态(box1=典型阶段耗时,box2=修正案次数分析,box3=投票分析)
const
aiPaneVisible
=
ref
({
box1
:
false
,
box2
:
false
,
box3
:
false
}
);
const
overviewAiContent
=
ref
({
box1
:
"智能总结生成中..."
,
box2
:
"智能总结生成中..."
,
box3
:
"智能总结生成中..."
}
);
const
aiPaneFetched
=
ref
({
box1
:
false
,
box2
:
false
,
box3
:
false
}
);
const
aiPaneLoading
=
ref
({
box1
:
false
,
box2
:
false
,
box3
:
false
}
);
// 绘制echarts图表
const
setChart
=
(
option
,
chartId
)
=>
{
let
chartDom
=
document
.
getElementById
(
chartId
);
...
...
@@ -991,6 +1047,96 @@ const handleGetBillVoteAnalyze = async () => {
}
}
;
const
buildAiChartPayload
=
key
=>
{
if
(
key
===
"box1"
)
{
return
{
type
:
"箱线图"
,
name
:
"典型阶段耗时"
,
data
:
{
categories
:
Array
.
isArray
(
chartData1
.
value
?.
dataX
)
?
chartData1
.
value
.
dataX
:
[],
samples
:
Array
.
isArray
(
chartData1
.
value
?.
dataY
)
?
chartData1
.
value
.
dataY
:
[]
}
}
;
}
if
(
key
===
"box2"
)
{
return
{
type
:
"箱线图"
,
name
:
"修正案次数分析"
,
data
:
{
categories
:
Array
.
isArray
(
chartData2
.
value
?.
dataX
)
?
chartData2
.
value
.
dataX
:
[],
samples
:
Array
.
isArray
(
chartData2
.
value
?.
dataY
)
?
chartData2
.
value
.
dataY
:
[]
}
}
;
}
if
(
key
===
"box3"
)
{
return
{
type
:
"投票分析"
,
name
:
"投票分析"
,
data
:
Array
.
isArray
(
voteAnalysisList
.
value
)
?
voteAnalysisList
.
value
:
[]
}
;
}
return
{
type
:
""
,
name
:
""
,
data
:
[]
}
;
}
;
const
requestAiPaneContent
=
async
key
=>
{
if
(
!
key
||
aiPaneLoading
.
value
[
key
]
||
aiPaneFetched
.
value
[
key
])
return
;
aiPaneLoading
.
value
=
{
...
aiPaneLoading
.
value
,
[
key
]:
true
}
;
overviewAiContent
.
value
=
{
...
overviewAiContent
.
value
,
[
key
]:
"智能总结生成中..."
}
;
try
{
const
payload
=
buildAiChartPayload
(
key
);
const
res
=
await
getChartAnalysis
(
{
text
:
JSON
.
stringify
(
payload
)
}
,
{
onChunk
:
chunk
=>
{
const
current
=
overviewAiContent
.
value
[
key
];
const
base
=
current
===
"智能总结生成中..."
?
""
:
current
;
overviewAiContent
.
value
=
{
...
overviewAiContent
.
value
,
[
key
]:
base
+
chunk
}
;
}
}
);
const
list
=
res
?.
data
;
const
first
=
Array
.
isArray
(
list
)
?
list
[
0
]
:
null
;
const
interpretation
=
first
?.
解读
||
first
?.[
"解读"
];
if
(
interpretation
)
{
overviewAiContent
.
value
=
{
...
overviewAiContent
.
value
,
[
key
]:
interpretation
}
;
}
aiPaneFetched
.
value
=
{
...
aiPaneFetched
.
value
,
[
key
]:
true
}
;
}
catch
(
error
)
{
console
.
error
(
"获取图表解读失败"
,
error
);
overviewAiContent
.
value
=
{
...
overviewAiContent
.
value
,
[
key
]:
"智能总结生成失败"
}
;
}
finally
{
aiPaneLoading
.
value
=
{
...
aiPaneLoading
.
value
,
[
key
]:
false
}
;
}
}
;
const
handleShowAiPane
=
key
=>
{
aiPaneVisible
.
value
=
{
...
aiPaneVisible
.
value
,
[
key
]:
true
}
;
requestAiPaneContent
(
key
);
}
;
const
handleHideAiPane
=
key
=>
{
aiPaneVisible
.
value
=
{
...
aiPaneVisible
.
value
,
[
key
]:
false
}
;
}
;
onMounted
(
async
()
=>
{
await
handleGetBillTimeAnalyze
();
await
handleGetBillAmeAnalyzeCount
();
...
...
@@ -1916,4 +2062,38 @@ onMounted(async () => {
width
:
200
px
;
margin
-
left
:
10
px
;
}
.
analysis
-
ai
-
wrapper
{
position
:
relative
;
height
:
100
%
;
}
.
analysis
-
ai
-
tip
-
row
{
position
:
absolute
;
left
:
0
;
bottom
:
15
px
;
width
:
100
%
;
display
:
flex
;
align
-
items
:
center
;
justify
-
content
:
center
;
z
-
index
:
2
;
}
.
analysis
-
ai
-
tip
-
action
{
position
:
absolute
;
right
:
0
px
;
}
.
analysis
-
ai
-
pane
{
position
:
absolute
;
left
:
0
;
bottom
:
0
;
width
:
100
%
;
z
-
index
:
5
;
pointer
-
events
:
none
;
:
deep
(.
ai
-
pane
-
wrapper
)
{
pointer
-
events
:
auto
;
}
}
<
/style
>
src/views/bill/deepDig/processAnalysis/utils/boxplot.js
浏览文件 @
8fb13448
const
resolveCssVarColor
=
(
varName
,
fallback
)
=>
{
try
{
if
(
typeof
window
===
'undefined'
||
typeof
document
===
'undefined'
)
return
fallback
const
value
=
window
.
getComputedStyle
(
document
.
documentElement
).
getPropertyValue
(
varName
)
const
trimmed
=
value
?
value
.
trim
()
:
''
return
trimmed
||
fallback
}
catch
(
e
)
{
return
fallback
}
}
const
getBoxPlotChcart
=
(
data
,
unit
,
labelConfig
=
{})
=>
{
const
primary2
=
resolveCssVarColor
(
'--color-primary-2'
,
'#F6FAFF'
)
const
labels
=
{
max
:
labelConfig
.
max
||
'最大耗时'
,
q3
:
labelConfig
.
q3
||
'平均耗时大'
,
...
...
@@ -16,6 +29,19 @@ const getBoxPlotChcart = (data, unit, labelConfig = {}) => {
// left: 'center'
// }
// ],
graphic
:
[
{
type
:
'text'
,
// 左上角只标注一次单位(y轴刻度不再逐行带单位)
left
:
'5%'
,
top
:
'0%'
,
style
:
{
text
:
unit
,
fill
:
'rgba(95, 101, 108, 1)'
,
font
:
'14px Microsoft YaHei'
}
}
],
tooltip
:
{
trigger
:
'item'
,
axisPointer
:
{
...
...
@@ -61,10 +87,14 @@ const getBoxPlotChcart = (data, unit, labelConfig = {}) => {
type
:
'value'
,
name
:
''
,
axisLabel
:
{
formatter
:
(
value
)
=>
`
${
value
}
${
unit
}
`
formatter
:
(
value
)
=>
`
${
value
}
`
},
splitArea
:
{
show
:
true
show
:
true
,
// ECharts绘制到canvas,不能直接识别CSS变量字符串;这里取到真实颜色值后再配置交替背景
areaStyle
:
{
color
:
[
primary2
,
'#ffffff'
]
}
}
},
series
:
[
...
...
src/views/bill/influence/industry/index.vue
浏览文件 @
8fb13448
...
...
@@ -4,187 +4,93 @@
<AnalysisBox
title=
"涉及行业"
:showAllBtn=
"false"
width=
"100%"
height=
"100%"
>
<div
class=
"left-main"
>
<div
class=
"left-center"
>
<el-select
v-model=
"curHylyId"
placeholder=
"请选择行业"
class=
"left-center-select"
@
change=
"handleIndustryChange"
>
<el-option
v-for=
"item in industryList"
:key=
"item.id"
:label=
"item.name || item.hylymc"
:value=
"item.id"
/>
<el-select
v-model=
"curHylyId"
placeholder=
"请选择领域"
class=
"left-center-select"
@
change=
"handleIndustryChange"
>
<el-option
v-for=
"item in industryList"
:key=
"item.id"
:label=
"item.name || item.hylymc"
:value=
"item.id"
/>
</el-select>
<el-input
v-model=
"companySearchKeyword"
placeholder=
"搜索实体"
class=
"left-center-search"
:suffix-icon=
"Search"
clearable
/>
<el-input
v-model=
"companySearchKeyword"
placeholder=
"搜索实体"
class=
"left-center-search"
:suffix-icon=
"Search"
clearable
/>
</div>
<div
class=
"left-footer"
>
<div
class=
"item-box"
>
<div
class=
"item"
:class=
"
{ itemActive: companyActiveIndex === idx }"
@click="handleClickCompany(val, idx)" v-for="(val, idx) in curCompanyList" :key="val.id">
<div
class=
"id"
>
{{
(
currentPage
-
1
)
*
pageSize
+
idx
+
1
}}
</div>
<div
class=
"title"
:class=
"
{ titleActive: companyActiveIndex === ((currentPage - 1) * pageSize + idx) }">
{{
val
.
name
}}
</div>
<div
class=
"icon"
>
<img
v-if=
"val.status === 'up'"
:src=
"upIcon"
alt=
""
/>
<img
v-if=
"val.status === 'down'"
:src=
"downIcon"
alt=
""
/>
<div
class=
"left-list"
>
<div
class=
"left-list-title"
>
实体名称
</div>
<div
class=
"left-list-content"
>
<el-empty
v-if=
"!curCompanyList?.length"
style=
"padding: 60px 0;"
description=
"暂无数据"
:image-size=
"100"
/>
<el-scrollbar
v-else
height=
"100%"
always
>
<div
class=
"item-box"
>
<div
class=
"item"
:class=
"
{ itemActive: companyActiveIndex === ((currentPage - 1) * pageSize + idx) }"
@click="handleClickCompany(val, idx)" v-for="(val, idx) in curCompanyList"
:key="val.id">
<div
class=
"item-icon"
>
<img
:src=
"defaultIcon2"
alt=
""
class=
"item-img"
/>
</div>
<div
class=
"title"
:class=
"
{ titleActive: companyActiveIndex === ((currentPage - 1) * pageSize + idx) }">
{{
val
.
name
}}
</div>
<div
class=
"icon"
>
<img
v-if=
"val.status === 'up'"
:src=
"upIcon"
alt=
""
/>
<img
v-if=
"val.status === 'down'"
:src=
"downIcon"
alt=
""
/>
</div>
</div>
</div>
</
div
>
</
el-scrollbar
>
</div>
<div
class=
"footer-box"
>
<div
class=
"left"
>
{{
`共 ${filteredCompanyList.length
}
项`
}}
<
/div
>
<
div
class
=
"right"
>
<
el
-
pagination
@
current
-
change
=
"handleCurrentChange"
:
pageSize
=
"pageSize"
:
current
-
page
=
"currentPage"
size
=
"small"
background
layout
=
"prev, pager, next
"
:
total
=
"filteredCompanyList.length"
/>
<
/div
>
</div
>
<div
class=
"left-pagination"
>
<div
class=
"left-pagination-left"
>
{{
`共 ${filteredCompanyList.length
}
项`
}}
<
/div
>
<
div
class
=
"left-pagination-right"
>
<
el
-
pagination
@
current
-
change
=
"handleCurrentChange"
:
pageSize
=
"pageSize
"
:
current
-
page
=
"currentPage"
size
=
"small"
background
layout
=
"prev, pager, next"
:
total
=
"filteredCompanyList.length"
/
>
<
/div
>
<
/div
>
<
/div
>
<
/AnalysisBox
>
<
/div
>
<
div
class
=
"right"
>
<
AnalysisBox
title
=
"产业链分析"
:
showAllBtn
=
"false"
width
=
"100%"
height
=
"100%"
>
<
div
class
=
"right-main"
>
<
div
class
=
"right-main-content"
id
=
"chartGraph"
>
<
div
class
=
"right-main-content-header"
>
<
div
class
=
"header-item1"
>
<
div
class
=
"header-item1-top"
>
{{
"基础支撑"
}}
<
/div
>
<
div
class
=
"header-item1-bottom"
>
<
div
class
=
"icon"
>
<
img
src
=
"./assets/images/warning.png"
alt
=
""
/>
<
/div
>
<
div
class
=
"text"
>
{{
"中国企业45家(51.00%),受制裁3家(7.00%)"
}}
<
/div
>
<
div
class
=
"box2"
>
<
AnalysisBox
:
showAllBtn
=
"false"
>
<
template
#
custom
-
title
>
<
div
class
=
"custom-title"
>
<
div
class
=
"title-left"
>
<
div
:
class
=
"['title-item', {'title-active': contentType==1
}
]"
@
click
=
"headerContentType(1)"
>
<
div
class
=
"title-icon"
>
<
img
:
src
=
"contentType==1 ? icon1620 : icon1621"
alt
=
""
>
<
/div
>
<
div
>
产业链
<
/div
>
<
/div
>
<
div
class
=
"header-item2"
>
<
div
class
=
"header-item2-top"
>
{{
"软件算法"
}}
<
/div
>
<
div
class
=
"header-item2-bottom"
>
<
div
class
=
"icon"
>
<
img
src
=
"./assets/images/warning.png"
alt
=
""
/>
<
/div
>
<
div
class
=
"text"
>
{{
"中国企业45家(51.00%),受制裁3家(7.00%)"
}}
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"header-item3"
>
<
div
class
=
"header-item3-top"
>
{{
"行业应用"
}}
<
/div
>
<
div
class
=
"header-item3-bottom"
>
<
div
class
=
"icon"
>
<
img
src
=
"./assets/images/warning.png"
alt
=
""
/>
<
/div
>
<
div
class
=
"text"
>
{{
"中国企业45家(51.00%),受制裁3家(7.00%)"
}}
<
/div
>
<
div
:
class
=
"['title-item', {'title-active': contentType==2
}
]"
@
click
=
"headerContentType(2)"
>
<
div
class
=
"title-icon"
>
<
img
:
src
=
"contentType==2 ? icon422 : icon423"
alt
=
""
>
<
/div
>
<
div
>
实体关系
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"right-main-content-main"
>
<
Fishbone
/>
<
div
class
=
"title-right"
v
-
if
=
"contentType==1"
>
<
el
-
select
v
-
model
=
"industryChain.id"
style
=
"width: 100%"
@
change
=
"onDecreeChainNodes"
>
<
el
-
option
v
-
for
=
"item in industryChain.list"
:
key
=
"item.id"
:
label
=
"item.name"
:
value
=
"item.id"
/>
<
/el-select
>
<
/div
>
<
/div
>
<
div
class
=
"box-footer"
>
<
div
class
=
"box-footer-left"
>
<
img
src
=
"../assets/icons/right-icon1.png"
alt
=
""
/>
<
/div
>
<
div
class
=
"box-footer-center"
>
法案以
218
:
214
(众议院)和
51
:
50
(副总统决胜票)微弱优势强行通过,暴露两党极端对立、党内倒戈频发的特点。
<
/div
>
<
div
class
=
"box-footer-right"
>
<
img
src
=
"../assets/icons/arrow-right.png"
alt
=
""
/>
<
/div
>
<
/div
>
<
/div
>
<
/AnalysisBox
>
<
div
class
=
"graph-dialog"
v
-
if
=
"isShowCompanyDialog"
>
<
div
class
=
"tool-box"
>
<
div
class
=
"tool"
@
click
=
"handleChangeChart(0)"
>
<
img
src
=
"./assets/images/tool1.png"
alt
=
""
/>
<
/div
>
<
div
class
=
"tool1"
@
click
=
"handleChangeChart(1)"
>
<
img
src
=
"./assets/images/tool2.png"
alt
=
""
/>
<
/div
>
<
div
class
=
"tool"
@
click
=
"handleChangeChart(0)"
>
<
img
src
=
"./assets/images/tool3.png"
alt
=
""
/>
<
/div
>
<
/div
>
<
div
class
=
"chart-box"
id
=
"graphChart"
><
/div
>
<
/div
>
<
div
class
=
"company-dialog"
v
-
if
=
"isShowCompanyDialog"
>
<
div
class
=
"dialog-header"
>
<
div
class
=
"logo"
>
<
img
:
src
=
"companyInfo.logo"
alt
=
""
/>
<
/div
>
<
div
class
=
"company-title"
>
{{
companyInfo
.
name
}}
<
/div
>
<
div
class
=
"status-icon"
>
<
img
v
-
if
=
"companyInfo.status === 'up'"
:
src
=
"upIcon"
alt
=
""
/>
<
img
v
-
if
=
"companyInfo.status === 'down'"
:
src
=
"downIcon"
alt
=
""
/>
<
/div
>
<
div
class
=
"status-rate"
>
{{
companyInfo
.
changeRate
+
"%"
}}
<
/template
>
<
div
class
=
"box2-main"
>
<
AiTips
:
tips
=
"tips"
/>
<
div
class
=
"graph-box"
v
-
if
=
"contentType==1"
>
<
ChartChain
:
listData
=
"fishbone.list"
:
baseData
=
"fishbone.base"
/>
<
/div
>
<
div
class
=
"
close"
@
click
=
"isShowCompanyDialog = false
"
>
<
img
:
src
=
"closeIcon"
alt
=
"
"
/>
<
div
class
=
"
graph-box"
v
-
if
=
"contentType==2 && graphInfo.nodes.length
"
>
<
GraphChart
:
nodes
=
"graphInfo.nodes"
:
links
=
"graphInfo.links"
layoutType
=
"force
"
/>
<
/div
>
<
/div
>
<
div
class
=
"dialog-main"
>
<
div
class
=
"dialog-box1"
>
<
div
class
=
"dialog-box1-header"
>
<
div
class
=
"icon"
>
<
img
:
src
=
"companyInfo.data1?.icon"
alt
=
""
/>
<
/div
>
<
div
class
=
"dialog-box1-title"
>
{{
companyInfo
.
data1
?.
title
}}
<
/div
>
<
/div
>
<
div
class
=
"dialog-box1-main"
>
<
div
class
=
"item"
v
-
for
=
"(val, idx) in companyInfo.data1?.list"
:
key
=
"idx"
>
<
div
class
=
"item-left"
>
<!--
<
img
:
src
=
"uncheckIcon"
alt
=
""
>
-->
<
img
:
src
=
"checkedIcon"
alt
=
""
/>
<
/div
>
<
div
class
=
"item-right"
>
<
CommonPrompt
:
content
=
"val"
>
{{
val
}}
<
/CommonPrompt
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"dialog-box2"
>
<
div
class
=
"dialog-box2-header"
>
<
div
class
=
"icon"
>
<
img
:
src
=
"companyInfo.data2?.icon"
alt
=
""
/>
<
/div
>
<
div
class
=
"dialog-box2-title"
>
{{
companyInfo
.
data2
?.
title
}}
<
/div
>
<
/div
>
<
div
class
=
"dialog-box2-main"
id
=
"chart2"
><
/div
>
<
/div
>
<
div
class
=
"dialog-box3"
>
<
div
class
=
"dialog-box3-header"
>
<
div
class
=
"icon"
>
<
img
:
src
=
"companyInfo.data3?.icon"
alt
=
""
/>
<
/div
>
<
div
class
=
"dialog-box3-title"
>
{{
companyInfo
.
data3
?.
title
}}
<
/div
>
<
/div
>
<
div
class
=
"dialog-box3-main"
id
=
"chart3"
><
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/AnalysisBox
>
<
/div
>
<
/div
>
<
/template
>
<
script
setup
>
import
{
ref
,
onMounted
,
nextTick
,
computed
,
watch
}
from
"vue"
;
import
{
ref
,
onMounted
,
onBeforeUnmount
,
nextTick
,
computed
,
watch
,
reactive
}
from
"vue"
;
import
{
useRoute
}
from
"vue-router"
;
import
*
as
echarts
from
"echarts"
;
...
...
@@ -198,6 +104,7 @@ import getTreeChart from "./utils/treeChart";
import
downIcon
from
"./assets/images/down.png"
;
import
upIcon
from
"./assets/images/up.png"
;
import
defaultIcon2
from
"@/assets/icons/default-icon2.png"
;
import
CompanyLogo
from
"./assets/images/company-logo.png"
;
import
icon1
from
"./assets/images/icon1.png"
;
import
icon2
from
"./assets/images/icon2.png"
;
...
...
@@ -211,8 +118,25 @@ import Fishbone from "./components/fishbone.vue";
import
CommonPrompt
from
"../../commonPrompt/index.vue"
;
import
AnalysisBox
from
"@/components/base/boxBackground/analysisBox.vue"
;
import
ChartChain
from
"@/views/decree/decreeLayout/influence/com/ChartChain.vue"
;
import
AiTips
from
"@/views/decree/decreeLayout/influence/com/AiTips.vue"
;
import
GraphChart
from
"@/components/base/GraphChart/index.vue"
;
import
{
getDecreeRelatedChain
,
getDecreeChainNodes
,
getDecreeRelatedEntitie
,
}
from
"@/api/decree/influence"
;
import
icon422
from
"@/views/decree/decreeLayout/influence/assets/images/icon422.png"
;
import
icon423
from
"@/views/decree/decreeLayout/influence/assets/images/icon423.png"
;
import
icon1620
from
"@/views/decree/decreeLayout/influence/assets/images/icon1620.png"
;
import
icon1621
from
"@/views/decree/decreeLayout/influence/assets/images/icon1621.png"
;
import
company
from
"@/views/decree/decreeLayout/influence/assets/images/company.png"
;
import
CompanyImg
from
"./assets/images/symbol.png"
;
const
ALL_INDUSTRY_VALUE
=
"__all_industry__"
;
const
isShowCompanyDialog
=
ref
(
false
);
const
handleIndustryChange
=
()
=>
{
...
...
@@ -237,12 +161,164 @@ const handleClickCompany = (val, index) => {
companyActiveIndex
.
value
=
(
currentPage
.
value
-
1
)
*
pageSize
.
value
+
index
;
if
(
val
)
{
curCompanyId
.
value
=
val
.
id
;
handleGetCompanyDetail
();
//
handleGetCompanyDetail();
companyInfo
.
value
.
name
=
val
.
name
;
companyInfo
.
value
.
status
=
val
.
status
||
companyInfo
.
value
.
status
;
headerChartData
(
val
);
}
isShowCompanyDialog
.
value
=
true
;
// isShowCompanyDialog.value = true;
}
;
const
tips
=
"这项政令标志着中美AI竞争进入一个新阶段,其核心特征是 “精准封锁”与“体系输出”相结合。它短期内无疑会给中国AI产业链带来压力,但长期看,这场竞争更可能是一场围绕技术路线、生态系统和治理规则的持久战。"
;
const
contentType
=
ref
(
1
);
const
entityInfo
=
reactive
({
id
:
""
,
node
:
{
id
:
""
,
companyName
:
""
}
,
}
);
// 产业链
const
industryChain
=
reactive
({
list
:
[],
id
:
""
,
}
);
// 产业链鱼骨图
const
fishbone
=
reactive
({
list
:
[],
base
:
[],
}
);
// 实体关系
const
graphInfo
=
reactive
({
nodes
:
[],
links
:
[],
}
);
const
onDecreeRelatedChain
=
async
(
id
)
=>
{
try
{
const
res
=
await
getDecreeRelatedChain
({
id
}
);
if
(
res
.
code
===
200
)
{
industryChain
.
list
=
res
.
data
||
[];
if
(
industryChain
.
list
.
length
)
onDecreeChainNodes
(
industryChain
.
list
[
0
].
id
);
}
}
catch
(
error
)
{
console
.
log
(
"获取产业链失败"
,
error
);
}
}
;
const
onDecreeChainNodes
=
async
(
id
)
=>
{
industryChain
.
id
=
id
;
try
{
const
res
=
await
getDecreeChainNodes
({
id
}
);
if
(
res
.
code
===
200
)
{
let
obj
=
res
.
data
.
chains
.
reduce
((
result
,
item
)
=>
{
result
[
"chain-"
+
item
.
id
]
=
{
...
item
,
children
:
[]
}
;
return
result
;
}
,
{
}
);
res
.
data
.
children
.
forEach
((
item
)
=>
{
if
(
item
.
companyId
==
entityInfo
.
id
)
{
obj
[
"chain-"
+
item
.
chainId
].
children
.
push
({
...
item
,
back
:
true
}
);
}
else
if
(
obj
[
"chain-"
+
item
.
chainId
]?.
children
?.
length
<
10
)
{
obj
[
"chain-"
+
item
.
chainId
].
children
.
push
(
item
);
}
}
);
fishbone
.
list
=
Object
.
values
(
obj
);
fishbone
.
base
=
(
res
.
data
.
levelInfos
||
[]).
map
((
item
,
index
)
=>
{
return
{
...
item
,
name
:
[
"上游"
,
"中游"
,
"下游"
][
index
]
}
;
}
);
}
}
catch
(
error
)
{
console
.
log
(
"获取产业链鱼骨图失败"
,
error
);
}
}
;
const
onFormatLink
=
(
item
,
index
)
=>
{
return
{
id
:
`link-${index + 1
}
`
,
source
:
item
.
id
+
""
,
target
:
entityInfo
.
id
+
""
,
label
:
{
show
:
true
,
color
:
"#055fc2"
,
backgroundColor
:
"#eef7ff"
,
borderWidth
:
0
,
offset
:
[
0
,
15
],
formatter
:
item
.
relation
,
}
,
lineStyle
:
{
color
:
"#B9DCFF"
,
type
:
"solid"
,
opacity
:
1
}
,
}
;
}
;
const
onWordWrap
=
(
word
,
num
)
=>
{
const
list
=
(
word
||
""
).
split
(
""
);
let
label
=
""
;
for
(
let
i
=
0
;
i
<
list
.
length
;
i
++
)
{
if
(
i
%
num
===
0
&&
i
!==
0
)
{
label
+=
"
\
n"
;
}
label
+=
list
[
i
];
}
return
label
;
}
;
const
onFormatNode
=
(
item
)
=>
{
let
leader
=
item
.
id
==
entityInfo
.
id
;
return
{
id
:
item
.
id
+
""
,
name
:
onWordWrap
(
item
.
companyName
||
item
.
name
||
""
,
7
),
label
:
{
show
:
true
,
color
:
"#3b414b"
,
fontSize
:
leader
?
18
:
14
,
fontWeight
:
leader
?
700
:
400
,
fontFamily
:
"Source Han Sans CN"
,
}
,
symbolSize
:
40
,
symbol
:
`image://${company
}
`
,
}
;
}
;
const
onDecreeRelatedEntitie
=
async
(
id
)
=>
{
try
{
const
res
=
await
getDecreeRelatedEntitie
({
id
}
);
if
(
res
.
code
===
200
)
{
graphInfo
.
links
=
(
res
.
data
||
[]).
map
(
onFormatLink
);
graphInfo
.
nodes
=
(
res
.
data
||
[]).
map
(
onFormatNode
);
if
(
entityInfo
.
node
?.
id
)
graphInfo
.
nodes
.
unshift
(
onFormatNode
(
entityInfo
.
node
));
}
}
catch
(
error
)
{
console
.
log
(
"获取实体关系失败"
,
error
);
}
}
;
const
headerChartData
=
(
row
)
=>
{
entityInfo
.
id
=
row
.
id
;
entityInfo
.
node
=
row
;
industryChain
.
id
=
""
;
fishbone
.
list
=
[];
fishbone
.
base
=
[];
graphInfo
.
nodes
=
[];
graphInfo
.
links
=
[];
switch
(
contentType
.
value
)
{
case
1
:
onDecreeRelatedChain
(
row
.
id
)
break
;
case
2
:
onDecreeRelatedEntitie
(
row
.
id
)
break
;
}
}
;
const
headerContentType
=
(
type
)
=>
{
contentType
.
value
=
type
;
headerChartData
(
entityInfo
.
node
);
}
;
const
pageSize
=
ref
(
10
);
...
...
@@ -250,6 +326,7 @@ const currentPage = ref(1);
const
companyList
=
ref
([]);
// 企业列表
const
companySearchKeyword
=
ref
(
""
);
// 企业搜索关键词
let
companySearchTimer
=
null
;
// 根据关键词筛选后的企业列表
const
filteredCompanyList
=
computed
(()
=>
{
...
...
@@ -272,9 +349,21 @@ const handleCurrentChange = page => {
currentPage
.
value
=
page
;
}
;
// 搜索关键词变化时重置到第一页
// 搜索关键词变化时重置到第一页
,并通过接口重新拉取列表
watch
(
companySearchKeyword
,
()
=>
{
currentPage
.
value
=
1
;
if
(
companySearchTimer
)
{
clearTimeout
(
companySearchTimer
);
}
companySearchTimer
=
setTimeout
(()
=>
{
handleGetCompanyListById
();
}
,
300
);
}
);
onBeforeUnmount
(()
=>
{
if
(
companySearchTimer
)
{
clearTimeout
(
companySearchTimer
);
}
}
);
const
industryList
=
ref
([
...
...
@@ -321,27 +410,36 @@ const companyInfo = ref({
const
handleGetHylyList
=
async
()
=>
{
try
{
const
res
=
await
getHylyList
();
// console.log("行业领域字典列表", res);
industryList
.
value
=
res
.
data
if
(
res
.
data
&&
res
.
data
.
length
>
0
)
{
curHylyId
.
value
=
res
.
data
[
0
].
id
;
if
(
res
.
code
===
200
&&
Array
.
isArray
(
res
.
data
))
{
industryList
.
value
=
[{
id
:
ALL_INDUSTRY_VALUE
,
name
:
"全部领域"
}
,
...
res
.
data
];
curHylyId
.
value
=
ALL_INDUSTRY_VALUE
;
return
;
}
}
catch
(
error
)
{
}
industryList
.
value
=
[];
curHylyId
.
value
=
""
;
}
catch
(
error
)
{
industryList
.
value
=
[];
curHylyId
.
value
=
""
;
}
}
;
const
curHylyId
=
ref
(
""
);
// 根据行业领域id获取公司列表
const
handleGetCompanyListById
=
async
()
=>
{
const
params
=
{
id
:
curHylyId
.
value
}
;
const
params
=
{
}
;
const
trimmedCompanyName
=
companySearchKeyword
.
value
.
trim
();
if
(
curHylyId
.
value
&&
curHylyId
.
value
!==
ALL_INDUSTRY_VALUE
)
{
params
.
id
=
curHylyId
.
value
;
}
if
(
trimmedCompanyName
)
{
params
.
companyName
=
trimmedCompanyName
;
}
try
{
const
res
=
await
getCompanyList
(
params
);
// console.log('根据行业id获取公司里列表', res);
if
(
res
.
code
===
200
&&
res
.
data
.
length
)
{
if
(
res
.
code
===
200
&&
Array
.
isArray
(
res
.
data
)
&&
res
.
data
.
length
)
{
companyList
.
value
=
res
.
data
;
companySearchKeyword
.
value
=
""
;
currentPage
.
value
=
1
;
nextTick
(()
=>
{
handleClickCompany
(
companyList
.
value
[
0
],
0
);
...
...
@@ -349,7 +447,9 @@ const handleGetCompanyListById = async () => {
}
else
{
companyList
.
value
=
[];
}
}
catch
(
error
)
{
}
}
catch
(
error
)
{
companyList
.
value
=
[];
}
}
;
// 根据法案id,公司id,行业领域id获取公司的详情
...
...
@@ -357,7 +457,7 @@ const handleGetCompanyDetail = async () => {
const
params
=
{
billId
:
window
.
sessionStorage
.
getItem
(
"billId"
),
companyId
:
curCompanyId
.
value
,
id
:
curHylyId
.
value
id
:
curHylyId
.
value
===
ALL_INDUSTRY_VALUE
?
""
:
curHylyId
.
value
}
;
try
{
const
res
=
await
getCompanyDetail
(
params
);
...
...
@@ -711,15 +811,28 @@ onMounted(async () => {
flex-direction: column;
height: 100%;
overflow: hidden;
padding: 10px 16px;
}
.left-center {
flex
: 1
;
min-height: 0
;
m
argin: 12px 17px 0
;
flex
-shrink: 0
;
height: 32px
;
m
in-height: 32px
;
display: flex;
align-items: flex-start;
gap: 12px;
align-items: center;
gap: 16px;
margin-bottom: 10px;
:deep(.el-input__wrapper),
:deep(.el-select__wrapper) {
height: 32px;
}
:deep(.el-input__inner),
:deep(.el-select__selection) {
height: 32px;
line-height: 32px;
}
.left-center-select {
width: 150px;
...
...
@@ -731,48 +844,76 @@ onMounted(async () => {
min-width: 0;
:deep(.el-input__wrapper) {
border: 1px solid var(--bg-black-10);
box-shadow: none;
background-color: var(--el-fill-color-blank);
border-radius: var(--el-border-radius-base);
box-shadow: 0 0 0 1px var(--el-border-color) inset;
border: none;
box-sizing: border-box;
}
}
}
.left-footer {
flex-shrink: 0;
margin: 0 auto;
width: 446px;
height: 520px;
.left-list {
flex: 1;
min-height: 0;
overflow: hidden;
display: flex;
flex-direction: column;
.left-list-title {
width: 100%;
text-align: left;
color: var(--text-primary-80-color);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
border-top: 1px solid rgba(240, 242, 244, 1);
padding: 12px 0;
}
.left-list-content {
flex: 1;
min-height: 0;
}
.item-box {
height: 480
px;
overflow: hidden
;
width: 446
px;
margin: 0 auto
;
.item {
width: 100%;
height: 48px;
border-radius: 4px;
border-bottom: 1px solid rgba(243, 243, 244, 1);
border-bottom: 1px solid rgba(240, 242, 244, 1);
border-top: 1px solid transparent;
display: flex;
cursor: pointer;
&:hover {
background: rgba(246, 251, 255, 1);
background-color: #f7f8fa;
}
&:first-child {
border-top-color: rgba(240, 242, 244, 1);
}
.i
d
{
.i
tem-icon
{
margin-left: 12px;
margin-top: 8px;
width: 24px;
height: 24px;
border-radius: 12px;
background: rgba(231, 241, 255);
text-align: center;
line-height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 12px;
font-weight: 400;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
.item-img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.title {
...
...
@@ -804,31 +945,53 @@ onMounted(async () => {
}
.itemActive {
background: rgba(246, 251, 255, 1);
background-color: rgba(5, 95, 194, 0.05);
border-top-color: rgba(174, 214, 255, 1);
border-bottom-color: rgba(174, 214, 255, 1);
.item-icon {
background: rgba(5, 95, 194, 0.1);
}
}
.titleActive {
color: rgba(22, 119, 255, 1) !important;
}
}
}
.footer-box {
display: flex;
justify-content: space-between;
.left-pagination {
flex-shrink: 0;
margin: 0 auto;
width: 446px;
height: 65px;
overflow: hidden;
display: flex;
align-items: flex-start;
.left {
width: 100px;
height: 20px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
justify-content: space-between;
width: 100%;
box-sizing: border-box;
.right {
flex: 300px;
}
.left-pagination-left {
width: 100px;
height: 18px;
margin-top: 25px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
overflow: hidden;
white-space: nowrap;
}
.left-pagination-right {
flex: 1;
min-width: 0;
display: flex;
justify-content: flex-end;
margin-top: 23px;
}
}
}
...
...
@@ -1362,5 +1525,78 @@ onMounted(async () => {
}
}
}
.box2 {
margin-top: 16px;
margin-left: 16px;
width: 1247px;
height: 847px;
position: relative;
.custom-title {
display: flex;
justify-content: space-between;
align-items: flex-end;
width: 100%;
height: 100%;
padding: 0 20px;
.title-left {
display: flex;
border: 1px solid rgb(5, 95, 194);
color: rgb(5, 95, 194);
border-radius: 16px;
width: 240px;
height: 32px;
overflow: hidden;
cursor: pointer;
.title-item {
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
width: 50%;
font-size: 16px;
line-height: 16px;
font-family: "Microsoft YaHei";
.title-icon {
width: 14px;
height: 14px;
font-size: 0;
img {
width: 100%;
height: 100%;
}
}
}
.title-active {
background-color: rgb(5, 95, 194);
color: white;
}
}
.title-right {
width: 180px;
}
}
.box2-main {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
padding: 16px 20px;
.graph-box {
height: 20px;
flex: auto;
margin-top: 16px;
}
}
}
}
</style>
src/views/bill/introdoction/index.vue
浏览文件 @
8fb13448
...
...
@@ -90,10 +90,10 @@
<
img
class
=
"person-avatar"
:
src
=
"curPerson.imageUrl || defaultAvatar"
alt
=
""
@
click
=
"handleClickAvatar(curPerson)"
/>
<
div
class
=
"usr-icon1"
>
<
img
src
=
"./assets/images/usr-icon1.png
"
alt
=
""
/>
<
img
:
src
=
"partyIconUrl
"
alt
=
""
/>
<
/div
>
<
div
class
=
"usr-icon2"
>
<
img
src
=
"./assets/images/usr-icon2.png
"
alt
=
""
/>
<
img
:
src
=
"congressIconUrl
"
alt
=
""
/>
<
/div
>
<
/div
>
<
div
class
=
"info-right"
>
...
...
@@ -159,6 +159,12 @@ import { getPersonSummaryInfo } from "@/api/common/index";
import
defaultAvatar
from
"../assets/images/default-icon1.png"
;
import
defaultNew
from
"../assets/images/default-icon-news.png"
;
import
defaultBill
from
"./assets/images/image1.png"
import
defaultUsrIcon1
from
"./assets/images/usr-icon1.png"
;
import
defaultUsrIcon2
from
"./assets/images/usr-icon2.png"
;
import
cyyIcon
from
"@/assets/icons/cyy.png"
;
import
zyyIcon
from
"@/assets/icons/zyy.png"
;
import
ghdIcon
from
"@/assets/icons/ghd.png"
;
import
mzdIcon
from
"@/assets/icons/mzd.png"
;
import
{
ElMessage
}
from
"element-plus"
;
const
route
=
useRoute
();
...
...
@@ -229,6 +235,22 @@ const basicInfo = ref({});
const
riskSignal
=
computed
(()
=>
basicInfo
.
value
?.
riskSignalVO
||
null
);
const
hylyList
=
computed
(()
=>
(
Array
.
isArray
(
basicInfo
.
value
?.
hylyList
)
?
basicInfo
.
value
.
hylyList
:
[]));
const
reportList
=
computed
(()
=>
(
Array
.
isArray
(
basicInfo
.
value
?.
reportList
)
?
basicInfo
.
value
.
reportList
:
[]));
// 提出人头像下方标志:参/众议院 + 党派
const
congressIconUrl
=
computed
(()
=>
{
const
congress
=
curPerson
.
value
?.
congress
;
if
(
congress
===
"参议院"
)
return
cyyIcon
;
if
(
congress
===
"众议院"
)
return
zyyIcon
;
return
defaultUsrIcon1
;
}
);
const
partyIconUrl
=
computed
(()
=>
{
const
dp
=
curPerson
.
value
?.
dp
;
if
(
dp
===
"共和党"
)
return
ghdIcon
;
if
(
dp
===
"民主党"
)
return
mzdIcon
;
return
defaultUsrIcon2
;
}
);
const
reversedStageList
=
computed
(()
=>
{
const
list
=
Array
.
isArray
(
basicInfo
.
value
?.
stageList
)
?
basicInfo
.
value
.
stageList
:
[];
return
[...
list
].
reverse
();
...
...
@@ -764,9 +786,10 @@ onMounted(() => {
.
person
-
box
{
width
:
500
px
;
overflow
-
x
:
auto
;
overflow
-
x
:
hidden
;
display
:
flex
;
justify
-
content
:
flex
-
start
;
flex
-
wrap
:
wrap
;
padding
-
bottom
:
5
px
;
&
::
-
webkit
-
scrollbar
{
...
...
@@ -783,7 +806,8 @@ onMounted(() => {
}
.
person
-
item
{
height
:
28
px
;
min
-
height
:
28
px
;
height
:
auto
;
box
-
sizing
:
border
-
box
;
border
:
1
px
solid
var
(
--
btn
-
plain
-
border
-
color
);
border
-
radius
:
4
px
;
...
...
@@ -799,8 +823,12 @@ onMounted(() => {
margin
-
right
:
8
px
;
padding
:
1
px
12
px
;
cursor
:
pointer
;
white
-
space
:
nowrap
;
flex
-
shrink
:
0
;
white
-
space
:
normal
;
word
-
break
:
break
-
all
;
line
-
height
:
18
px
;
flex
-
shrink
:
1
;
max
-
width
:
170
px
;
text
-
align
:
center
;
}
.
nameItemActive
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论