Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
zrch-risk-39
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Administrator
zrch-risk-39
Commits
9dd9c254
提交
9dd9c254
authored
3月 06, 2026
作者:
kxjia
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
指标名称
上级
dc235789
隐藏空白字符变更
内嵌
并排
正在显示
15 个修改的文件
包含
1092 行增加
和
342 行删除
+1092
-342
.env
zrch-risk-client-39/.env
+3
-3
.env.development
zrch-risk-client-39/.env.development
+2
-2
.env.production
zrch-risk-client-39/.env.production
+4
-5
index.html
zrch-risk-client-39/index.html
+1
-1
api.ts
zrch-risk-client-39/src/api/common/api.ts
+18
-0
componentMap.ts
zrch-risk-client-39/src/components/Form/src/componentMap.ts
+3
-1
JCascaderDomain.vue
.../components/Form/src/jeecg/components/JCascaderDomain.vue
+25
-24
JSelectMetric.vue
...rc/components/Form/src/jeecg/components/JSelectMetric.vue
+0
-1
index.ts
zrch-risk-client-39/src/components/Form/src/types/index.ts
+3
-2
Tb3.vue
...isk-client-39/src/views/baosong/report/components/Tb3.vue
+1
-1
MetricChartModal.vue
...src/views/metric/approval/components/MetricChartModal.vue
+631
-0
index.vue
zrch-risk-client-39/src/views/metric/approval/index.vue
+236
-152
left.vue
zrch-risk-client-39/src/views/metric/approval/left.vue
+117
-146
StDomain.data.ts
...isk-client-39/src/views/standardlib/base/StDomain.data.ts
+1
-0
StDomainList.vue
...isk-client-39/src/views/standardlib/base/StDomainList.vue
+47
-4
没有找到文件。
zrch-risk-client-39/.env
浏览文件 @
9dd9c254
...
...
@@ -8,7 +8,7 @@ VITE_GLOB_APP_TITLE = 科技风险管理平台
VITE_GLOB_APP_SHORT_NAME = 科技风险管理平台
# 单点登录服务端地址
VITE_GLOB_APP_CAS_BASE_URL=http://cas.test.com:8443/cas
#
VITE_GLOB_APP_CAS_BASE_URL=http://cas.test.com:8443/cas
# 是否开启单点登录
...
...
@@ -18,10 +18,10 @@ VITE_GLOB_APP_OPEN_SSO = false
VITE_GLOB_APP_OPEN_QIANKUN=true
#后台接口全路径地址(必填)
VITE_GLOB_DOMAIN_URL=http://47.98.203.68:8080/stm/
#
VITE_GLOB_DOMAIN_URL=http://47.98.203.68:8080/stm/
# 文件预览地址
# VITE_GLOB_ONLINE_VIEW_URL=http://fileview.jeecg.com/onlinePreview
VITE_GLOB_ONLINE_VIEW_URL=http://47.98.203.68:8080/stm/sys/common/static/
#
VITE_GLOB_ONLINE_VIEW_URL=http://47.98.203.68:8080/stm/sys/common/static/
zrch-risk-client-39/.env.development
浏览文件 @
9dd9c254
...
...
@@ -9,7 +9,7 @@ VITE_PUBLIC_PATH = /
VITE_PROXY = [["/stm","http://localhost:8080/stm"],["/upload","http://localhost:3300/upload"]]
#后台接口全路径地址(必填)
VITE_GLOB_DOMAIN_URL=http://localhost:8080/stm
/
VITE_GLOB_DOMAIN_URL=http://localhost:8080/stm
#后台接口父地址(必填)
VITE_GLOB_API_URL=/stm
...
...
@@ -33,5 +33,5 @@ VITE_APP_SUB_jeecg-app-1 = '//localhost:8092'
VITE_GLOB_ONLINE_DOCUMENT_VERSION=wps
# 文件预览地址
VITE_GLOB_ONLINE_VIEW_URL=http://localhost:
808
0/stm/sys/common/static/
VITE_GLOB_ONLINE_VIEW_URL=http://localhost:
310
0/stm/sys/common/static/
zrch-risk-client-39/.env.production
浏览文件 @
9dd9c254
...
...
@@ -16,13 +16,12 @@ VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
VITE_GLOB_API_URL=/stm
#后台接口全路径地址(必填)
# VITE_GLOB_DOMAIN_URL=https://itrm.westmining.com:8080
/stm
# VITE_GLOB_ONLINE_VIEW_URL=https://itrm.westmining.com:8080
/stm/sys/common/static/
VITE_GLOB_DOMAIN_URL=https://itrm.westmining.com
/stm
VITE_GLOB_ONLINE_VIEW_URL=https://itrm.westmining.com
/stm/sys/common/static/
#后台接口全路径地址(必填)
VITE_GLOB_DOMAIN_URL=http://47.98.203.68:8080/stm/
VITE_GLOB_ONLINE_VIEW_URL=http://47.98.203.68:8080/stm/sys/common/static/
# VITE_GLOB_DOMAIN_URL=http://47.98.203.68:8080/stm/
# VITE_GLOB_ONLINE_VIEW_URL=http://47.98.203.68:8080/stm/sys/common/static/
# 接口父路径前缀
VITE_GLOB_API_URL_PREFIX=
...
...
zrch-risk-client-39/index.html
浏览文件 @
9dd9c254
...
...
@@ -157,7 +157,7 @@
</style>
<div
class=
"app-loading"
>
<div
class=
"app-loading-wrap"
>
<img
src=
"<%= basePublicPath %>/resource/img/logo.png"
class=
"app-loading-logo"
alt=
"Logo"
style=
"width: 80px;height:32px;"
/>
<img
src=
"<%= basePublicPath %>/resource/img/logo.png"
class=
"app-loading-logo"
alt=
"Logo"
/>
<div
class=
"app-loading-dots"
>
<span
class=
"dot dot-spin"
><i></i><i></i><i></i><i></i></span>
</div>
...
...
zrch-risk-client-39/src/api/common/api.ts
浏览文件 @
9dd9c254
...
...
@@ -22,8 +22,13 @@ enum Api {
queryDepartPostUserPageList
=
'/sys/user/queryDepartPostUserPageList'
,
//查询所选部门的所有父节点ID
queryAllParentId
=
'/sys/sysDepart/queryAllParentId'
,
getMetricList
=
'/metric/metricMonitorSet/list'
,
queryAllMetric
=
'/metric/metricMonitorSet/queryAllMetric'
,
rateRuleList
=
'/rate/rateRule/list'
,
}
/**
* 上传父路径
*/
...
...
@@ -188,3 +193,16 @@ export const refreshDragCache = () => defHttp.get({ url: Api.refreshDragCache },
* @param params
*/
export
const
refreshHomeCache
=
()
=>
defHttp
.
get
({
url
:
Api
.
refreshDefaultIndexCache
},
{
isTransformResponse
:
false
});
export
const
getMetricList
=
(
params
)
=>
{
return
defHttp
.
get
({
url
:
Api
.
getMetricList
,
params
})
};
export
const
queryAllMetric
=
(
params
)
=>
{
return
defHttp
.
get
({
url
:
Api
.
queryAllMetric
,
params
})
}
export
const
getRateRuleList
=
(
params
)
=>
{
return
defHttp
.
get
({
url
:
Api
.
rateRuleList
,
params
});
};
zrch-risk-client-39/src/components/Form/src/componentMap.ts
浏览文件 @
9dd9c254
...
...
@@ -76,7 +76,7 @@ import JCaSelect from './jeecg/components/JCaSelect.vue';
import
StSelectLable
from
'./jeecg/components/StSelectLable.vue'
;
import
JSearchSelectDuty
from
'./jeecg/components/JSearchSelectDuty.vue'
;
import
JSelectMetric
from
'./jeecg/components/JSelectMetric.vue'
;
const
componentMap
=
new
Map
<
ComponentType
,
Component
>
();
...
...
@@ -182,6 +182,8 @@ componentMap.set('JCaSelect', JCaSelect);
componentMap
.
set
(
'StSelectLable'
,
StSelectLable
);
componentMap
.
set
(
'JSearchSelectDuty'
,
JSearchSelectDuty
);
componentMap
.
set
(
'JSelectMetric'
,
JSelectMetric
);
export
function
add
(
compName
:
ComponentType
,
component
:
Component
)
{
componentMap
.
set
(
compName
,
component
);
}
...
...
zrch-risk-client-39/src/components/Form/src/jeecg/components/JCascaderDomain.vue
浏览文件 @
9dd9c254
...
...
@@ -29,7 +29,7 @@
enum
Api
{
url
=
'/sys/dict/loadTreeData'
,
view
=
'/
sys/dict/loadDictItem/
'
,
view
=
'/
base.domain/stDomain/queryByCode
'
,
}
const
props
=
defineProps
({
...
...
@@ -110,29 +110,30 @@
treeValue
.
value
=
props
.
multiple
?
[]
:
null
;
return
;
}
const
params
=
{
key
:
props
.
value
};
const
result
=
await
defHttp
.
get
({
url
:
`
${
Api
.
view
}${
props
.
dict
}
`
,
params
},
{
isTransformResponse
:
false
});
if
(
result
.
success
&&
result
.
result
?.
length
>
0
)
{
console
.
log
(
result
,
'result'
);
console
.
log
(
result
.
result
,
'result.result'
);
console
.
log
(
props
,
'props'
);
const
values
=
props
.
value
;
console
.
log
(
values
,
'values'
);
const
length
=
values
.
length
;
console
.
log
(
length
,
'length'
);
if
(
length
===
2
)
{
treeValue
.
value
=
[
values
];
console
.
log
(
treeValue
.
value
,
'treeValue.value2'
);
}
else
if
(
length
===
4
)
{
treeValue
.
value
=
[
values
.
substring
(
0
,
2
),
values
];
console
.
log
(
treeValue
.
value
,
'treeValue.value4'
);
}
else
if
(
length
===
6
)
{
treeValue
.
value
=
[
values
.
substring
(
0
,
2
),
values
.
substring
(
0
,
4
),
values
];
console
.
log
(
treeValue
.
value
,
'treeValue.value6'
);
}
console
.
log
(
props
.
value
,
'props.value'
);
const
params
=
{
code
:
props
.
value
};
const
result
=
await
defHttp
.
get
({
url
:
`
${
Api
.
view
}
`
,
params
},
{
isTransformResponse
:
false
});
console
.
log
(
result
,
'result'
);
if
(
result
.
success
&&
result
.
result
)
{
// console.log(result.result, 'result.result');
// console.log(props, 'props');
// const values = props.value;
// console.log(values, 'values');
// const length = values.length;
// console.log(length, 'length');
// if (length === 2) {
// treeValue.value = [values];
// console.log(treeValue.value, 'treeValue.value2');
// } else if (length === 4) {
// treeValue.value = [values.substring(0, 2), values];
// console.log(treeValue.value, 'treeValue.value4');
// } else if (length === 6) {
// treeValue.value = [values.substring(0, 2), values.substring(0, 4), values];
// console.log(treeValue.value, 'treeValue.value6');
// }
treeValue
.
value
=
[
result
.
result
];
onLoadTriggleChange
(
result
.
result
[
0
]);
}
}
...
...
zrch-risk-client-39/src/components/Form/src/jeecg/components/JSelectMetric.vue
浏览文件 @
9dd9c254
<
template
>
<div>
<JMetricBiz
@
handleOpen=
"handleOpen"
:loading=
"loadingEcho"
v-bind=
"attrs"
></JMetricBiz>
...
...
zrch-risk-client-39/src/components/Form/src/types/index.ts
浏览文件 @
9dd9c254
...
...
@@ -168,4 +168,5 @@ export type ComponentType =
|
'StSelectLable'
|
'JTreeSelectDomain'
|
'JCaSelect'
|
'JInputSelect'
;
\ No newline at end of file
|
'JInputSelect'
|
'JSelectMetric'
;
\ No newline at end of file
zrch-risk-client-39/src/views/baosong/report/components/Tb3.vue
浏览文件 @
9dd9c254
...
...
@@ -275,7 +275,7 @@
</vxe-column>
<!-- 备注列 -->
<vxe-column
field=
"remarks"
title=
"备注"
width=
"
2
00"
>
<vxe-column
field=
"remarks"
title=
"备注"
width=
"
1
00"
>
<
template
#
default=
"{ row }"
>
<vxe-textarea
:rows=
"row.remarks.rows"
...
...
zrch-risk-client-39/src/views/metric/approval/components/MetricChartModal.vue
0 → 100644
浏览文件 @
9dd9c254
<
template
>
<a-modal
:visible=
"visible"
:title=
"title"
:width=
"'60%'"
:bodyStyle=
"
{ height: '80vh', padding: '20px' }"
:footer="null"
@ok="handleOk"
@cancel="handleCancel"
@update:visible="(value) => emit('update:visible', value)"
:centered="true"
:destroyOnClose="true"
:maskClosable="false"
>
<div
style=
"height: 100%; display: flex; flex-direction: column;"
>
<!-- 加载状态 -->
<div
v-if=
"chartLoading"
style=
"text-align: center; padding: 50px;"
>
<a-spin
size=
"large"
/>
</div>
<template
v-else
>
<!-- 指标信息 -->
<div
style=
"margin-bottom: 16px; padding: 12px; background: #f5f7fa; border-radius: 4px;"
>
<a-row
:gutter=
"16"
>
<a-col
:span=
"4"
><strong>
指标编码:
</strong>
{{
row
?.
mtrcNo
}}
</a-col>
<a-col
:span=
"12"
style=
"white-space: nowrap; overflow: hidden; text-overflow: ellipsis;"
><strong>
指标名称:
</strong>
{{
row
?.
mtrcName
}}
</a-col>
<a-col
:span=
"4"
><strong>
采集频率:
</strong>
{{
getFreqText
(
row
?.
collFreq
)
}}
</a-col>
<a-col
:span=
"4"
><strong>
数据条数:
</strong>
{{
chartDataList
.
length
}}
</a-col>
</a-row>
</div>
<!-- 时间选择表单 -->
<div
style=
"margin-bottom: 16px; padding: 12px; background: #f9f9f9; border-radius: 4px;"
>
<a-row
:gutter=
"16"
>
<a-col
:span=
"16"
>
<BasicForm
@
register=
"registerForm"
/>
</a-col>
<a-col
:span=
"8"
>
<a-space
:size=
"5"
style=
"float: right;"
>
<a-button
type=
"primary"
@
click=
"searchQuery"
>
查询
</a-button>
<a-button
@
click=
"searchReset"
>
重置
</a-button>
</a-space>
</a-col>
</a-row>
</div>
<a-tabs
v-model:activeKey=
"activeTabKey"
@
change=
"handleTabChange"
style=
"flex: 1; display: flex; flex-direction: column;"
>
<a-tab-pane
key=
"list"
tab=
"指标值"
style=
"height: 100%;"
>
<a-table
:dataSource=
"chartDataList"
:columns=
"dataColumns"
:pagination=
"
{ pageSize: 10 }"
size="small"
:scroll="{ y: 'calc(70vh - 200px)' }"
bordered
>
<template
#
bodyCell=
"
{ column, text, record }">
<template
v-if=
"column.key === 'riskLevel'"
>
<a-badge
:status=
"getRiskLevelStatus(record.riskLevel)"
:text=
"getRiskLevelText(record.riskLevel)"
/>
</
template
>
</template>
</a-table>
</a-tab-pane>
<a-tab-pane
key=
"line"
tab=
"走势图"
style=
"height: 100%;"
>
<div
ref=
"lineChartRef"
style=
"width: 100%; height: calc(70vh - 150px);"
></div>
</a-tab-pane>
<a-tab-pane
key=
"bar"
tab=
"柱状图"
style=
"height: 100%;"
>
<div
ref=
"barChartRef"
style=
"width: 100%; height: calc(70vh - 150px);"
></div>
</a-tab-pane>
<a-tab-pane
key=
"pie"
tab=
"风险分布"
style=
"height: 100%;"
>
<div
ref=
"pieChartRef"
style=
"width: 100%; height: calc(70vh - 150px);"
></div>
</a-tab-pane>
</a-tabs>
</template>
</div>
</a-modal>
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
,
watch
,
nextTick
}
from
'vue'
import
*
as
echarts
from
'echarts'
import
{
queryAllList
,
queryByMtrcNo
}
from
'../../MetricReport.api'
import
{
BasicForm
,
useForm
}
from
'/@/components/Form/index'
import
{
FormSchema
}
from
'/@/components/Table'
interface
Props
{
visible
:
boolean
title
:
string
row
?:
any
}
const
props
=
defineProps
<
Props
>
()
const
emit
=
defineEmits
([
'update:visible'
,
'ok'
,
'cancel'
])
// 响应式数据
const
activeTabKey
=
ref
(
'list'
)
const
chartLoading
=
ref
(
false
)
const
chartDataList
=
ref
<
any
[]
>
([])
const
curMtrcSet
=
ref
<
any
>
({})
// 图表实例
const
lineChartRef
=
ref
<
HTMLDivElement
|
null
>
(
null
)
const
barChartRef
=
ref
<
HTMLDivElement
|
null
>
(
null
)
const
pieChartRef
=
ref
<
HTMLDivElement
|
null
>
(
null
)
let
lineChart
:
echarts
.
ECharts
|
null
=
null
let
barChart
:
echarts
.
ECharts
|
null
=
null
let
pieChart
:
echarts
.
ECharts
|
null
=
null
// 表单配置
const
searchFormSchema
:
FormSchema
[]
=
[
{
label
:
'开始日期'
,
field
:
'stFillTime'
,
component
:
'DatePicker'
,
colProps
:
{
xs
:
12
,
sm
:
12
,
md
:
12
,
lg
:
8
,
xl
:
8
},
defaultValue
:
(
new
Date
().
getFullYear
()
-
3
)
+
"-"
+
(
new
Date
().
getMonth
()
+
1
)
+
"-"
+
(
new
Date
().
getDate
()),
},
{
label
:
'结束日期'
,
field
:
'endFillTime'
,
defaultValue
:
new
Date
(),
component
:
'DatePicker'
,
colProps
:
{
xs
:
12
,
sm
:
12
,
md
:
12
,
lg
:
8
,
xl
:
8
},
},
]
// 初始化表单
const
[
registerForm
,
{
setFieldsValue
,
getFieldsValue
}]
=
useForm
({
labelWidth
:
100
,
schemas
:
searchFormSchema
,
showActionButtonGroup
:
false
,
baseColProps
:
{
span
:
24
}
})
// 表格列定义
const
dataColumns
=
[
{
title
:
'填报时间'
,
dataIndex
:
'fillTime'
,
key
:
'fillTime'
,
width
:
150
,
render
:
(
text
)
=>
text
||
'无数据'
},
{
title
:
'填报值'
,
dataIndex
:
'fillVals'
,
key
:
'fillVals'
,
width
:
100
},
{
title
:
'风险等级'
,
dataIndex
:
'riskLevel'
,
key
:
'riskLevel'
,
width
:
100
},
]
// 处理确定
const
handleOk
=
()
=>
{
emit
(
'ok'
)
emit
(
'update:visible'
,
false
)
}
// 处理取消
const
handleCancel
=
()
=>
{
emit
(
'cancel'
)
emit
(
'update:visible'
,
false
)
// 销毁图表实例
cleanupCharts
()
}
// 清理图表实例
const
cleanupCharts
=
()
=>
{
if
(
lineChart
)
{
lineChart
.
dispose
()
lineChart
=
null
}
if
(
barChart
)
{
barChart
.
dispose
()
barChart
=
null
}
if
(
pieChart
)
{
pieChart
.
dispose
()
pieChart
=
null
}
}
// 获取采集频率文本
const
getFreqText
=
(
freq
)
=>
{
const
map
=
{
1
:
'每日'
,
2
:
'每周'
,
3
:
'每月'
,
4
:
'每季度'
,
5
:
'每半年'
,
6
:
'每年'
}
return
map
[
freq
]
||
freq
}
// 获取风险等级状态
const
getRiskLevelStatus
=
(
level
)
=>
{
if
(
level
===
1
)
return
'success'
if
(
level
===
2
)
return
'processing'
if
(
level
===
3
)
return
'error'
return
'default'
}
// 获取风险等级文本
const
getRiskLevelText
=
(
level
)
=>
{
if
(
level
===
1
)
return
'低风险'
if
(
level
===
2
)
return
'中风险'
if
(
level
===
3
)
return
'高风险'
return
'其他'
}
// 格式化时间
const
formatTime
=
(
time
,
collFreq
)
=>
{
if
(
!
time
)
return
''
// 确保 time 是字符串
const
timeStr
=
String
(
time
)
// 确保 collFreq 是数字
const
freq
=
Number
(
collFreq
)
||
0
try
{
if
(
freq
==
1
)
{
return
timeStr
.
length
>=
10
?
timeStr
.
substr
(
5
,
5
)
:
timeStr
// MM-DD
}
else
if
(
freq
==
2
)
{
return
timeStr
.
length
>=
10
?
timeStr
.
substr
(
5
,
5
)
:
timeStr
// MM-DD
}
else
if
(
freq
==
3
||
freq
===
4
||
freq
===
5
)
{
return
timeStr
.
length
>=
7
?
timeStr
.
substr
(
0
,
7
)
:
timeStr
// YYYY-MM
}
else
if
(
freq
==
6
)
{
return
timeStr
.
length
>=
4
?
timeStr
.
substr
(
0
,
4
)
:
timeStr
// YYYY
}
else
{
return
timeStr
.
length
>=
17
?
timeStr
.
substr
(
11
,
16
)
:
timeStr
// HH:mm
}
}
catch
(
error
)
{
return
timeStr
}
}
// 加载数据
const
loadData
=
async
()
=>
{
if
(
!
props
.
row
)
return
chartLoading
.
value
=
true
try
{
// 获取表单数据
const
formData
=
getFieldsValue
()
queryByMtrcNo
({
mtrcNo
:
props
.
row
.
mtrcNo
,
}).
then
(
res
=>
{
curMtrcSet
.
value
=
res
||
{}
})
// 从接口获取数据
const
res
=
await
queryAllList
({
mtrcNos
:
props
.
row
.
mtrcNo
,
stFillTime
:
formData
.
stFillTime
,
endFillTime
:
formData
.
endFillTime
})
// 处理数据
if
(
res
&&
res
.
dataList
)
{
chartDataList
.
value
=
res
.
dataList
.
map
(
item
=>
{
const
formattedTime
=
formatTime
(
item
.
fillTime
,
curMtrcSet
.
value
.
collFreq
)
return
{
...
item
,
fillTime
:
formattedTime
}
})
}
else
{
chartDataList
.
value
=
[]
}
await
nextTick
()
// 根据当前激活的标签页初始化对应的图表
setTimeout
(()
=>
{
if
(
activeTabKey
.
value
===
'line'
)
{
initLineChart
()
}
else
if
(
activeTabKey
.
value
===
'bar'
)
{
initBarChart
()
}
else
if
(
activeTabKey
.
value
===
'pie'
)
{
initPieChart
()
}
},
200
)
}
catch
(
error
)
{
chartDataList
.
value
=
[]
}
finally
{
chartLoading
.
value
=
false
}
}
// 查询
const
searchQuery
=
()
=>
{
loadData
()
}
// 重置
const
searchReset
=
()
=>
{
setFieldsValue
({
stFillTime
:
(
new
Date
().
getFullYear
()
-
3
)
+
"-"
+
(
new
Date
().
getMonth
()
+
1
)
+
"-"
+
(
new
Date
().
getDate
()),
endFillTime
:
new
Date
()
})
loadData
()
}
// 初始化所有图表
const
initAllCharts
=
()
=>
{
// 注意:由于标签页可能未激活,容器可能不存在,所以这里不直接初始化
// 图表会在标签切换时初始化
}
// 获取图表数据
const
getChartData
=
()
=>
{
const
categories
=
chartDataList
.
value
.
map
(
item
=>
item
.
fillTime
)
const
values
=
chartDataList
.
value
.
map
(
item
=>
{
const
val
=
parseFloat
(
item
.
fillVals
)
||
0
return
val
})
// 按风险等级统计饼图数据
const
riskCount
=
{
1
:
0
,
// 低风险
2
:
0
,
// 中风险
3
:
0
// 高风险
}
chartDataList
.
value
.
forEach
(
item
=>
{
if
(
item
.
riskLevel
&&
riskCount
[
item
.
riskLevel
]
!==
undefined
)
{
riskCount
[
item
.
riskLevel
]
++
}
})
const
pieData
=
[]
// 按固定顺序添加数据项,并指定颜色
if
(
riskCount
[
1
]
>
0
)
{
pieData
.
push
({
value
:
riskCount
[
1
],
name
:
'低风险'
,
itemStyle
:
{
color
:
'#73D13D'
}
})
}
if
(
riskCount
[
2
]
>
0
)
{
pieData
.
push
({
value
:
riskCount
[
2
],
name
:
'中风险'
,
itemStyle
:
{
color
:
'#FA8C16'
}
})
}
if
(
riskCount
[
3
]
>
0
)
{
pieData
.
push
({
value
:
riskCount
[
3
],
name
:
'高风险'
,
itemStyle
:
{
color
:
'#CF1322'
}
})
}
return
{
categories
,
values
,
pieData
}
}
// 初始化折线图
const
initLineChart
=
()
=>
{
if
(
!
lineChartRef
.
value
)
{
return
}
if
(
lineChart
)
{
lineChart
.
dispose
()
}
lineChart
=
echarts
.
init
(
lineChartRef
.
value
)
const
{
categories
,
values
}
=
getChartData
()
const
option
=
{
title
:
{
text
:
`
${
props
.
row
?.
mtrcName
}
-
趋势分析
`,
left: 'center',
top: 10,
textStyle: {
fontSize: 16,
fontWeight: 'normal'
}
},
tooltip: {
trigger: 'axis',
formatter: function(params) {
return `
$
{
params
[
0
].
name
}
<
br
/>
$
{
params
[
0
].
marker
}
$
{
params
[
0
].
seriesName
}:
$
{
params
[
0
].
value
}
`
}
},
grid
:
{
left
:
'8%'
,
right
:
'5%'
,
top
:
'15%'
,
bottom
:
'8%'
,
containLabel
:
true
},
xAxis
:
{
type
:
'category'
,
data
:
categories
.
length
>
0
?
categories
:
[
'无数据'
],
axisLabel
:
{
rotate
:
categories
.
length
>
10
?
30
:
0
,
interval
:
categories
.
length
>
20
?
2
:
0
},
axisLine
:
{
lineStyle
:
{
color
:
'#999'
}
}
},
yAxis
:
{
type
:
'value'
,
name
:
`单位[
${
props
.
row
?.
unit
||
''
}]
`,
nameLocation: 'middle',
nameGap: 45,
splitLine: {
lineStyle: { type: 'dashed', color: '#eee' }
}
},
series: [{
name: props.row?.mtrcName || '指标数值',
data: values.length > 0 ? values : [0],
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 6,
lineStyle: {
width: 3,
color: '#409eff'
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(64, 158, 255, 0.3)' },
{ offset: 1, color: 'rgba(64, 158, 255, 0.05)' }
])
},
markPoint: {
data: [
{ type: 'max', name: '最大值' },
{ type: 'min', name: '最小值' }
]
},
markLine: {
data: [
{ type: 'average', name: '平均值' }
]
}
}]
}
lineChart.setOption(option)
lineChart.resize()
}
// 初始化柱状图
const initBarChart = () => {
if (!barChartRef.value) {
return
}
if (barChart) {
barChart.dispose()
}
barChart = echarts.init(barChartRef.value)
const { categories, values } = getChartData()
const option = {
title: {
text: `
$
{
props
.
row
?.
mtrcName
}
-
对比分析
`,
left: 'center',
top: 10,
textStyle: {
fontSize: 16,
fontWeight: 'normal'
}
},
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' },
formatter: function(params) {
return `
$
{
params
[
0
].
name
}
<
br
/>
$
{
params
[
0
].
marker
}
$
{
params
[
0
].
seriesName
}:
$
{
params
[
0
].
value
}
`
}
},
grid: {
left: '8%',
right: '5%',
top: '15%',
bottom: '8%',
containLabel: true
},
xAxis: {
type: 'category',
data: categories.length > 0 ? categories : ['无数据'],
axisLabel: {
rotate: categories.length > 10 ? 30 : 0,
interval: categories.length > 20 ? 2 : 0
},
axisLine: {
lineStyle: { color: '#999' }
}
},
yAxis: {
type: 'value',
name: `
单位
[
$
{
props
.
row
?.
unit
||
''
}]
`,
nameLocation: 'middle',
nameGap: 45,
splitLine: {
lineStyle: { type: 'dashed', color: '#eee' }
}
},
series: [{
name: props.row?.mtrcName || '指标数值',
data: values.length > 0 ? values : [0],
type: 'bar',
barWidth: '50%',
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
]),
borderRadius: [6, 6, 0, 0]
},
label: {
show: values.length <= 20,
position: 'top',
color: '#333',
fontSize: 11,
formatter: '{c}'
},
markPoint: {
data: [
{ type: 'max', name: '最大值' },
{ type: 'min', name: '最小值' }
]
}
}]
}
barChart.setOption(option)
barChart.resize()
}
// 初始化饼图
const initPieChart = () => {
if (!pieChartRef.value) {
return
}
if (pieChart) {
pieChart.dispose()
}
pieChart = echarts.init(pieChartRef.value)
const { pieData } = getChartData()
if (pieData.length === 0) {
pieData.push({ value: 1, name: '暂无数据' })
}
const option = {
title: {
text: `
$
{
props
.
row
?.
mtrcName
}
-
风险分布
`,
left: 'center',
top: 10,
textStyle: {
fontSize: 16,
fontWeight: 'normal'
}
},
tooltip: {
trigger: 'item',
formatter: '{b}<br/>{c} ({d}%)'
},
legend: {
orient: 'horizontal',
bottom: 20,
left: 'center',
itemWidth: 25,
itemHeight: 14
},
series: [{
name: '风险分布',
type: 'pie',
radius: ['45%', '70%'],
center: ['50%', '45%'],
avoidLabelOverlap: true,
itemStyle: {
borderRadius: 8,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: true,
position: 'outside',
formatter: '{b}: {d}%',
fontSize: 11
},
emphasis: {
scale: true,
label: { show: true, fontWeight: 'bold' }
},
data: pieData
}]
}
pieChart.setOption(option)
pieChart.resize()
}
// 标签切换处理
const handleTabChange = (key) => {
setTimeout(() => {
if (key === 'line') {
initLineChart()
} else if (key === 'bar') {
initBarChart()
} else if (key === 'pie') {
initPieChart()
}
}, 100)
}
// 监听可见性变化
watch(() => props.visible, async (newVal) => {
if (newVal) {
activeTabKey.value = 'list' // 默认选中列表
await loadData()
} else {
cleanupCharts()
}
})
</
script
>
<
style
scoped
>
</
style
>
\ No newline at end of file
zrch-risk-client-39/src/views/metric/approval/index.vue
浏览文件 @
9dd9c254
<
template
>
<div
style=
"
height: 100%;
padding: 10px;"
>
<div
style=
"padding: 10px;"
>
<a-row
style=
"height: 100%;"
:gutter=
"[8, 8]"
>
<a-col
:span=
"5"
>
<a-card
title=
""
:bordered=
"true"
style=
"width:100%;height:100%;"
>
<Left
@
searchData=
"setDataList"
></Left>
<a-card
:bordered=
"true"
style=
"width:100%;height:100%;"
>
<Left
@
searchData=
"handleLeftSearch"
@
resetData=
"handleLeftReset"
/>
</a-card>
</a-col>
<a-col
:span=
"19"
>
<!-- 时间搜索表单 -->
<div
style=
"margin-bottom: 16px; padding: 12px; background: #f9f9f9; border-radius: 4px;"
>
<a-row
:gutter=
"16"
align=
"middle"
>
<a-col
:span=
"1
4
"
>
<a-col
:span=
"1
6
"
>
<div
style=
"display: flex; align-items: center; gap: 16px;"
>
<div
style=
"display: flex; align-items: center;"
>
<span
style=
"margin-right: 8px;"
>
开始日期:
</span>
<a-date-picker
v-model:value=
"searchForm.st
Fill
Time"
style=
"width: 150px;"
/>
<a-date-picker
v-model:value=
"searchForm.st
art
Time"
style=
"width: 150px;"
/>
</div>
<div
style=
"display: flex; align-items: center;"
>
<span
style=
"margin-right: 8px;"
>
结束日期:
</span>
<a-date-picker
v-model:value=
"searchForm.endFillTime"
style=
"width: 150px;"
/>
<a-date-picker
v-model:value=
"searchForm.endTime"
style=
"width: 150px;"
/>
</div>
<div
style=
"display: flex; align-items: center;"
>
<span
style=
"margin-right: 8px;"
>
指标名称:
</span>
<a-input
v-model:value=
"searchForm.mtrcName"
placeholder=
"请输入指标名称"
style=
"width: 150px;"
/>
</div>
</div>
</a-col>
<a-col
:span=
"
10
"
>
<a-col
:span=
"
8
"
>
<a-space
:size=
"5"
style=
"margin-left:0px;"
>
<a-button
type=
"primary"
@
click=
"handleSearch"
>
查询
</a-button>
<a-button
type=
"primary"
@
click=
"handleSearch"
:loading=
"gridOptions.loading"
>
查询
</a-button>
<a-button
@
click=
"resetSearch"
>
重置
</a-button>
</a-space>
</a-col>
</a-row>
</div>
<vxe-grid
v-bind=
"gridOptions"
ref=
"tableRef"
>
<vxe-grid
v-bind=
"gridOptions"
ref=
"tableRef"
@
page-change=
"handlePageChange"
>
<template
#
toolbarButtons
>
<div
style=
"margin:2px 20px;size:15px"
>
指标填报列表:
</div>
<vxe-button
size=
"small"
@
click=
"handleApproval(1)
"
>
审批通过
</vxe-button>
<vxe-button
size=
"small"
@
click=
"handleApproval(2)
"
>
审批未通过
</vxe-button>
<vxe-button
size=
"small"
@
click=
"handleApproval(1)"
:loading=
"batchLoading
"
>
审批通过
</vxe-button>
<vxe-button
size=
"small"
@
click=
"handleApproval(2)"
:loading=
"batchLoading
"
>
审批未通过
</vxe-button>
<div
style=
"margin:auto"
>
共搜索到
<span
class=
"count-number"
>
{{
totalRecords
}}
</span>
条记录
</div>
</
template
>
<
template
#
active=
"{ row }"
>
<vxe-button
mode=
"text"
status=
"primary"
@
click=
"saveApproval(row.reportId,1)
"
>
通过
</vxe-button>
<vxe-button
mode=
"text"
status=
"error"
@
click=
"saveApproval(row.reportId,2)
"
>
退回
</vxe-button>
<vxe-button
mode=
"text"
status=
"primary"
@
click=
"saveApproval(row.reportId, 1)"
:loading=
"row._loading
"
>
通过
</vxe-button>
<vxe-button
mode=
"text"
status=
"error"
@
click=
"saveApproval(row.reportId, 2)"
:loading=
"row._loading
"
>
退回
</vxe-button>
</
template
>
<
template
#
mtrcName=
"{ row }"
>
<a
@
click=
"showChartModal(row)"
style=
"color: #409eff; cursor: pointer;"
>
...
...
@@ -53,24 +63,26 @@
</
template
>
</vxe-grid>
</a-col>
</a-row>
<!-- 图表弹窗组件 -->
<MetricChartModal
v-model:visible=
"chartModalVisible"
:title=
"chartModalTitle"
:row=
"currentRow"
@
cancel=
"handleModalClose"
/>
</a-row>
<!-- 图表弹窗组件 -->
<MetricChartModal
v-model:visible=
"chartModalVisible"
:title=
"chartModalTitle"
:row=
"currentRow"
@
cancel=
"handleModalClose"
/>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
{
reactive
,
onMounted
,
ref
}
from
'vue'
import
type
{
VxeGridProps
}
from
'vxe-table'
import
{
dataApprovalList
,
batchSaveApproval
}
from
'../MetricReport.api'
;
import
{
reactive
,
onMounted
,
ref
,
computed
}
from
'vue'
import
type
{
VxeGridProps
,
VxeGridInstance
}
from
'vxe-table'
import
{
debounce
}
from
'lodash-es'
import
{
dataApprovalList
,
batchSaveApproval
}
from
'../MetricReport.api'
import
Left
from
'./left.vue'
import
MetricChartModal
from
'./components/MetricChartModal.vue'
import
{
VXETable
}
from
'vxe-table'
interface
RowVO
{
id
:
number
...
...
@@ -81,8 +93,9 @@ interface RowVO {
address
:
string
}
const
tableRef
=
ref
()
const
totalRecords
=
ref
()
const
tableRef
=
ref
<
VxeGridInstance
>
()
const
totalRecords
=
ref
(
0
)
const
batchLoading
=
ref
(
false
)
// 图表弹窗
const
chartModalVisible
=
ref
(
false
)
...
...
@@ -91,203 +104,274 @@ const currentRow = ref<any>(null)
// 搜索表单
const
searchForm
=
reactive
({
stFillTime
:
null
,
endFillTime
:
null
startTime
:
null
,
endTime
:
null
,
mtrcName
:
''
})
// 左侧筛选条件
const
formData
=
reactive
({})
const
leftFormData
=
ref
({})
// 存储所有原始数据
const
allData
=
ref
<
any
[]
>
([])
// 防抖搜索函数
const
debouncedSearch
=
debounce
(()
=>
{
handleSearch
()
},
500
)
// 表格配置
const
gridOptions
=
reactive
<
VxeGridProps
<
RowVO
>>
({
border
:
true
,
showOverflow
:
true
,
keepSource
:
true
,
height
:
"auto"
,
maxHeight
:
"750px"
,
loading
:
false
,
exportConfig
:
{},
columnConfig
:
{
resizable
:
true
},
editConfig
:
{
trigger
:
'click'
,
mode
:
'row'
,
showStatus
:
true
// 分页配置 - 前端分页模式
pagerConfig
:
{
enabled
:
true
,
pageSize
:
10
,
currentPage
:
1
,
total
:
0
,
pageSizes
:
[
10
,
20
,
50
,
100
],
layouts
:
[
'PrevJump'
,
'PrevPage'
,
'Number'
,
'NextPage'
,
'NextJump'
,
'Sizes'
,
'Total'
],
perfect
:
true
},
cellStyle
({
row
,
column
})
{
if
(
column
.
field
===
'appSta'
)
{
if
(
row
.
appSta
==
'通过'
)
{
return
{
color
:
'blue'
}
}
else
if
(
row
.
appSta
==
'未通过'
)
{
return
{
color
:
'red'
}
}
else
if
(
row
.
appSta
==
'未审批'
)
{
return
{
backgroundColor
:
''
}
}
}
else
if
(
column
.
field
===
'riskLevel'
)
{
if
(
row
.
riskLevel
==
'低风险'
)
{
return
{
color
:
'#73D13D'
}
}
else
if
(
row
.
riskLevel
==
'中风险'
)
{
return
{
color
:
'#FA8C16'
}
}
else
if
(
row
.
riskLevel
==
'高风险'
)
{
return
{
color
:
'#CF1322'
}
}
// 工具栏配置
toolbarConfig
:
{
refresh
:
true
,
export
:
true
,
zoom
:
true
,
custom
:
true
,
slots
:
{
buttons
:
'toolbarButtons'
}
},
// 列配置
columns
:
[
{
type
:
'seq'
,
width
:
50
},
{
type
:
'checkbox'
,
width
:
50
},
{
field
:
'reportId'
,
title
:
'id'
,
visible
:
false
},
{
field
:
'reportId'
,
title
:
'id'
,
visible
:
false
},
{
field
:
'mtrcNo'
,
title
:
'指标编码'
,
sortable
:
true
},
{
field
:
'mtrcName'
,
title
:
'指标名称'
,
showOverflow
:
true
,
slots
:
{
default
:
'mtrcName'
}
},
{
field
:
'collFreq'
,
title
:
'采集频率'
,
},
{
field
:
'collFreq'
,
title
:
'采集频率'
},
{
field
:
'timeName'
,
title
:
'填报时间'
},
{
field
:
'riskLevel'
,
title
:
'风险等级'
},
{
field
:
'domainName'
,
title
:
'所属领域'
,
showOverflow
:
true
},
{
field
:
'mtrcCtp'
,
title
:
'指标类型'
},
{
field
:
'fillVals'
,
title
:
'填报值'
},
{
field
:
'appSta'
,
title
:
'状态'
,
},
{
field
:
'appSta'
,
title
:
'状态'
},
{
field
:
'active'
,
title
:
'审批'
,
width
:
150
,
fixed
:
'right'
,
slots
:
{
default
:
'active'
}
}
],
toolbarConfig
:
{
refresh
:
true
,
export
:
true
,
zoom
:
true
,
custom
:
true
,
slots
:
{
buttons
:
'toolbarButtons'
,
},
// 单元格样式
cellStyle
({
row
,
column
})
{
if
(
column
.
field
===
'appSta'
)
{
if
(
row
.
appSta
==
'通过'
)
{
return
{
color
:
'blue'
}
}
else
if
(
row
.
appSta
==
'未通过'
)
{
return
{
color
:
'red'
}
}
}
else
if
(
column
.
field
===
'riskLevel'
)
{
if
(
row
.
riskLevel
==
'低风险'
)
{
return
{
color
:
'#73D13D'
}
}
else
if
(
row
.
riskLevel
==
'中风险'
)
{
return
{
color
:
'#FA8C16'
}
}
else
if
(
row
.
riskLevel
==
'高风险'
)
{
return
{
color
:
'#CF1322'
}
}
}
},
data
:
[]
})
async
function
setDataList
(
params
=
{})
{
// 存储左侧筛选条件
Object
.
assign
(
formData
,
params
)
// 更新当前页数据
const
updatePageData
=
()
=>
{
const
{
currentPage
,
pageSize
}
=
gridOptions
.
pagerConfig
!
const
start
=
(
currentPage
-
1
)
*
pageSize
const
end
=
start
+
pageSize
gridOptions
.
data
=
allData
.
value
.
slice
(
start
,
end
)
// 合并时间搜索条件
// 更新分页总记录数
gridOptions
.
pagerConfig
!
.
total
=
allData
.
value
.
length
totalRecords
.
value
=
allData
.
value
.
length
}
// 加载数据
async
function
loadData
()
{
if
(
gridOptions
.
loading
)
return
// 合并所有搜索条件
const
searchParams
=
{
...
params
,
stFillTime
:
searchForm
.
stFillTime
,
endFillTime
:
searchForm
.
endFillTime
...
leftFormData
.
value
,
startTime
:
searchForm
.
startTime
,
endTime
:
searchForm
.
endTime
,
mtrcName
:
searchForm
.
mtrcName
}
console
.
log
(
'加载数据参数:'
,
searchParams
)
gridOptions
.
loading
=
true
try
{
const
res
=
await
dataApprovalList
(
searchParams
);
gridOptions
.
data
=
res
||
[]
totalRecords
.
value
=
res
.
length
const
res
=
await
dataApprovalList
(
searchParams
)
console
.
log
(
'返回数据:'
,
res
)
// 处理返回数据
if
(
Array
.
isArray
(
res
))
{
allData
.
value
=
res
}
else
if
(
res
&&
res
.
records
)
{
allData
.
value
=
res
.
records
}
else
if
(
res
&&
res
.
data
)
{
allData
.
value
=
res
.
data
}
else
{
allData
.
value
=
[]
}
// 重置到第一页
gridOptions
.
pagerConfig
!
.
currentPage
=
1
// 更新表格数据
updatePageData
()
}
catch
(
error
)
{
console
.
error
(
'加载数据失败:'
,
error
)
allData
.
value
=
[]
gridOptions
.
data
=
[]
totalRecords
.
value
=
0
gridOptions
.
pagerConfig
!
.
total
=
0
}
finally
{
gridOptions
.
loading
=
false
}
}
const
handleApproval
=
async
(
appSta
)
=>
{
const
ids
=
await
getSelectIds
();
if
(
ids
.
length
==
0
){
return
;
}
batchSaveApproval
({
ids
:
ids
,
appSta
:
appSta
},
setDataList
)
// 处理分页变化
const
handlePageChange
=
({
currentPage
,
pageSize
}:
{
currentPage
:
number
,
pageSize
:
number
})
=>
{
console
.
log
(
'分页变化:'
,
currentPage
,
pageSize
)
// 更新分页配置
gridOptions
.
pagerConfig
!
.
currentPage
=
currentPage
gridOptions
.
pagerConfig
!
.
pageSize
=
pageSize
// 前端分页:直接从 allData 中切片
updatePageData
()
}
const
saveApproval
=
async
(
id
,
sta
)
=>
{
batchSaveApproval
({
ids
:[
id
],
appSta
:
sta
},
function
(){
})
// 处理左侧搜索
function
handleLeftSearch
(
params
)
{
console
.
log
(
'左侧搜索:'
,
params
)
leftFormData
.
value
=
{
...
params
}
loadData
()
// 重新从后端获取数据
}
async
function
getSelectIds
()
{
let
ids
=
[];
const
$table
=
tableRef
.
value
;
if
(
$table
)
{
const
selRecords
=
$table
.
getCheckboxRecords
();
selRecords
.
forEach
(
function
(
ele
)
{
ids
.
push
(
ele
.
reportId
);
});
}
return
ids
;
// 处理左侧重置
function
handleLeftReset
()
{
console
.
log
(
'左侧重置'
)
leftFormData
.
value
=
{}
searchForm
.
startTime
=
null
searchForm
.
endTime
=
null
loadData
()
// 重新从后端获取数据
}
// 处理搜索
const
handleSearch
=
async
()
=>
{
await
setDataList
(
formData
)
async
function
handleSearch
()
{
console
.
log
(
'执行搜索'
)
await
loadData
()
// 重新从后端获取数据
}
// 重置搜索
const
resetSearch
=
()
=>
{
searchForm
.
stFillTime
=
null
searchForm
.
endFillTime
=
null
setDataList
({})
function
resetSearch
()
{
searchForm
.
startTime
=
null
searchForm
.
endTime
=
null
searchForm
.
mtrcName
=
''
handleSearch
()
}
onMounted
(
async
()
=>
{
await
setDataList
({});
})
// 批量审批
async
function
handleApproval
(
appSta
:
number
)
{
const
$table
=
tableRef
.
value
if
(
!
$table
)
return
const
selectRecords
=
$table
.
getCheckboxRecords
()
if
(
selectRecords
.
length
===
0
)
{
VXETable
.
modal
.
message
({
content
:
'请至少选择一条记录'
,
status
:
'warning'
})
return
}
const
ids
=
selectRecords
.
map
(
item
=>
item
.
reportId
)
batchLoading
.
value
=
true
try
{
await
batchSaveApproval
({
ids
:
ids
,
appSta
:
appSta
})
VXETable
.
modal
.
message
({
content
:
'操作成功'
,
status
:
'success'
})
// 重新加载数据
await
loadData
()
// 清空选中
$table
.
clearCheckboxRow
()
}
catch
(
error
)
{
console
.
error
(
'批量审批失败:'
,
error
)
VXETable
.
modal
.
message
({
content
:
'操作失败'
,
status
:
'error'
})
}
finally
{
batchLoading
.
value
=
false
}
}
// 单个审批
async
function
saveApproval
(
id
:
number
,
sta
:
number
)
{
const
row
=
gridOptions
.
data
.
find
(
item
=>
item
.
reportId
===
id
)
if
(
row
)
{
row
.
_loading
=
true
}
try
{
await
batchSaveApproval
({
ids
:
[
id
],
appSta
:
sta
})
VXETable
.
modal
.
message
({
content
:
'操作成功'
,
status
:
'success'
})
// 重新加载数据
await
loadData
()
}
catch
(
error
)
{
console
.
error
(
'审批失败:'
,
error
)
VXETable
.
modal
.
message
({
content
:
'操作失败'
,
status
:
'error'
})
}
finally
{
if
(
row
)
{
row
.
_loading
=
false
}
}
}
// 显示图表弹窗
const
showChartModal
=
(
row
)
=>
{
function
showChartModal
(
row
:
any
)
{
currentRow
.
value
=
row
chartModalTitle
.
value
=
`指标详情 -
${
row
.
mtrcName
}
`
chartModalVisible
.
value
=
true
}
// 处理弹窗关闭
const
handleModalClose
=
()
=>
{
function
handleModalClose
()
{
chartModalVisible
.
value
=
false
}
onMounted
(
async
()
=>
{
await
loadData
()
})
defineExpose
({
setDataList
,
loadData
,
refreshData
:
loadData
})
</
script
>
<
style
scoped
>
.custom-bottom
{
height
:
60px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
background
:
linear-gradient
(
135deg
,
#f8f9fa
0%
,
#e9ecef
100%
);
border-top
:
1px
solid
#e1e4e8
;
}
.record-count
{
display
:
flex
;
align-items
:
center
;
padding
:
8px
16px
;
background
:
white
;
border-radius
:
6px
;
box-shadow
:
0
2px
8px
rgba
(
0
,
0
,
0
,
0.1
);
font-size
:
14px
;
color
:
#606266
;
}
.record-count
i
{
margin-right
:
8px
;
color
:
#409eff
;
}
.count-number
{
font-weight
:
bold
;
color
:
#409eff
;
...
...
zrch-risk-client-39/src/views/metric/approval/left.vue
浏览文件 @
9dd9c254
...
...
@@ -5,15 +5,14 @@
ref=
"formRef"
:data=
"formData"
:loading=
"loading"
@
submit=
"submitEvent"
@
reset=
"resetEvent"
>
>
<vxe-form-item
title=
"年份"
field=
"qyear"
span=
"24"
>
<template
#
default=
"params"
>
<div
class=
"button-group"
>
<vxe-button
:mode=
"params.data.qyear === undefined ? 'button' : 'text'"
:status=
"params.data.qyear === undefined ? 'primary' : ''"
@
click=
"handleButtonClick('qyear', undefined
, params
)"
@
click=
"handleButtonClick('qyear', undefined)"
>
全部
</vxe-button>
...
...
@@ -22,20 +21,21 @@
:key=
"year"
:mode=
"params.data.qyear === year ? 'button' : 'text'"
:status=
"params.data.qyear === year ? 'primary' : ''"
@
click=
"handleButtonClick('qyear', year
, params
)"
@
click=
"handleButtonClick('qyear', year)"
>
{{
year
}}
</vxe-button>
</div>
</
template
>
</vxe-form-item>
<vxe-form-item
title=
"风险等级"
field=
"riskLevel"
span=
"24"
:item-render=
"{}"
title-overflow
>
<vxe-form-item
title=
"风险等级"
field=
"riskLevel"
span=
"24"
>
<
template
#
default=
"params"
>
<div
class=
"button-group"
>
<vxe-button
:mode=
"params.data.riskLevel === undefined ? 'button' : 'text'"
:status=
"params.data.riskLevel === undefined ? 'primary' : ''"
@
click=
"handleButtonClick('riskLevel', undefined
, params
)"
@
click=
"handleButtonClick('riskLevel', undefined)"
>
全部
</vxe-button>
...
...
@@ -44,20 +44,21 @@
:key=
"item.value"
:mode=
"params.data.riskLevel === item.value ? 'button' : 'text'"
:status=
"params.data.riskLevel === item.value ? 'primary' : ''"
@
click=
"handleButtonClick('riskLevel', item.value
, params
)"
@
click=
"handleButtonClick('riskLevel', item.value)"
>
{{
item
.
label
}}
</vxe-button>
</div>
</
template
>
</vxe-form-item>
<vxe-form-item
title=
"采集频率"
field=
"collFreq"
span=
"24"
:item-render=
"{}"
title-overflow
>
<vxe-form-item
title=
"采集频率"
field=
"collFreq"
span=
"24"
>
<
template
#
default=
"params"
>
<div
class=
"button-group"
>
<vxe-button
:mode=
"params.data.collFreq === undefined ? 'button' : 'text'"
:status=
"params.data.collFreq === undefined ? 'primary' : ''"
@
click=
"handleButtonClick('collFreq', undefined
, params
)"
@
click=
"handleButtonClick('collFreq', undefined)"
>
全部
</vxe-button>
...
...
@@ -66,20 +67,21 @@
:key=
"item.value"
:mode=
"params.data.collFreq === item.value ? 'button' : 'text'"
:status=
"params.data.collFreq === item.value ? 'primary' : ''"
@
click=
"handleButtonClick('collFreq', item.value
, params
)"
@
click=
"handleButtonClick('collFreq', item.value)"
>
{{
item
.
label
}}
</vxe-button>
</div>
</
template
>
</vxe-form-item>
<vxe-form-item
title=
"采集方法"
field=
"collMethod"
span=
"24"
:item-render=
"{}"
title-overflow
>
<vxe-form-item
title=
"采集方法"
field=
"collMethod"
span=
"24"
>
<
template
#
default=
"params"
>
<div
class=
"button-group"
>
<vxe-button
:mode=
"params.data.collMethod === undefined ? 'button' : 'text'"
:status=
"params.data.collMethod === undefined ? 'primary' : ''"
@
click=
"handleButtonClick('collMethod', undefined
, params
)"
@
click=
"handleButtonClick('collMethod', undefined)"
>
全部
</vxe-button>
...
...
@@ -88,34 +90,35 @@
:key=
"item.value"
:mode=
"params.data.collMethod === item.value ? 'button' : 'text'"
:status=
"params.data.collMethod === item.value ? 'primary' : ''"
@
click=
"handleButtonClick('collMethod', item.value
, params
)"
@
click=
"handleButtonClick('collMethod', item.value)"
>
{{
item
.
label
}}
</vxe-button>
</div>
</
template
>
</vxe-form-item>
<vxe-form-item
title=
"指标类型"
field=
"mtrcCtp"
span=
"24"
:item-render=
"{}"
title-overflow
>
<vxe-form-item
title=
"指标类型"
field=
"mtrcCtp"
span=
"24"
>
<
template
#
default=
"params"
>
<div
class=
"button-group"
>
<vxe-button
:mode=
"params.data.mtrcCtp === undefined ? 'button' : 'text'"
:status=
"params.data.mtrcCtp === undefined ? 'primary' : ''"
@
click=
"handleButtonClick('mtrcCtp', undefined
, params
)"
@
click=
"handleButtonClick('mtrcCtp', undefined)"
>
全部
</vxe-button>
<vxe-button
:mode=
"params.data.mtrcCtp === '1' ? 'button' : 'text'"
:status=
"params.data.mtrcCtp === '1' ? 'primary' : ''"
@
click=
"handleButtonClick('mtrcCtp', '1'
, params
)"
@
click=
"handleButtonClick('mtrcCtp', '1')"
>
基础指标
</vxe-button>
<vxe-button
:mode=
"params.data.mtrcCtp === '2' ? 'button' : 'text'"
:status=
"params.data.mtrcCtp === '2' ? 'primary' : ''"
@
click=
"handleButtonClick('mtrcCtp', '2'
, params
)"
@
click=
"handleButtonClick('mtrcCtp', '2')"
>
计算指标
</vxe-button>
...
...
@@ -123,210 +126,178 @@
</
template
>
</vxe-form-item>
<vxe-form-item
title=
"是否统计"
field=
"metrictype"
span=
"24"
:item-render=
"{}"
title-overflow
>
<vxe-form-item
title=
"是否统计"
field=
"mtrcTp"
span=
"24"
>
<
template
#
default=
"params"
>
<div
class=
"button-group"
>
<vxe-button
:mode=
"params.data.m
etrictype
=== undefined ? 'button' : 'text'"
:status=
"params.data.m
etrictype
=== undefined ? 'primary' : ''"
@
click=
"handleButtonClick('mtrcTp', undefined, params
)"
:mode=
"params.data.m
trcTp
=== undefined ? 'button' : 'text'"
:status=
"params.data.m
trcTp
=== undefined ? 'primary' : ''"
@
click=
"handleButtonClick('mtrcTp', undefined
)"
>
全部
</vxe-button>
<vxe-button
:mode=
"params.data.mtrcTp === '1' ? 'button' : 'text'"
:status=
"params.data.mtrcTp === '1' ? 'primary' : ''"
@
click=
"handleButtonClick('mtrcTp', '1'
, params
)"
@
click=
"handleButtonClick('mtrcTp', '1')"
>
统计
</vxe-button>
<vxe-button
:mode=
"params.data.m
etrictype
=== '2' ? 'button' : 'text'"
:mode=
"params.data.m
trcTp
=== '2' ? 'button' : 'text'"
:status=
"params.data.mtrcTp === '2' ? 'primary' : ''"
@
click=
"handleButtonClick('mtrcTp', '2'
, params
)"
@
click=
"handleButtonClick('mtrcTp', '2')"
>
不统计
</vxe-button>
</div>
</
template
>
</vxe-form-item>
<vxe-form-item
title=
"审批状态"
field=
"appSta"
span=
"24"
:item-render=
"{}"
title-overflow
>
<vxe-form-item
title=
"审批状态"
field=
"appSta"
span=
"24"
>
<
template
#
default=
"params"
>
<div
class=
"button-group"
>
<vxe-button
:mode=
"params.data.appSta === undefined ? 'button' : 'text'"
:status=
"params.data.appSta === undefined ? 'primary' : ''"
@
click=
"handleButtonClick('appSta', undefined
, params
)"
@
click=
"handleButtonClick('appSta', undefined)"
>
全部
</vxe-button>
<vxe-button
:mode=
"params.data.appSta === '1' ? 'button' : 'text'"
:status=
"params.data.appSta === '1' ? 'primary' : ''"
@
click=
"handleButtonClick('appSta', '1'
, params
)"
@
click=
"handleButtonClick('appSta', '1')"
>
通过
</vxe-button>
<vxe-button
:mode=
"params.data.appSta === '2' ? 'button' : 'text'"
:status=
"params.data.appSta === '2' ? 'primary' : ''"
@
click=
"handleButtonClick('appSta', '2'
, params
)"
@
click=
"handleButtonClick('appSta', '2')"
>
未通过
</vxe-button>
</div>
</
template
>
</vxe-form-item>
<vxe-form-item
title=
"指标名称"
field=
"mtrcName"
span=
"24"
:item-render=
"{}"
title-overflow
>
<
template
#
default=
"params"
>
<vxe-input
v-model=
"params.data.mtrcName"
placeholder=
"请输入名称"
clearable
@
change=
"changeEvent"
></vxe-input>
<!-- 添加搜索和重置按钮 -->
<!-- <vxe-form-item span="24">
<template #default>
<div style="display: flex; gap: 8px; justify-content: center;">
<vxe-button status="primary" @click="handleSubmit">查询</vxe-button>
<vxe-button @click="handleReset">重置</vxe-button>
</div>
</template>
</vxe-form-item>
</vxe-form-item>
-->
</vxe-form>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
,
onMounted
}
from
'vue'
import
{
Dayjs
}
from
'dayjs'
;
import
{
VXETable
,
VxeFormInstance
,
VxeFormPropTypes
,
VxeFormEvents
}
from
'vxe-table'
import
{
labelCol
}
from
'../../newlib/components/data/AuditCommon.data'
;
import
{
ref
,
onMounted
}
from
'vue'
interface
FormDataVO
{
qyear
:
number
|
undefined
qmonth
:
number
|
undefined
quarter
:
number
|
undefined
riskLevel
:
number
|
undefined
collMethod
:
number
|
undefined
collFreq
:
number
|
undefined
mtrcCtp
:
string
|
undefined
appSta
:
string
|
undefined
,
mtrcTp
:
string
|
undefined
,
qyear
:
number
|
undefined
qmonth
:
number
|
undefined
quarter
:
number
|
undefined
riskLevel
:
number
|
undefined
collMethod
:
number
|
undefined
collFreq
:
number
|
undefined
mtrcCtp
:
string
|
undefined
appSta
:
string
|
undefined
mtrcTp
:
string
|
undefined
}
const
emit
=
defineEmits
([
'searchData'
]);
const
formRef
=
ref
<
VxeFormInstance
>
()
const
yearOptions
=
ref
([]);
const
emit
=
defineEmits
([
'searchData'
,
'resetData'
])
const
formRef
=
ref
()
const
yearOptions
=
ref
<
number
[]
>
([])
const
loading
=
ref
(
false
)
const
formData
=
ref
<
FormDataVO
>
({
qyear
:
2025
,
qmonth
:
undefined
,
quarter
:
undefined
,
riskLevel
:
undefined
,
collMethod
:
undefined
,
collFreq
:
undefined
,
mtrcCtp
:
undefined
,
appSta
:
undefined
,
mtrcTp
:
undefined
,
riskLevel
:
undefined
,
collMethod
:
undefined
,
collFreq
:
undefined
,
mtrcCtp
:
undefined
,
appSta
:
undefined
,
mtrcTp
:
undefined
})
// 处理按钮点击事件
const
handleButtonClick
=
(
field
:
keyof
FormDataVO
,
value
:
any
,
params
:
any
)
=>
{
// 如果点击已选中的按钮,则取消选择
if
(
formData
.
value
[
field
]
===
value
)
{
formData
.
value
[
field
]
=
undefined
;
}
else
{
formData
.
value
[
field
]
=
value
;
}
const
$form
=
formRef
.
value
if
(
$form
)
{
$form
.
updateStatus
(
params
)
searchData
()
// 选项数据
const
riskLevelOptions
=
ref
([
{
label
:
'低风险'
,
value
:
1
},
{
label
:
'中风险'
,
value
:
2
},
{
label
:
'高风险'
,
value
:
3
}
])
const
collMethodOptions
=
ref
([
{
label
:
'手动'
,
value
:
1
},
{
label
:
'自动'
,
value
:
2
},
{
label
:
'人工或自动'
,
value
:
3
}
])
const
collFreqOptions
=
ref
([
{
label
:
'月'
,
value
:
3
},
{
label
:
'季'
,
value
:
4
},
{
label
:
'半年'
,
value
:
5
},
{
label
:
'年'
,
value
:
6
}
])
// 初始化年份选项
const
initYearOptions
=
()
=>
{
const
currentYear
=
new
Date
().
getFullYear
()
yearOptions
.
value
=
[]
for
(
let
i
=
currentYear
-
3
;
i
<=
currentYear
;
i
++
)
{
yearOptions
.
value
.
push
(
i
)
}
}
const
changeEvent
=
(
params
:
any
)
=>
{
const
$form
=
formRef
.
value
if
(
$form
)
{
$form
.
updateStatus
(
params
)
searchData
()
// 处理按钮点击
const
handleButtonClick
=
(
field
:
keyof
FormDataVO
,
value
:
any
)
=>
{
if
(
formData
.
value
[
field
]
===
value
)
{
formData
.
value
[
field
]
=
undefined
}
else
{
formData
.
value
[
field
]
=
value
}
}
const
submitEvent
:
VxeFormEvents
.
Submit
=
()
=>
{
loading
.
value
=
true
setTimeout
(()
=>
{
loading
.
value
=
false
VXETable
.
modal
.
message
({
content
:
'保存成功'
,
status
:
'success'
})
},
1000
)
handleSubmit
();
}
const
resetEvent
:
VxeFormEvents
.
Reset
=
()
=>
{
VXETable
.
modal
.
message
({
content
:
'重置事件'
,
status
:
'info'
})
// 处理输入变化
const
handleInputChange
=
()
=>
{
// 不立即搜索,等待用户点击查询按钮
}
const
getMonths
=
(
value
:
Dayjs
)
=>
{
const
localeData
=
value
.
localeData
();
const
months
=
[];
for
(
let
i
=
0
;
i
<
12
;
i
++
)
{
months
.
push
(
localeData
.
monthsShort
(
value
.
month
(
i
)));
}
return
months
;
};
// 处理提交查询
const
handleSubmit
=
()
=>
{
emit
(
'searchData'
,
{
...
formData
.
value
})
}
const
initYearOptions
=
()
=>
{
yearOptions
.
value
=
[];
const
currentYear
=
new
Date
().
getFullYear
();
for
(
let
i
=
currentYear
-
3
;
i
<=
currentYear
;
i
++
)
{
yearOptions
.
value
.
push
(
i
);
// 处理重置
const
handleReset
=
()
=>
{
formData
.
value
=
{
qyear
:
2025
,
qmonth
:
undefined
,
quarter
:
undefined
,
riskLevel
:
undefined
,
collMethod
:
undefined
,
collFreq
:
undefined
,
mtrcCtp
:
undefined
,
appSta
:
undefined
,
mtrcTp
:
undefined
}
};
const
monthOptions
=
ref
([
{
label
:
'1月'
,
value
:
1
},
{
label
:
'2月'
,
value
:
2
},
{
label
:
'3月'
,
value
:
3
},
{
label
:
'4月'
,
value
:
4
},
{
label
:
'5月'
,
value
:
5
},
{
label
:
'6月'
,
value
:
6
},
{
label
:
'7月'
,
value
:
7
},
{
label
:
'8月'
,
value
:
8
},
{
label
:
'9月'
,
value
:
9
},
{
label
:
'10月'
,
value
:
10
},
{
label
:
'11月'
,
value
:
11
},
{
label
:
'12月'
,
value
:
12
}
]);
const
quarterOptions
=
ref
([
{
label
:
'第一季度'
,
value
:
1
},
{
label
:
'第二季度'
,
value
:
2
},
{
label
:
'第三季度'
,
value
:
3
},
{
label
:
'第四季度'
,
value
:
4
}
]);
const
collMethodOptions
=
ref
([
{
label
:
'手动'
,
value
:
1
},
{
label
:
'自动'
,
value
:
2
},
{
label
:
'人工或自动'
,
value
:
3
},
]);
const
riskLevelOptions
=
ref
([
{
label
:
'低风险'
,
value
:
1
},
{
label
:
'中风险'
,
value
:
2
},
{
label
:
'高风险'
,
value
:
3
},
]);
const
collFreqOptions
=
ref
([
{
label
:
'月'
,
value
:
3
},
{
label
:
'季'
,
value
:
4
},
{
label
:
'半年'
,
value
:
5
},
{
label
:
'年'
,
value
:
6
},
]);
const
searchData
=
()
=>
{
emit
(
'searchData'
,
formData
.
value
);
emit
(
'resetData'
)
}
onMounted
(
async
()
=>
{
await
initYearOptions
();
onMounted
(()
=>
{
initYearOptions
()
})
</
script
>
...
...
zrch-risk-client-39/src/views/standardlib/base/StDomain.data.ts
浏览文件 @
9dd9c254
...
...
@@ -23,6 +23,7 @@ export const columns: BasicColumn[] = [
ellipsis
:
true
,
dataIndex
:
'domainDesc'
,
width
:
300
,
ifShow
:
false
,
},
{
title
:
'更新时间'
,
...
...
zrch-risk-client-39/src/views/standardlib/base/StDomainList.vue
浏览文件 @
9dd9c254
...
...
@@ -7,6 +7,8 @@
<a-button
type=
"primary"
@
click=
"handleCreate"
preIcon=
"ant-design:plus-outlined"
>
新建
</a-button>
<a-button
v-show=
"showBtn"
type=
"primary"
preIcon=
"ant-design:export-outlined"
@
click=
"onExportXls"
>
导出
</a-button>
<j-upload-button
v-show=
"showBtn"
type=
"primary"
preIcon=
"ant-design:import-outlined"
@
click=
"onImportXls"
>
导入
</j-upload-button>
<a-button
type=
"primary"
@
click=
"handleExpandAll"
preIcon=
"ant-design:down-outlined"
>
展开所有
</a-button>
<a-button
type=
"primary"
@
click=
"handleCollapseAll"
preIcon=
"ant-design:up-outlined"
>
折叠所有
</a-button>
<a-dropdown
v-show=
"showBtn"
v-if=
"selectedRowKeys.length > 0"
>
<template
#
overlay
>
...
...
@@ -217,7 +219,6 @@ import { downloadFile } from '/@/utils/common/renderUtils';
getDataByResult
(
result
.
items
);
setTimeout
(()
=>
{
loadDataByExpandedRows
()
nextTick
(
expandAll
)
},
800
);
}
...
...
@@ -281,10 +282,7 @@ import { downloadFile } from '/@/utils/common/renderUtils';
//判断是否标记了带有子节点
if
(
item
[
"hasChild"
]
==
'1'
){
let
loadChild
=
{
id
:
item
.
id
+
'_loadChild'
,
name
:
'loading...'
,
isLoading
:
true
}
console
.
log
(
loadChild
)
item
.
children
=
[
loadChild
]
// // 设置展开的key
handleExpand
(
true
,
item
)
}
return
item
})
...
...
@@ -394,6 +392,51 @@ import { downloadFile } from '/@/utils/common/renderUtils';
]
}
/**
* 展开所有节点
*/
async
function
handleExpandAll
()
{
// 展开所有节点
expandAll
();
// 加载所有子节点数据
const
dataSource
=
getDataSource
();
await
loadAllChildren
(
dataSource
);
}
/**
* 折叠所有节点
*/
function
handleCollapseAll
()
{
// 清空展开的节点
expandedRowKeys
.
value
=
[];
// 重新加载表格数据,确保所有节点都折叠
reload
();
}
/**
* 递归加载所有子节点数据
*/
async
function
loadAllChildren
(
nodes
)
{
if
(
!
nodes
||
nodes
.
length
===
0
)
return
;
for
(
const
node
of
nodes
)
{
if
(
node
.
children
&&
node
.
children
.
length
>
0
&&
node
.
children
[
0
].
isLoading
)
{
let
data
=
getFormVlaue
();
if
(
data
.
level
!==
"1"
)
{
let
result
=
await
getChildList
({
upperDomainCode
:
node
.
domainCode
,
level
:
data
.
level
,
domainName
:
data
.
domainName
});
result
=
result
.
records
?
result
.
records
:
result
;
if
(
result
&&
result
.
length
>
0
)
{
node
.
children
=
getDataByResult
(
result
);
await
loadAllChildren
(
node
.
children
);
}
}
}
else
if
(
node
.
children
&&
node
.
children
.
length
>
0
)
{
await
loadAllChildren
(
node
.
children
);
}
}
}
</
script
>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论