Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
zrch-risk-39
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Administrator
zrch-risk-39
Commits
072342b1
提交
072342b1
authored
2月 05, 2026
作者:
kxjia
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
修改验证功能
上级
0bdc8778
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
255 行增加
和
10 行删除
+255
-10
Tb1.vue
...isk-client-39/src/views/baosong/report/components/Tb1.vue
+17
-2
ValidationDrawer.vue
...iews/baosong/report/components/check/ValidationDrawer.vue
+229
-7
BaosongTaskReviewList.vue
...ent-39/src/views/baosong/review/BaosongTaskReviewList.vue
+9
-1
没有找到文件。
zrch-risk-client-39/src/views/baosong/report/components/Tb1.vue
浏览文件 @
072342b1
...
...
@@ -278,7 +278,6 @@
<vxe-textarea
:rows=
"row.remarks.rows"
v-model=
"formData[getFieldKey(row.code, row.remarks.field)]"
:disabled=
"!row.hasRight"
/>
</
template
>
</vxe-column>
...
...
@@ -921,10 +920,26 @@ const buildExpression = (formula: string, rowCode: string): string => {
for
(
const
fieldName
of
uniqueFields
)
{
const
key
=
getFieldKey
(
rowCode
,
fieldName
)
const
value
=
formData
[
key
]
if
(
value
!==
undefined
)
{
// 检查字段类型,如果是日期类型,转换为时间戳进行比较
const
row
=
tableFormData
.
find
((
r
:
TableRow
)
=>
r
.
code
===
rowCode
)
let
processedValue
=
value
if
(
row
&&
row
.
content
&&
Array
.
isArray
(
row
.
content
))
{
const
fieldItem
=
row
.
content
.
find
((
c
:
ContentItem
)
=>
c
.
field
===
fieldName
)
if
(
fieldItem
&&
fieldItem
.
type
===
'date'
)
{
// 将日期字符串转换为时间戳(毫秒)
const
date
=
new
Date
(
value
)
if
(
!
isNaN
(
date
.
getTime
()))
{
processedValue
=
date
.
getTime
()
}
}
}
expression
=
expression
.
replace
(
new
RegExp
(
`\\b
${
fieldName
}
\\b`
,
'g'
),
`Number(
${
v
alue
}
)`
`Number(
${
processedV
alue
}
)`
)
}
}
...
...
zrch-risk-client-39/src/views/baosong/report/components/check/ValidationDrawer.vue
浏览文件 @
072342b1
...
...
@@ -11,6 +11,39 @@
>
<template
#
default
>
<div
class=
"validation-results"
>
<!-- Tab 切换 -->
<div
class=
"result-tabs"
>
<div
class=
"tab-item"
:class=
"
{ active: activeTab === 'all' }"
@click="activeTab = 'all'"
>
全部 (
{{
validationResultsList
.
length
}}
)
</div>
<div
class=
"tab-item"
:class=
"
{ active: activeTab === 'passed' }"
@click="activeTab = 'passed'"
>
通过 (
{{
validationResultsList
.
filter
(
item
=>
item
.
isValid
).
length
}}
)
</div>
<div
class=
"tab-item"
:class=
"
{ active: activeTab === 'failed' }"
@click="activeTab = 'failed'"
>
未通过 (
{{
validationResultsList
.
filter
(
item
=>
!
item
.
isValid
).
length
}}
)
</div>
<div
class=
"tab-item"
:class=
"
{ active: activeTab === 'unfilled' }"
@click="activeTab = 'unfilled'"
>
未填报 (
{{
unfilledFields
.
length
}}
)
</div>
</div>
<!-- 统计信息 -->
<div
class=
"result-summary"
>
<div
class=
"summary-item"
>
<span
class=
"summary-label"
>
校验字段数:
</span>
...
...
@@ -24,7 +57,12 @@
<span
class=
"summary-label"
>
失败:
</span>
<span
class=
"summary-value error"
>
{{
validationResultsList
.
filter
(
item
=>
!
item
.
isValid
).
length
}}
</span>
</div>
<div
class=
"summary-item"
>
<span
class=
"summary-label"
>
未填报:
</span>
<span
class=
"summary-value warning"
>
{{
unfilledFields
.
length
}}
</span>
</div>
</div>
<div
class=
"process-log"
v-if=
"showProcessLog && validationProcess.length > 0"
>
<h4>
执行过程:
</h4>
<div
class=
"process-content"
>
...
...
@@ -33,17 +71,39 @@
</div>
</div>
</div>
<div
class=
"results-list"
>
<!-- 未填报字段列表 -->
<div
v-if=
"activeTab === 'unfilled'"
class=
"results-list"
>
<div
v-for=
"(field, index) in unfilledFields"
:key=
"index"
class=
"result-item unfilled"
>
<div
class=
"result-field"
>
{{
field
.
rowCode
}}
-
{{
field
.
fieldName
}}
</div>
<div
class=
"result-desc"
>
{{
field
.
description
}}
</div>
</div>
</div>
<!-- 校验结果列表 -->
<div
v-else
class=
"results-list"
>
<div
v-for=
"(result, index) in
validationResultsList
"
v-for=
"(result, index) in
filteredResults
"
:key=
"index"
class=
"result-item"
:class=
"
{ success: result.isValid, error: !result.isValid }"
@click="handleValidationResultClick(result)"
>
<div
class=
"result-field"
>
{{
result
.
description
}}
【
{{
result
.
field
}}
】
</div>
<div
class=
"result-field"
>
{{
result
.
description
}}
</div>
<div
class=
"result-formula"
>
公式:
{{
result
.
formula
}}
</div>
<div
class=
"result-value"
>
值:
{{
formatFieldValue
(
result
.
fieldValue
)
}}
</div>
<div
v-if=
"result.fieldValues && Object.keys(result.fieldValues).length > 0"
class=
"result-params"
>
<span
class=
"params-title"
>
参数值:
</span>
<span
v-for=
"(value, key, index) in result.fieldValues"
:key=
"key"
class=
"param-item"
>
<span
class=
"param-name"
>
{{
key
}}
=
{{
formatFieldValue
(
value
)
}}
</span>
<span
v-if=
"index
<
Object
.
keys
(
result
.
fieldValues
).
length
-
1
"
class=
"param-separator"
>
,
</span>
</span>
</div>
<div
v-if=
"result.evaluatedFormula"
class=
"result-evaluated"
>
替换后公式:
{{
result
.
evaluatedFormula
}}
</div>
<div
class=
"result-value"
>
当前字段值:
{{
formatFieldValue
(
result
.
fieldValue
)
}}
</div>
<div
v-if=
"!result.isValid"
class=
"result-error"
>
失败原因:
{{
result
.
description
}}
</div>
</div>
</div>
...
...
@@ -72,7 +132,7 @@
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
,
watch
}
from
'vue'
import
{
ref
,
watch
,
computed
}
from
'vue'
interface
ValidationResult
{
field
:
string
...
...
@@ -81,6 +141,8 @@ interface ValidationResult {
isValid
:
boolean
fieldValue
:
any
rowCode
:
string
fieldValues
:
Record
<
string
,
any
>
evaluatedFormula
:
string
}
interface
ValidationFormula
{
...
...
@@ -92,10 +154,17 @@ interface TableRow {
code
:
string
content
:
Array
<
{
field
:
string
type
?:
string
[
key
:
string
]:
any
}
>
}
interface
UnfilledField
{
rowCode
:
string
fieldName
:
string
description
:
string
}
const
props
=
defineProps
({
modelValue
:
{
type
:
Boolean
,
...
...
@@ -116,11 +185,52 @@ const showProcessLog = ref(false)
const
validationTooltipVisible
=
ref
(
false
)
const
validationTooltipPosition
=
ref
({
left
:
0
,
top
:
0
})
const
validationTooltipContent
=
ref
(
''
)
const
activeTab
=
ref
(
'all'
)
// 通过外部传入的数据
const
validFormula
=
ref
<
ValidationFormula
[]
>
([])
const
formData
=
ref
<
Record
<
string
,
any
>>
({})
// 计算属性:过滤后的结果
const
filteredResults
=
computed
(()
=>
{
if
(
activeTab
.
value
===
'all'
)
{
return
validationResultsList
.
value
}
else
if
(
activeTab
.
value
===
'passed'
)
{
return
validationResultsList
.
value
.
filter
(
item
=>
item
.
isValid
)
}
else
if
(
activeTab
.
value
===
'failed'
)
{
return
validationResultsList
.
value
.
filter
(
item
=>
!
item
.
isValid
)
}
return
validationResultsList
.
value
})
// 计算属性:未填报字段
const
unfilledFields
=
computed
<
UnfilledField
[]
>
(()
=>
{
const
fields
:
UnfilledField
[]
=
[]
props
.
tableFormData
.
forEach
((
row
)
=>
{
if
(
row
.
content
&&
Array
.
isArray
(
row
.
content
))
{
row
.
content
.
forEach
((
item
)
=>
{
if
(
item
.
field
)
{
const
key
=
`
${
row
.
code
}
_
${
item
.
field
}
`
const
value
=
formData
.
value
[
key
]
if
(
value
===
undefined
||
value
===
null
||
value
===
''
)
{
// 查找该字段的校验公式
const
formula
=
validFormula
.
value
.
find
(
f
=>
f
.
formula
.
includes
(
item
.
field
))
fields
.
push
({
rowCode
:
row
.
code
,
fieldName
:
item
.
field
,
description
:
formula
?.
des
||
'未填报'
})
}
}
})
}
})
return
fields
})
watch
(()
=>
props
.
modelValue
,
(
newVal
)
=>
{
drawerVisible
.
value
=
newVal
})
...
...
@@ -141,6 +251,7 @@ const performValidation = () => {
validationProcess
.
value
.
push
(
`找到
${
validFormula
.
value
.
length
}
个验证公式`
)
validFormula
.
value
.
forEach
((
formulaItem
:
ValidationFormula
)
=>
{
validationProcess
.
value
.
push
(
`开始校验公式:
${
formulaItem
.
des
}
`
)
const
result
=
evaluateFormula
(
formulaItem
.
formula
,
formulaItem
.
des
)
...
...
@@ -170,6 +281,8 @@ const evaluateFormula = (formula: string, description: string): ValidationResult
r
.
content
?.
some
((
c
:
any
)
=>
c
.
field
===
fieldName
)
)
console
.
log
(
row
)
if
(
!
row
)
{
validationProcess
.
value
.
push
(
`跳过: 未找到字段
${
fieldName
}
所在的行`
)
return
null
...
...
@@ -207,14 +320,29 @@ const evaluateFormula = (formula: string, description: string): ValidationResult
uniqueFields
.
sort
((
a
,
b
)
=>
b
.
length
-
a
.
length
);
const
fieldValues
:
Record
<
string
,
any
>
=
{};
let
expression
=
formula
;
for
(
const
fieldName
of
uniqueFields
)
{
const
key
=
`
${
row
.
code
}
_
${
fieldName
}
`
;
const
value
=
formData
.
value
[
key
];
fieldValues
[
fieldName
]
=
value
;
if
(
value
!==
undefined
&&
value
!==
''
)
{
// 检查字段类型,如果是日期类型,转换为时间戳进行比较
const
fieldItem
=
row
.
content
.
find
((
c
:
any
)
=>
c
.
field
===
fieldName
);
let
processedValue
=
value
;
if
(
fieldItem
&&
fieldItem
.
type
===
'date'
)
{
// 将日期字符串转换为时间戳(毫秒)
const
date
=
new
Date
(
value
);
if
(
!
isNaN
(
date
.
getTime
()))
{
processedValue
=
date
.
getTime
();
}
}
expression
=
expression
.
replace
(
new
RegExp
(
`\\b
${
fieldName
}
\\b`
,
'g'
),
`
Number(
${
value
}
)
`
`
${
processedValue
}
`
);
}
}
...
...
@@ -232,7 +360,9 @@ const evaluateFormula = (formula: string, description: string): ValidationResult
formula
:
formula
,
isValid
:
isValid
,
fieldValue
:
fieldValue
,
rowCode
:
row
.
code
rowCode
:
row
.
code
,
fieldValues
:
fieldValues
,
evaluatedFormula
:
expression
}
}
catch
(
error
)
{
validationProcess
.
value
.
push
(
`公式执行错误:
${
error
instanceof
Error
?
error
.
message
:
String
(
error
)}
`
)
...
...
@@ -323,6 +453,38 @@ defineExpose({
flex-direction: column;
}
.result-tabs {
display: flex;
gap: 8px;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 2px solid #e8e8e8;
}
.tab-item {
padding: 8px 16px;
cursor: pointer;
border-radius: 4px 4px 0 0;
font-size: 14px;
color: #666;
background-color: #f5f5f5;
transition: all 0.3s;
border: 1px solid #e8e8e8;
border-bottom: none;
&:hover {
background-color: #e6f7ff;
color: #1890ff;
}
&.active {
background-color: #1890ff;
color: white;
border-color: #1890ff;
font-weight: bold;
}
}
.result-summary {
display: flex;
gap: 20px;
...
...
@@ -355,6 +517,10 @@ defineExpose({
color: #ff4d4f;
}
.summary-value.warning {
color: #faad14;
}
.process-log {
margin: 15px 0;
padding: 10px;
...
...
@@ -422,6 +588,15 @@ defineExpose({
}
}
.result-item.unfilled {
background-color: #fffbe6;
border-left: 4px solid #faad14;
&:hover {
background-color: #fff1b8;
}
}
.result-field {
font-weight: bold;
margin-bottom: 5px;
...
...
@@ -445,6 +620,53 @@ defineExpose({
word-break: break-all;
}
.result-params {
margin: 8px 0;
padding: 8px;
background-color: rgba(24, 144, 255, 0.05);
border-radius: 4px;
border: 1px dashed #1890ff;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 4px;
}
.params-title {
font-size: 12px;
color: #1890ff;
font-weight: bold;
}
.param-item {
display: inline-flex;
align-items: center;
font-size: 12px;
}
.param-name {
color: #333;
font-family: monospace;
font-weight: 500;
}
.param-separator {
color: #999;
margin: 0 2px;
}
.result-evaluated {
font-size: 12px;
color: #52c41a;
font-family: monospace;
margin-bottom: 5px;
background-color: rgba(82, 196, 26, 0.05);
padding: 4px 6px;
border-radius: 2px;
word-break: break-all;
border-left: 3px solid #52c41a;
}
.result-value {
font-size: 12px;
color: #999;
...
...
zrch-risk-client-39/src/views/baosong/review/BaosongTaskReviewList.vue
浏览文件 @
072342b1
...
...
@@ -175,7 +175,7 @@
record
[
'token'
]
=
allReportData
.
value
;
let
retData
=
await
downLoadTaskXml
(
record
);
goTo
File
(
retData
);
handleDownload
File
(
retData
);
}
function
setRowkey
(
row
)
{
...
...
@@ -190,6 +190,14 @@
message
.
warning
(
'没有找到要下载的文件'
);
}
}
const
handleDownloadFile
=
(
filePath
)
=>
{
const
globOnlineViewUrl
:
string
=
import
.
meta
.
env
.
VITE_GLOB_ONLINE_VIEW_URL
;
const
url
=
globOnlineViewUrl
+
filePath
;
if
(
url
)
{
window
.
open
(
url
);
}
};
</
script
>
<
style
scoped
></
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论