vue3-element-plus-app-chu 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/view/dcps/digital-rmb-authorization/api.ts +3 -14
- package/src/view/dcps/digital-rmb-authorization/components/AuthorizationDetailDialog.vue +23 -14
- package/src/view/dcps/digital-rmb-authorization/index.vue +69 -32
- package/src/view/dcps/digital-rmb-authorization/runtime.ts +1 -3
- package/src/view/dcps/digital-rmb-authorization/typs.ts +25 -34
package/package.json
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { AuthorizationTask } from './typs'
|
|
1
|
+
import baseHttpClient from "@chic/http"
|
|
3
2
|
|
|
4
3
|
export default {
|
|
5
4
|
/**
|
|
@@ -9,22 +8,12 @@ export default {
|
|
|
9
8
|
* platfSeqNo 为平台流水号,taskSts 为任务状态(01 待审批、02 已通过、03 已拒绝)。
|
|
10
9
|
* 日期范围:createTmBegin、createTmEnd 为创建日期起止值,格式为 YYYYMMDD。
|
|
11
10
|
*/
|
|
12
|
-
queryListApi: (params: unknown) => post<
|
|
13
|
-
// 当前页的授权任务记录。
|
|
14
|
-
resultList: AuthorizationTask[]
|
|
15
|
-
// 符合筛选条件的总记录数,接口可能返回字符串或数字。
|
|
16
|
-
totalCount: string | number
|
|
17
|
-
}>>('/TAM/0001/140507001', params),
|
|
11
|
+
queryListApi: (params: unknown) => baseHttpClient.post<any>("/TAM/0001/140507001", params),
|
|
18
12
|
/**
|
|
19
13
|
* 提交单笔数字人民币授权任务的审批结果。
|
|
20
14
|
* @param params 审批参数:opType 固定为 authorize;platfSeqNo 为待审批任务的平台流水号。
|
|
21
15
|
* 审批结果:approveFlag 为 02(通过)或 03(拒绝);rmk 为备注,拒绝时填写原因。
|
|
22
16
|
* 审批身份:apprvrId、apprvrName 为审批人工号和姓名;apprUserId、userId 同样传审批人工号。
|
|
23
17
|
*/
|
|
24
|
-
authorizeApi: (params: unknown) => post<
|
|
25
|
-
// 业务处理状态,仅作返回字段;请求成功以 head.retCode 为准。
|
|
26
|
-
bizSts: string
|
|
27
|
-
// 审批结果状态,仅作返回字段,不参与请求成功判断。
|
|
28
|
-
resultSts: string
|
|
29
|
-
}>>('/TAM/0001/120507001', params),
|
|
18
|
+
authorizeApi: (params: unknown) => baseHttpClient.post<any>("/TAM/0001/120507001", params)
|
|
30
19
|
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
|
-
import type { AuthorizationTask } from '../typs'
|
|
4
3
|
|
|
5
4
|
// 父页面传入的弹窗状态、任务数据和操作权限。
|
|
6
5
|
const props = defineProps<{
|
|
7
6
|
// 是否显示详情弹窗。
|
|
8
7
|
modelValue: boolean
|
|
9
8
|
// 原始任务数据,用于判断审批状态和传递审批任务。
|
|
10
|
-
task:
|
|
9
|
+
task: any
|
|
11
10
|
// 父页面格式化后的金额、状态和时间,仅用于展示。
|
|
12
|
-
displayValues:
|
|
11
|
+
displayValues: any
|
|
13
12
|
// 页面正在查询或提交审批时,禁用详情中的审批入口。
|
|
14
13
|
disabled?: boolean
|
|
15
14
|
}>()
|
|
@@ -18,7 +17,7 @@ const emit = defineEmits<{
|
|
|
18
17
|
// visible 为更新后的弹窗显隐状态。
|
|
19
18
|
'update:modelValue': [visible: boolean]
|
|
20
19
|
// task 为用户选择审批的原始任务。
|
|
21
|
-
approve: [task:
|
|
20
|
+
approve: [task: any]
|
|
22
21
|
}>()
|
|
23
22
|
|
|
24
23
|
// 详情分组配置;title 为分组标题,fields 每项为 [任务字段名, 展示名称]。
|
|
@@ -71,7 +70,7 @@ const canApprove = computed(() =>
|
|
|
71
70
|
&& !!props.task.platfSeqNo?.trim(),
|
|
72
71
|
)
|
|
73
72
|
/** 读取详情展示值,空值显示占位符;field 为任务字段名。 */
|
|
74
|
-
const displayValue = (field:
|
|
73
|
+
const displayValue = (field: string) => props.displayValues?.[field]?.trim() || '—'
|
|
75
74
|
|
|
76
75
|
// 通知父页面打开审批弹窗,由父页面统一提交审批。
|
|
77
76
|
const approveTask = () => {
|
|
@@ -83,13 +82,14 @@ const approveTask = () => {
|
|
|
83
82
|
<el-dialog
|
|
84
83
|
:model-value="modelValue"
|
|
85
84
|
title="数字人民币授权详情"
|
|
85
|
+
style="--el-dialog-padding-primary: 10px; padding: 10px 16px; margin-bottom: 16px"
|
|
86
86
|
width="min(1280px, calc(100vw - 32px))"
|
|
87
|
-
top="
|
|
87
|
+
top="16px"
|
|
88
88
|
append-to-body
|
|
89
89
|
destroy-on-close
|
|
90
90
|
@update:model-value="emit('update:modelValue', $event)"
|
|
91
91
|
>
|
|
92
|
-
<el-scrollbar
|
|
92
|
+
<el-scrollbar class="detail-scrollbar">
|
|
93
93
|
<div v-if="task" class="detail-content">
|
|
94
94
|
<!-- 交易摘要 -->
|
|
95
95
|
<header class="detail-summary">
|
|
@@ -116,6 +116,7 @@ const approveTask = () => {
|
|
|
116
116
|
v-for="[field, label] in group.fields"
|
|
117
117
|
:key="field"
|
|
118
118
|
class="detail-field"
|
|
119
|
+
:class="{ 'detail-field--remark': field === 'rmk' }"
|
|
119
120
|
>
|
|
120
121
|
<dt>{{ label }}</dt>
|
|
121
122
|
<dd>{{ displayValue(field) }}</dd>
|
|
@@ -136,20 +137,28 @@ const approveTask = () => {
|
|
|
136
137
|
</template>
|
|
137
138
|
|
|
138
139
|
<style scoped>
|
|
139
|
-
|
|
140
|
-
.detail-
|
|
140
|
+
/* 为弹窗边距、标题和底部按钮预留空间,其余高度用于完整展示详情。 */
|
|
141
|
+
.detail-scrollbar :deep(.el-scrollbar__wrap) {
|
|
142
|
+
max-height: calc(100vh - 120px);
|
|
143
|
+
max-height: calc(100dvh - 120px);
|
|
144
|
+
}
|
|
145
|
+
.detail-content { display: grid; gap: 8px; font-size: 13px; line-height: 1.4; }
|
|
146
|
+
.detail-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; padding: 14px; border-radius: 8px; background: var(--el-color-primary-light-9); overflow-wrap: anywhere; }
|
|
141
147
|
.detail-label,
|
|
142
148
|
.detail-field dt { color: var(--el-text-color-secondary); font-size: 12px; }
|
|
143
149
|
.detail-amount { display: block; margin-top: 4px; color: var(--el-color-primary-dark-2); font-size: 24px; font-variant-numeric: tabular-nums; line-height: 1.3; }
|
|
144
150
|
.detail-status { display: block; margin-top: 6px; color: var(--el-text-color-primary); font-size: 15px; }
|
|
145
151
|
.detail-reference { display: grid; grid-column: span 2; align-content: start; gap: 4px; }
|
|
146
|
-
.detail-group { padding:
|
|
147
|
-
.detail-group h3 { margin: 0 0
|
|
148
|
-
.detail-fields { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap:
|
|
149
|
-
.detail-field { min-width: 0; padding: 12px; border-radius: 6px; background: var(--el-fill-color-lighter); }
|
|
150
|
-
.detail-field
|
|
152
|
+
.detail-group { display: grid; grid-template-columns: 72px minmax(0, 1fr); align-items: start; gap: 8px; padding: 12px; border: 1px solid var(--el-border-color-lighter); border-radius: 8px; }
|
|
153
|
+
.detail-group h3 { margin: 4px 0 0; padding-left: 8px; border-left: 3px solid var(--el-color-primary); color: var(--el-text-color-primary); font-size: 14px; line-height: 20px; }
|
|
154
|
+
.detail-fields { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin: 0; }
|
|
155
|
+
.detail-field { min-width: 0; padding: 8px 12px; border-radius: 6px; background: var(--el-fill-color-lighter); }
|
|
156
|
+
.detail-field--remark { grid-column: 1 / -1; }
|
|
157
|
+
.detail-field dd { margin: 2px 0 0; color: var(--el-text-color-primary); font-weight: 600; overflow-wrap: anywhere; white-space: pre-wrap; }
|
|
151
158
|
|
|
152
159
|
@media (max-width: 1024px) {
|
|
160
|
+
.detail-group { grid-template-columns: minmax(0, 1fr); }
|
|
161
|
+
.detail-group h3 { margin-top: 0; }
|
|
153
162
|
.detail-summary,
|
|
154
163
|
.detail-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
155
164
|
}
|
|
@@ -5,7 +5,10 @@ import { ArtDataTable, type ColumnOption, type PaginationOptions, type TableSett
|
|
|
5
5
|
import AuthorizationDetailDialog from './components/AuthorizationDetailDialog.vue'
|
|
6
6
|
import API from './api'
|
|
7
7
|
import runtime from './runtime'
|
|
8
|
-
import type {
|
|
8
|
+
import type { AuthorizationFilters, AuthorizationQueryParams, AuthorizationTask } from './typs'
|
|
9
|
+
|
|
10
|
+
type Decision = 'approve' | 'reject'
|
|
11
|
+
type AmountSortOrder = 'ascending' | 'descending' | null
|
|
9
12
|
|
|
10
13
|
// 初始查询条件;空字符串表示不限制该条件,重置时恢复此配置。
|
|
11
14
|
const defaultFilters: AuthorizationFilters = {
|
|
@@ -16,7 +19,7 @@ const defaultFilters: AuthorizationFilters = {
|
|
|
16
19
|
taskSts: '', // 任务状态;空值查询全部状态。
|
|
17
20
|
}
|
|
18
21
|
// 默认创建日期范围:[开始日期, 结束日期],格式为 YYYYMMDD,查询重置时使用。
|
|
19
|
-
const defaultDates:
|
|
22
|
+
const defaultDates: [string, string] = [
|
|
20
23
|
runtime.createTmBegin,
|
|
21
24
|
runtime.createTmEnd,
|
|
22
25
|
]
|
|
@@ -38,9 +41,10 @@ const decisionActions = [
|
|
|
38
41
|
|
|
39
42
|
// 查询表单、列表和分页状态。
|
|
40
43
|
const filters = ref({ ...defaultFilters }) // 正在编辑的查询条件,点击查询后才生效。
|
|
41
|
-
const dateRange = ref<
|
|
44
|
+
const dateRange = ref<[string, string] | null>([...defaultDates]) // 当前选择的创建日期范围,格式为 YYYYMMDD,允许为空。
|
|
42
45
|
const showSearchBar = ref(true) // 筛选区是否显示,由表格工具栏切换。
|
|
43
46
|
const rows = ref<AuthorizationTask[]>([]) // 当前页的原始授权任务列表。
|
|
47
|
+
const amountSortOrder = ref<AmountSortOrder>(null) // 当前页金额的排序方向,null 保留接口返回顺序。
|
|
44
48
|
const pagination = reactive({ current: 1, size: 10, total: 0 }) // 当前页码、每页条数、符合查询条件的总条数。
|
|
45
49
|
const loading = ref(false) // 列表请求是否进行中,同时控制表格和查询按钮的加载状态。
|
|
46
50
|
let requestId = 0 // 最新列表请求的序号,用于忽略过期响应。
|
|
@@ -48,11 +52,11 @@ let disposed = false // 页面是否已卸载,避免未完成请求继续更
|
|
|
48
52
|
|
|
49
53
|
// 详情保留原始任务,格式化数据单独用于展示。
|
|
50
54
|
const detailDialogVisible = ref(false) // 详情弹窗是否显示。
|
|
51
|
-
const detailTask = ref<
|
|
55
|
+
const detailTask = ref<any>(null) // 当前查看详情的原始任务,未选择时为 null。
|
|
52
56
|
|
|
53
57
|
// 审批弹窗状态。
|
|
54
58
|
const dialogVisible = ref(false) // 审批弹窗是否显示。
|
|
55
|
-
const selectedTask = ref<
|
|
59
|
+
const selectedTask = ref<any>(null) // 本次待处理的任务,提交时读取平台流水号。
|
|
56
60
|
const remark = ref('') // 用户输入的审批备注,通过时选填,拒绝时必填。
|
|
57
61
|
const remarkError = ref('') // 拒绝原因的校验提示,空字符串表示没有错误。
|
|
58
62
|
const pendingDecision = ref<Decision | null>(null) // 正在提交的操作:approve 通过、reject 拒绝;null 表示空闲。
|
|
@@ -64,7 +68,7 @@ const paginationOptions: PaginationOptions = { align: 'right', background: false
|
|
|
64
68
|
// 提取异常提示;error 为捕获到的请求或处理异常。
|
|
65
69
|
const getErrorMessage = (error: unknown) => error instanceof Error ? error.message : '请求失败,请稍后重试'
|
|
66
70
|
// 判断 task 是否可审批:必须处于待审批状态,且平台流水号有效。
|
|
67
|
-
const canApprove = (task?:
|
|
71
|
+
const canApprove = (task?: any) => task?.taskSts === '01' && !!task.platfSeqNo?.trim()
|
|
68
72
|
// 将状态码 status 转为中文名称,未识别的状态保留原值。
|
|
69
73
|
const formatStatus = (status?: string) => statusLabels[status || ''] || status || '未知'
|
|
70
74
|
// 将接口时间 value 转为浏览器本地时间,空值显示横线,无效时间保留原文。
|
|
@@ -76,7 +80,10 @@ const formatDateTime = (value?: string) => {
|
|
|
76
80
|
|
|
77
81
|
// 将金额字符串 value 拆成符号、整数和小数,避免转为浮点数后丢失精度。
|
|
78
82
|
const parseAmount = (value?: string) => {
|
|
79
|
-
const
|
|
83
|
+
const text = String(value ?? '').trim()
|
|
84
|
+
// 仅去掉合法千分位分隔符,避免把格式错误的 1,23 当成正常金额。
|
|
85
|
+
const normalized = /^[+-]?\d{1,3}(?:,\d{3})+(?:\.\d*)?$/.test(text) ? text.replace(/,/g, '') : text
|
|
86
|
+
const match = /^([+-]?)(\d*)(?:\.(\d*))?$/.exec(normalized) // 匹配结果:1 为符号,2 为整数,3 为小数。
|
|
80
87
|
if (!match || (!match[2] && !match[3])) return null
|
|
81
88
|
|
|
82
89
|
return {
|
|
@@ -89,7 +96,7 @@ const parseAmount = (value?: string) => {
|
|
|
89
96
|
// 格式化金额 value:先换算为整数分并四舍五入,再添加千分位,统一显示两位小数。
|
|
90
97
|
const formatAmount = (value?: string) => {
|
|
91
98
|
const amount = parseAmount(value) // 解析后的十进制金额,无法识别时为 null。
|
|
92
|
-
if (!amount) return value
|
|
99
|
+
if (!amount) return String(value ?? '').trim() || '—'
|
|
93
100
|
|
|
94
101
|
const fraction = amount.fraction.padEnd(3, '0') // 至少保留三位小数,第三位用于判断进位。
|
|
95
102
|
let cents = BigInt(amount.integer + fraction.slice(0, 2)) // 金额绝对值对应的整数分,使用 BigInt 保证精度。
|
|
@@ -101,11 +108,11 @@ const formatAmount = (value?: string) => {
|
|
|
101
108
|
return `${sign}${integer}.${digits.slice(-2)}`
|
|
102
109
|
}
|
|
103
110
|
|
|
104
|
-
//
|
|
105
|
-
const compareAmounts = (left
|
|
111
|
+
// 补齐小数后按精确整数比较;空值和无效金额在升序、降序中均排在最后。
|
|
112
|
+
const compareAmounts = (left: string | undefined, right: string | undefined, order: Exclude<AmountSortOrder, null>) => {
|
|
106
113
|
const leftAmount = parseAmount(left) // 左侧金额的解析结果。
|
|
107
114
|
const rightAmount = parseAmount(right) // 右侧金额的解析结果。
|
|
108
|
-
if (!leftAmount && !rightAmount) return
|
|
115
|
+
if (!leftAmount && !rightAmount) return 0
|
|
109
116
|
if (!leftAmount) return 1
|
|
110
117
|
if (!rightAmount) return -1
|
|
111
118
|
|
|
@@ -114,11 +121,21 @@ const compareAmounts = (left?: string, right?: string) => {
|
|
|
114
121
|
const rightDigits = rightAmount.integer + rightAmount.fraction.padEnd(precision, '0') // 右侧金额按统一精度放大后的绝对值。
|
|
115
122
|
const leftValue = BigInt(leftDigits) * (leftAmount.negative ? -1n : 1n) // 左侧带符号的精确整数。
|
|
116
123
|
const rightValue = BigInt(rightDigits) * (rightAmount.negative ? -1n : 1n) // 右侧带符号的精确整数。
|
|
117
|
-
|
|
118
|
-
if (leftValue
|
|
124
|
+
const direction = order === 'ascending' ? 1 : -1
|
|
125
|
+
if (leftValue < rightValue) return -direction
|
|
126
|
+
if (leftValue > rightValue) return direction
|
|
119
127
|
return 0
|
|
120
128
|
}
|
|
121
129
|
|
|
130
|
+
// 只排序当前页的副本,详情和审批继续使用原始任务;取消排序时恢复接口顺序。
|
|
131
|
+
const tableRows = computed(() => {
|
|
132
|
+
const order = amountSortOrder.value
|
|
133
|
+
return order ? [...rows.value].sort((left, right) => compareAmounts(left.txnAmt, right.txnAmt, order)) : rows.value
|
|
134
|
+
})
|
|
135
|
+
const changeSort = ({ prop, order }: { prop: string; order: AmountSortOrder }) => {
|
|
136
|
+
amountSortOrder.value = prop === 'txnAmt' ? order : null
|
|
137
|
+
}
|
|
138
|
+
|
|
122
139
|
/**
|
|
123
140
|
* 生成普通文本列,默认将空值显示为横线。
|
|
124
141
|
* @param prop 接口字段名。
|
|
@@ -127,16 +144,33 @@ const compareAmounts = (left?: string, right?: string) => {
|
|
|
127
144
|
* @param format 字段格式化函数,参数 value 为当前单元格原值。
|
|
128
145
|
*/
|
|
129
146
|
const textColumn = (
|
|
130
|
-
prop:
|
|
147
|
+
prop: string,
|
|
131
148
|
label: string,
|
|
132
149
|
width: number,
|
|
133
150
|
format = (value?: string) => value?.trim() || '—',
|
|
134
|
-
): ColumnOption
|
|
151
|
+
): ColumnOption => ({
|
|
135
152
|
// row 为当前行任务,按 prop 读取单元格值后交给 format 处理。
|
|
136
153
|
prop, label, width, showOverflowTooltip: true, formatter: (row) => format(row[prop]),
|
|
137
154
|
})
|
|
155
|
+
|
|
156
|
+
// 日期列按原始时间戳对当前页排序,空值和无效日期在升序时排在最后。
|
|
157
|
+
const dateColumn = (
|
|
158
|
+
prop: string,
|
|
159
|
+
label: string,
|
|
160
|
+
): ColumnOption => ({
|
|
161
|
+
...textColumn(prop, label, 180, formatDateTime),
|
|
162
|
+
sortable: true,
|
|
163
|
+
sortMethod: (left, right) => {
|
|
164
|
+
const leftTime = Date.parse(left[prop]?.trim() || '')
|
|
165
|
+
const rightTime = Date.parse(right[prop]?.trim() || '')
|
|
166
|
+
if (Number.isNaN(leftTime)) return Number.isNaN(rightTime) ? 0 : 1
|
|
167
|
+
if (Number.isNaN(rightTime)) return -1
|
|
168
|
+
return leftTime - rightTime
|
|
169
|
+
},
|
|
170
|
+
})
|
|
171
|
+
|
|
138
172
|
// 表格完整列配置;字段顺序即展示顺序,任务状态和操作列固定在右侧。
|
|
139
|
-
const tableColumns: ColumnOption
|
|
173
|
+
const tableColumns: ColumnOption[] = [
|
|
140
174
|
{ key: 'sequence', type: 'globalIndex', label: '序号', width: 80, align: 'center' },
|
|
141
175
|
textColumn('platfSeqNo', '平台流水号', 190),
|
|
142
176
|
textColumn('id', '任务ID', 180),
|
|
@@ -145,9 +179,7 @@ const tableColumns: ColumnOption<AuthorizationTask>[] = [
|
|
|
145
179
|
textColumn('payeeName', '收款人名称', 160),
|
|
146
180
|
{
|
|
147
181
|
prop: 'txnAmt', label: '交易金额(元)', width: 180, align: 'right',
|
|
148
|
-
useSlot: true, slotName: 'amount', sortable:
|
|
149
|
-
// left、right 为参与排序的两条任务;只比较当前页金额。
|
|
150
|
-
sortMethod: (left, right) => compareAmounts(left.txnAmt, right.txnAmt),
|
|
182
|
+
useSlot: true, slotName: 'amount', sortable: 'custom',
|
|
151
183
|
},
|
|
152
184
|
textColumn('payWltId', '付款钱包ID', 190),
|
|
153
185
|
textColumn('authoOrgName', '授权机构名称', 180),
|
|
@@ -158,11 +190,11 @@ const tableColumns: ColumnOption<AuthorizationTask>[] = [
|
|
|
158
190
|
textColumn('collSideAcctBeloOrgNo', '收款方账户所属机构编号', 210),
|
|
159
191
|
textColumn('subBrchName', '落地支行名称', 180),
|
|
160
192
|
textColumn('subBrchBankNo', '落地支行行号', 160),
|
|
161
|
-
|
|
162
|
-
|
|
193
|
+
dateColumn('txnTm', '交易发起时间'),
|
|
194
|
+
dateColumn('createTm', '创建时间'),
|
|
163
195
|
textColumn('apprvrId', '审批人ID', 130),
|
|
164
196
|
textColumn('apprvrName', '审批人名称', 130),
|
|
165
|
-
|
|
197
|
+
dateColumn('approveTm', '审批时间'),
|
|
166
198
|
textColumn('rmk', '审批备注', 220),
|
|
167
199
|
{ ...textColumn('taskSts', '任务状态', 100, formatStatus), fixed: 'right', align: 'center' },
|
|
168
200
|
{ key: 'actions', label: '操作', width: 80, fixed: 'right', align: 'center', useSlot: true },
|
|
@@ -185,7 +217,7 @@ const detailValues = computed(() => {
|
|
|
185
217
|
|
|
186
218
|
// 读取表单并组装请求参数,接口日期格式为 YYYYMMDD。
|
|
187
219
|
const getQueryFilters = () => ({
|
|
188
|
-
opType: 'query', // 查询授权任务。
|
|
220
|
+
opType: 'query' as const, // 查询授权任务。
|
|
189
221
|
authoOrgNo: filters.value.authoOrgNo.trim(), // 归属机构编号。
|
|
190
222
|
collePayerName: filters.value.collePayerName.trim(), // 付款人名称。
|
|
191
223
|
payeeName: filters.value.payeeName.trim(), // 收款人名称。
|
|
@@ -201,12 +233,12 @@ let appliedQuery = getQueryFilters()
|
|
|
201
233
|
const loadList = async () => {
|
|
202
234
|
if (disposed) return
|
|
203
235
|
const currentRequestId = ++requestId // 本次请求序号,仅与最新序号相等时允许更新界面。
|
|
204
|
-
const params = { ...appliedQuery, pageIndex: pagination.current, pageSize: pagination.size } // 本次查询条件和分页快照。
|
|
236
|
+
const params: AuthorizationQueryParams = { ...appliedQuery, pageIndex: pagination.current, pageSize: pagination.size } // 本次查询条件和分页快照。
|
|
205
237
|
loading.value = true
|
|
206
238
|
try {
|
|
207
239
|
for (let attempt = 0; attempt < 2; attempt += 1) { // attempt:0 为首次查询,1 为页码修正后的补查。
|
|
208
240
|
// head 为公共响应头,body 为包含列表及总条数的业务数据。
|
|
209
|
-
const { head, body } = await API.queryListApi(params)
|
|
241
|
+
const { head, body } = await API.queryListApi(params) as any
|
|
210
242
|
if (currentRequestId !== requestId) return
|
|
211
243
|
if (head?.retCode !== '00000') {
|
|
212
244
|
throw new Error(head?.retMsg || '查询失败')
|
|
@@ -257,13 +289,13 @@ const changePage = (current: number, size = pagination.size) => {
|
|
|
257
289
|
}
|
|
258
290
|
|
|
259
291
|
// 双击行查看详情;task 为当前行的原始授权任务。
|
|
260
|
-
const openDetailDialog = (task:
|
|
292
|
+
const openDetailDialog = (task: any) => {
|
|
261
293
|
if (loading.value || pendingDecision.value) return
|
|
262
294
|
detailTask.value = task
|
|
263
295
|
detailDialogVisible.value = true
|
|
264
296
|
}
|
|
265
297
|
// 打开审批窗口;task 为列表或详情选中的任务,只允许处理待审批状态。
|
|
266
|
-
const openDecisionDialog = (task:
|
|
298
|
+
const openDecisionDialog = (task: any) => {
|
|
267
299
|
if (!canApprove(task) || loading.value || pendingDecision.value) return
|
|
268
300
|
detailDialogVisible.value = false
|
|
269
301
|
selectedTask.value = task
|
|
@@ -373,7 +405,7 @@ onBeforeUnmount(() => {
|
|
|
373
405
|
v-model:show-search-bar="showSearchBar"
|
|
374
406
|
fill
|
|
375
407
|
toolbar-layout="search,refresh,size,fullscreen,columns,settings"
|
|
376
|
-
:data="
|
|
408
|
+
:data="tableRows"
|
|
377
409
|
:columns="tableColumns"
|
|
378
410
|
:loading="loading"
|
|
379
411
|
:pagination="pagination"
|
|
@@ -382,6 +414,7 @@ onBeforeUnmount(() => {
|
|
|
382
414
|
empty-text="暂无符合条件的授权任务"
|
|
383
415
|
@pagination:current-change="changePage"
|
|
384
416
|
@pagination:size-change="(size) => changePage(1, size)"
|
|
417
|
+
@sort-change="changeSort"
|
|
385
418
|
@refresh="loadList"
|
|
386
419
|
@row-dblclick="openDetailDialog"
|
|
387
420
|
>
|
|
@@ -478,14 +511,18 @@ onBeforeUnmount(() => {
|
|
|
478
511
|
</template>
|
|
479
512
|
|
|
480
513
|
<style scoped>
|
|
481
|
-
/*
|
|
514
|
+
/* 页面先扣除宿主占用高度,再使用 flex 分配剩余高度,让列表内部滚动并保留分页。 */
|
|
482
515
|
.dcps-page {
|
|
516
|
+
/* 手动修改这里:顶部导航/页签 + 底部状态栏 + 宿主上下留白的合计高度。
|
|
517
|
+
独立页面保持 0px;例如顶部 90px、底部 24px、上下留白 6px,填写 120px。
|
|
518
|
+
不包含浏览器标签栏、地址栏,也不包含本页面自身的 padding。 */
|
|
519
|
+
--host-layout-height: 0px;
|
|
483
520
|
box-sizing: border-box;
|
|
484
521
|
display: flex;
|
|
485
522
|
flex-direction: column;
|
|
486
|
-
gap:
|
|
487
|
-
height: 100vh;
|
|
488
|
-
height: 100dvh;
|
|
523
|
+
gap: 5px;
|
|
524
|
+
height: calc(100vh - var(--host-layout-height));
|
|
525
|
+
height: calc(100dvh - var(--host-layout-height));
|
|
489
526
|
min-height: 0;
|
|
490
527
|
min-width: 0;
|
|
491
528
|
padding: 5px;
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { AuthorizationRuntime } from './typs'
|
|
2
|
-
|
|
3
1
|
// 返回配置的默认查询日期,格式为 YYYYMMDD;当前使用固定日期。
|
|
4
2
|
const getLocalDate = () => {
|
|
5
3
|
return `20261012`
|
|
@@ -8,7 +6,7 @@ const getLocalDate = () => {
|
|
|
8
6
|
const today = getLocalDate() // 默认查询日期,取自上方函数中的固定配置。
|
|
9
7
|
|
|
10
8
|
/** 授权页面的审批人和默认创建日期;日期格式为 YYYYMMDD。 */
|
|
11
|
-
const runtime
|
|
9
|
+
const runtime = {
|
|
12
10
|
approverId: '10092', // 审批人工号。
|
|
13
11
|
approverName: '王干事', // 审批人姓名。
|
|
14
12
|
createTmBegin: today, // 默认创建开始日期,格式为 YYYYMMDD。
|
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** 页面查询条件;空字符串表示不限制该条件。 */
|
|
2
|
+
export interface AuthorizationFilters {
|
|
3
|
+
authoOrgNo: string // 归属行(报备机构)编号。
|
|
4
|
+
collePayerName: string // 付款人名称。
|
|
5
|
+
payeeName: string // 收款人名称。
|
|
6
|
+
platfSeqNo: string // 平台流水号。
|
|
7
|
+
taskSts: string // 任务状态:01 待审批、02 已通过、03 已拒绝。
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** 列表查询参数;日期格式为 YYYYMMDD,分页从第 1 页开始。 */
|
|
11
|
+
export interface AuthorizationQueryParams extends AuthorizationFilters {
|
|
12
|
+
opType: 'query' // 查询操作标识。
|
|
13
|
+
createTmBegin: string // 创建开始日期。
|
|
14
|
+
createTmEnd: string // 创建结束日期。
|
|
15
|
+
pageIndex: number // 当前页码。
|
|
16
|
+
pageSize: number // 每页条数。
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** 接口返回的数字人民币授权任务字段。 */
|
|
2
20
|
export interface AuthorizationTask {
|
|
3
21
|
id?: string // 任务 ID。
|
|
4
22
|
platfSeqNo?: string // 平台流水号,用于定位审批任务。
|
|
@@ -8,7 +26,7 @@ export interface AuthorizationTask {
|
|
|
8
26
|
collePayerName?: string // 付款人名称。
|
|
9
27
|
payeeName?: string // 收款人名称。
|
|
10
28
|
payWltId?: string // 付款钱包 ID。
|
|
11
|
-
txnAmt?: string //
|
|
29
|
+
txnAmt?: string // 交易金额,单位为元,保留字符串精度。
|
|
12
30
|
txnTm?: string // 交易发起时间。
|
|
13
31
|
createTm?: string // 任务创建时间。
|
|
14
32
|
taskSts?: string // 任务状态:01 待审批、02 已通过、03 已拒绝。
|
|
@@ -24,36 +42,9 @@ export interface AuthorizationTask {
|
|
|
24
42
|
collSideAcctBeloOrgNo?: string // 收款方账户所属机构编号。
|
|
25
43
|
}
|
|
26
44
|
|
|
27
|
-
/**
|
|
28
|
-
export interface
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
platfSeqNo: string // 平台流水号。
|
|
33
|
-
taskSts: string // 任务状态:01 待审批、02 已通过、03 已拒绝。
|
|
45
|
+
/** 列表查询返回的业务数据。 */
|
|
46
|
+
export interface AuthorizationQueryResult {
|
|
47
|
+
resultList: AuthorizationTask[] // 当前页的授权任务记录。
|
|
48
|
+
totalCount: string | number // 符合查询条件的总记录数。
|
|
49
|
+
totalPage?: string | number // 总页数。
|
|
34
50
|
}
|
|
35
|
-
|
|
36
|
-
/** 创建日期范围:[开始日期, 结束日期],格式为 YYYYMMDD。 */
|
|
37
|
-
export type AuthorizationDateRange = [string, string]
|
|
38
|
-
|
|
39
|
-
/** 页面审批操作:approve 通过,reject 拒绝。 */
|
|
40
|
-
export type Decision = 'approve' | 'reject'
|
|
41
|
-
|
|
42
|
-
/** 当前审批人信息,供授权请求使用。 */
|
|
43
|
-
export interface ApproverInfo {
|
|
44
|
-
approverId: string // 审批人工号。
|
|
45
|
-
approverName: string // 审批人姓名。
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** 授权页面运行配置,集中定义审批人和默认创建日期。 */
|
|
49
|
-
export interface AuthorizationRuntime extends ApproverInfo {
|
|
50
|
-
createTmBegin: string // 默认创建开始日期,格式为 YYYYMMDD。
|
|
51
|
-
createTmEnd: string // 默认创建结束日期,格式为 YYYYMMDD。
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** 通过和拒绝共用的审批表单;姓名只读,由 runtime 提供。 */
|
|
55
|
-
export interface ApprovalForm {
|
|
56
|
-
approverId: string // 本次审批使用的工号,取自 runtime,页面禁用修改。
|
|
57
|
-
remark: string // 通过时为可选备注,拒绝时为必填原因。
|
|
58
|
-
}
|
|
59
|
-
|