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 个修改的文件
包含
251 行增加
和
11 行删除
+251
-11
influence.js
src/api/influence.js
+5
-3
index.vue
src/views/bill/deepDig/processAnalysis/index.vue
+180
-0
boxplot.js
src/views/bill/deepDig/processAnalysis/utils/boxplot.js
+32
-2
index.vue
src/views/bill/influence/industry/index.vue
+0
-0
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,6 +32,7 @@
</div>
</div>
-->
<AnalysisBox
title=
"典型阶段耗时"
>
<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"
>
...
...
@@ -46,6 +47,14 @@
</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>
<div
class=
"box2"
>
...
...
@@ -80,6 +89,7 @@
</div>
</div>
-->
<AnalysisBox
title=
"修正案次数分析"
>
<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"
>
...
...
@@ -94,6 +104,14 @@
</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>
</div>
...
...
@@ -366,6 +384,7 @@
<
/div
>
<
/div> --
>
<
AnalysisBox
title
=
"投票分析"
>
<
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
>
...
...
@@ -678,6 +697,14 @@
<
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
>
...
...
@@ -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
差异被折叠。
点击展开。
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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论