vue3-element-plus-app-chu 0.0.28 → 0.0.30
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/flow-query/api.ts +2 -2
- package/src/view/dcps/flow-query/index.vue +243 -45
- package/src/view/dcps/flow-query/typs.ts +26 -4
- package/src/view/dcps/forecast/index.vue +5 -5
- package/src/view/dcps/funding/injection/index.vue +1 -1
- package/src/view/dcps/parameters/index.vue +4 -4
- package/src/view/dcps/write-off/index.vue +5 -5
- package/src/view/112.xlsx +0 -0
package/package.json
CHANGED
|
@@ -4,8 +4,8 @@ import type { FlowQueryParams } from './typs'
|
|
|
4
4
|
export default {
|
|
5
5
|
/**
|
|
6
6
|
* 分页查询数字人民币实时流水(140504002)。
|
|
7
|
-
*
|
|
8
|
-
* @param params
|
|
7
|
+
* 筛选条件全部可空:为空时业务 body 为空对象,与原契约一致。
|
|
8
|
+
* @param params 业务筛选条件与公共分页参数,分页由请求层放入 head 并转换为字符串。
|
|
9
9
|
*/
|
|
10
10
|
queryFlowApi: (params: FlowQueryParams) =>
|
|
11
11
|
baseHttpClient.post<any>('/TAM/0001/140504002', params),
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
|
3
|
-
import { ElMessageBox } from 'element-plus'
|
|
3
|
+
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
4
4
|
import API from './api'
|
|
5
5
|
import { ArtDataTable, type ColumnOption, type PaginationOptions, type TableSettings } from '@/components/table'
|
|
6
|
-
import type { FlowRow, Tam140504002OutBody } from './typs'
|
|
6
|
+
import type { FlowQueryParams, FlowRow, RealtimeFlowFilters, Tam140504002OutBody } from './typs'
|
|
7
7
|
|
|
8
8
|
defineOptions({ name: 'DcpsFlowQueryPage' })
|
|
9
9
|
|
|
@@ -79,14 +79,95 @@ const formatAmount = (value?: string): string => {
|
|
|
79
79
|
return `${negative ? '-' : ''}${integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}.${fraction.padEnd(2, '0')}`
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
/** 筛选输入沿用同一套金额规则:只接受十进制文本和合法千分位。 */
|
|
83
|
+
const normalizeAmount = (value: string): string => {
|
|
84
|
+
let text = value.trim()
|
|
85
|
+
if (text.includes(',')) {
|
|
86
|
+
if (!/^[+-]?\d{1,3}(?:,\d{3})+(?:\.\d*)?$/.test(text)) return ''
|
|
87
|
+
text = text.replace(/,/g, '')
|
|
88
|
+
}
|
|
89
|
+
const match = /^([+-]?)(\d*)(?:\.(\d*))?$/.exec(text)
|
|
90
|
+
if (!match || (!match[2] && !match[3])) return ''
|
|
91
|
+
const integer = (match[2] || '0').replace(/^0+(?=\d)/, '')
|
|
92
|
+
const fraction = match[3] || ''
|
|
93
|
+
const negative = match[1] === '-' && /[1-9]/.test(integer + fraction)
|
|
94
|
+
return `${negative ? '-' : ''}${integer}${fraction ? `.${fraction}` : ''}`
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** 比较两个标准化后的金额字符串,返回 -1/0/1。 */
|
|
98
|
+
const compareAmounts = (left: string, right: string): number => {
|
|
99
|
+
const leftText = normalizeAmount(left)
|
|
100
|
+
const rightText = normalizeAmount(right)
|
|
101
|
+
if (!leftText || !rightText) {
|
|
102
|
+
if (!leftText && !rightText) return 0
|
|
103
|
+
return leftText ? -1 : 1
|
|
104
|
+
}
|
|
105
|
+
const parts = (text: string) => {
|
|
106
|
+
const negative = text.startsWith('-')
|
|
107
|
+
const [integer = '0', fraction = ''] = (negative ? text.slice(1) : text).split('.')
|
|
108
|
+
return { negative, integer, fraction }
|
|
109
|
+
}
|
|
110
|
+
const a = parts(leftText)
|
|
111
|
+
const b = parts(rightText)
|
|
112
|
+
const precision = Math.max(a.fraction.length, b.fraction.length)
|
|
113
|
+
const toInteger = (amount: ReturnType<typeof parts>) =>
|
|
114
|
+
BigInt(amount.integer + amount.fraction.padEnd(precision, '0')) * (amount.negative ? -1n : 1n)
|
|
115
|
+
return toInteger(a) < toInteger(b) ? -1 : toInteger(a) > toInteger(b) ? 1 : 0
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** 校验筛选金额:非负十进制,最多两位小数;返回标准化后的文本。 */
|
|
119
|
+
const validAmount = (value: string) => {
|
|
120
|
+
const normalized = normalizeAmount(value)
|
|
121
|
+
if (!normalized || normalized.startsWith('-') || (normalized.split('.')[1]?.length || 0) > 2) return ''
|
|
122
|
+
return normalized
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** 业务类型字典:201 兑回、202 兑出、203 付现。 */
|
|
126
|
+
const busiTypeLabels: Record<string, string> = { '201': '兑回', '202': '兑出', '203': '付现' }
|
|
127
|
+
/** 收支方向字典:I 来账、O 往账。 */
|
|
128
|
+
const payDirecLabels: Record<string, string> = { I: '来账', O: '往账' }
|
|
129
|
+
/** 交易状态字典:S 成功、P 处理中、F 失败。 */
|
|
130
|
+
const tranStatusLabels: Record<string, string> = { S: '成功', P: '处理中', F: '失败' }
|
|
131
|
+
|
|
132
|
+
const busiTypeOptions = Object.entries(busiTypeLabels).map(([value, label]) => ({ value, label }))
|
|
133
|
+
const payDirecOptions = Object.entries(payDirecLabels).map(([value, label]) => ({ value, label }))
|
|
134
|
+
const tranStatusOptions = Object.entries(tranStatusLabels).map(([value, label]) => ({ value, label }))
|
|
135
|
+
|
|
136
|
+
let disposed = false // 页面是否已卸载,避免未完成请求继续更新界面。
|
|
137
|
+
|
|
138
|
+
// ---------- 查询条件与列表状态 ----------
|
|
139
|
+
|
|
140
|
+
/** 默认查询条件;空字符串表示不限制该条件,重置时恢复此配置。实时流水默认不限日期。 */
|
|
141
|
+
const createFlowFilters = (): RealtimeFlowFilters => ({
|
|
142
|
+
bizType: '',
|
|
143
|
+
cdtrNm: '',
|
|
144
|
+
dbtrNm: '',
|
|
145
|
+
endTxnAmt: '',
|
|
146
|
+
orgKeyword: '',
|
|
147
|
+
startTxnAmt: '',
|
|
148
|
+
txnDate: '',
|
|
149
|
+
txnDirection: '',
|
|
150
|
+
txnSts: '',
|
|
151
|
+
})
|
|
152
|
+
const flowFilters = ref<RealtimeFlowFilters>(createFlowFilters())
|
|
153
|
+
/** 已生效的查询快照:翻页、刷新继续使用同一份条件,表单中的新输入不影响进行中的查询。 */
|
|
154
|
+
let flowAppliedQuery: FlowQueryParams = { pageIndex: 1, pageSize: 15 }
|
|
155
|
+
|
|
156
|
+
// 重复输入项共用一份配置,依次为字段、名称和输入框长度限制。
|
|
157
|
+
const flowTextFilters = [
|
|
158
|
+
['orgKeyword', '机构关键字', 180],
|
|
159
|
+
['dbtrNm', '付款人名称', 180],
|
|
160
|
+
['cdtrNm', '收款人名称', 180],
|
|
161
|
+
] as const
|
|
162
|
+
|
|
163
|
+
// 列表、分页与请求状态;请求序号防止旧响应覆盖新结果。
|
|
82
164
|
const flowRows = ref<FlowRow[]>([])
|
|
83
165
|
const flowPagination = reactive({ current: 1, size: 15, total: 0 })
|
|
84
166
|
const flowPaginationOptions: PaginationOptions = { align: 'right', pageSizes: [15, 30, 50, 100], background: false }
|
|
85
167
|
const flowTableSettings = ref<TableSettings>({ size: 'small', stripe: true, border: true, headerBackground: true })
|
|
86
168
|
const flowLoading = ref(false)
|
|
87
169
|
const flowQueryError = ref('')
|
|
88
|
-
let
|
|
89
|
-
let flowRequestId = 0 // 仅最新请求可以写入列表;离开页面时使未完成请求失效。
|
|
170
|
+
let flowRequestId = 0
|
|
90
171
|
|
|
91
172
|
/** 所有代码字段保留接口原值,不套用核销接口的方向、业务类型或状态字典。 */
|
|
92
173
|
const flowTextColumn = (prop: keyof FlowRow, label: string, width: number, visible = true): ColumnOption<FlowRow> => ({
|
|
@@ -115,17 +196,18 @@ const flowColumns: ColumnOption<FlowRow>[] = [
|
|
|
115
196
|
flowTextColumn('subBrchBankNo', '落地支行行号', 170, false),
|
|
116
197
|
]
|
|
117
198
|
|
|
118
|
-
/**
|
|
199
|
+
/** 分页字段进公共 head,筛选条件保留在 body;无条件时 body 为空对象,不违反接口契约。 */
|
|
119
200
|
const loadFlowList = async () => {
|
|
120
201
|
if (disposed) return
|
|
121
202
|
const currentId = ++flowRequestId
|
|
203
|
+
const query = { ...flowAppliedQuery }
|
|
122
204
|
const pageSize = flowPagination.size
|
|
123
205
|
let pageIndex = flowPagination.current
|
|
124
206
|
flowLoading.value = true
|
|
125
207
|
flowQueryError.value = ''
|
|
126
208
|
try {
|
|
127
209
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
128
|
-
const response = await API.queryFlowApi({ pageIndex, pageSize })
|
|
210
|
+
const response = await API.queryFlowApi({ ...query, pageIndex, pageSize }) as any
|
|
129
211
|
if (disposed || currentId !== flowRequestId) return
|
|
130
212
|
const page = readPage(ensureSuccess(response), pageIndex, pageSize)
|
|
131
213
|
if (pageIndex > page.lastPage) {
|
|
@@ -150,13 +232,59 @@ const loadFlowList = async () => {
|
|
|
150
232
|
}
|
|
151
233
|
}
|
|
152
234
|
|
|
153
|
-
/**
|
|
235
|
+
/** 查询从第一页开始:校验并快照当前表单条件,只发送已填写的字段。 */
|
|
154
236
|
const searchFlow = () => {
|
|
155
237
|
if (disposed || flowLoading.value) return
|
|
238
|
+
const source = flowFilters.value
|
|
239
|
+
if (source.txnDate.trim() && !/^\d{8}$/.test(source.txnDate.trim())) {
|
|
240
|
+
return void ElMessage.warning('请选择有效的交易日期')
|
|
241
|
+
}
|
|
242
|
+
const startTxnAmt = validAmount(source.startTxnAmt)
|
|
243
|
+
if (source.startTxnAmt.trim() && !startTxnAmt) {
|
|
244
|
+
return void ElMessage.warning('起始金额请输入非负数,最多保留两位小数')
|
|
245
|
+
}
|
|
246
|
+
const endTxnAmt = validAmount(source.endTxnAmt)
|
|
247
|
+
if (source.endTxnAmt.trim() && !endTxnAmt) {
|
|
248
|
+
return void ElMessage.warning('截止金额请输入非负数,最多保留两位小数')
|
|
249
|
+
}
|
|
250
|
+
if (startTxnAmt && endTxnAmt && compareAmounts(startTxnAmt, endTxnAmt) > 0) {
|
|
251
|
+
return void ElMessage.warning('起始金额不能大于截止金额')
|
|
252
|
+
}
|
|
253
|
+
// 只保留已填写的筛选条件;空字符串不发送,表示不限制该条件。
|
|
254
|
+
const query: FlowQueryParams = { pageIndex: 1, pageSize: flowPagination.size }
|
|
255
|
+
for (const key of ['bizType', 'txnDirection', 'txnSts'] as const) {
|
|
256
|
+
const value = source[key].trim()
|
|
257
|
+
if (value) query[key] = value
|
|
258
|
+
}
|
|
259
|
+
for (const [key] of flowTextFilters) {
|
|
260
|
+
const value = source[key].trim()
|
|
261
|
+
if (value) query[key] = value
|
|
262
|
+
}
|
|
263
|
+
if (source.txnDate.trim()) query.txnDate = source.txnDate.trim()
|
|
264
|
+
if (startTxnAmt) query.startTxnAmt = startTxnAmt
|
|
265
|
+
if (endTxnAmt) query.endTxnAmt = endTxnAmt
|
|
266
|
+
flowAppliedQuery = query
|
|
267
|
+
flowPagination.current = 1
|
|
268
|
+
void loadFlowList()
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** 重置清空全部条件并按不限规则重新查询。 */
|
|
272
|
+
const resetFlowFilters = () => {
|
|
273
|
+
if (disposed || flowLoading.value) return
|
|
274
|
+
flowFilters.value = createFlowFilters()
|
|
275
|
+
flowAppliedQuery = { pageIndex: 1, pageSize: flowPagination.size }
|
|
156
276
|
flowPagination.current = 1
|
|
157
277
|
void loadFlowList()
|
|
158
278
|
}
|
|
159
279
|
|
|
280
|
+
const changeFlowPage = (current: number, size = flowPagination.size) => {
|
|
281
|
+
if (disposed || (current === flowPagination.current && size === flowPagination.size)) return
|
|
282
|
+
if (!Number.isSafeInteger(current) || current < 1 || !Number.isSafeInteger(size) || size < 1) return
|
|
283
|
+
flowPagination.current = current
|
|
284
|
+
flowPagination.size = size
|
|
285
|
+
void loadFlowList()
|
|
286
|
+
}
|
|
287
|
+
|
|
160
288
|
const realtimeChecking = ref(false)
|
|
161
289
|
|
|
162
290
|
/** 「实时查询流水」仅调用 140504002 确认实时链路;返回成功后弹窗提示,不改动表格与分页。 */
|
|
@@ -164,7 +292,7 @@ const checkRealtimeFlow = async () => {
|
|
|
164
292
|
if (disposed || realtimeChecking.value) return
|
|
165
293
|
realtimeChecking.value = true
|
|
166
294
|
try {
|
|
167
|
-
const response = await API.queryFlowApi({ pageIndex: 1, pageSize: 1 })
|
|
295
|
+
const response = await API.queryFlowApi({ pageIndex: 1, pageSize: 1 }) as any
|
|
168
296
|
if (disposed) return
|
|
169
297
|
if (response?.head?.retCode !== '00000') {
|
|
170
298
|
throw new Error(response?.head?.retMsg?.trim() || '实时查询流水失败')
|
|
@@ -178,14 +306,6 @@ const checkRealtimeFlow = async () => {
|
|
|
178
306
|
}
|
|
179
307
|
}
|
|
180
308
|
|
|
181
|
-
const changeFlowPage = (current: number, size = flowPagination.size) => {
|
|
182
|
-
if (disposed || (current === flowPagination.current && size === flowPagination.size)) return
|
|
183
|
-
if (!Number.isSafeInteger(current) || current < 1 || !Number.isSafeInteger(size) || size < 1) return
|
|
184
|
-
flowPagination.current = current
|
|
185
|
-
flowPagination.size = size
|
|
186
|
-
void loadFlowList()
|
|
187
|
-
}
|
|
188
|
-
|
|
189
309
|
onMounted(() => { void loadFlowList() })
|
|
190
310
|
onBeforeUnmount(() => {
|
|
191
311
|
disposed = true
|
|
@@ -195,39 +315,88 @@ onBeforeUnmount(() => {
|
|
|
195
315
|
|
|
196
316
|
<template>
|
|
197
317
|
<main class="dcps-page">
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
318
|
+
<section class="view-region">
|
|
319
|
+
<!-- 查询条件:控件尺寸跟随表格设置,卡片内边距为 10px,点击工具栏「查询」或回车生效。 -->
|
|
320
|
+
<el-card class="flow-search" shadow="never" :body-style="{ padding: '10px' }">
|
|
321
|
+
<el-form class="filter-form" :model="flowFilters" :size="flowTableSettings.size" label-position="top" @submit.prevent="searchFlow">
|
|
322
|
+
<el-form-item class="filter-date" label="交易日期">
|
|
323
|
+
<el-date-picker
|
|
324
|
+
v-model="flowFilters.txnDate"
|
|
325
|
+
type="date"
|
|
326
|
+
format="YYYY-MM-DD"
|
|
327
|
+
value-format="YYYYMMDD"
|
|
328
|
+
clearable
|
|
329
|
+
placeholder="不限"
|
|
330
|
+
:editable="false"
|
|
331
|
+
/>
|
|
332
|
+
</el-form-item>
|
|
333
|
+
<el-form-item class="filter-status" label="收支方向">
|
|
334
|
+
<el-select v-model="flowFilters.txnDirection" clearable placeholder="不限">
|
|
335
|
+
<el-option v-for="option in payDirecOptions" :key="option.value" :label="option.label" :value="option.value" />
|
|
336
|
+
</el-select>
|
|
337
|
+
</el-form-item>
|
|
338
|
+
<el-form-item class="filter-status" label="业务类型">
|
|
339
|
+
<el-select v-model="flowFilters.bizType" clearable placeholder="不限">
|
|
340
|
+
<el-option v-for="option in busiTypeOptions" :key="option.value" :label="option.label" :value="option.value" />
|
|
341
|
+
</el-select>
|
|
342
|
+
</el-form-item>
|
|
343
|
+
<el-form-item class="filter-status" label="交易状态">
|
|
344
|
+
<el-select v-model="flowFilters.txnSts" clearable placeholder="不限">
|
|
345
|
+
<el-option v-for="option in tranStatusOptions" :key="option.value" :label="option.label" :value="option.value" />
|
|
346
|
+
</el-select>
|
|
347
|
+
</el-form-item>
|
|
348
|
+
<!-- prop 为查询字段,label 为字段名称,maxlength 为允许输入的最大字符数。 -->
|
|
349
|
+
<el-form-item v-for="[key, label, maxlength] in flowTextFilters" :key="key" :label="label">
|
|
350
|
+
<el-input v-model="flowFilters[key]" :placeholder="`输入${label}`" :maxlength="maxlength" clearable />
|
|
351
|
+
</el-form-item>
|
|
352
|
+
<el-form-item class="filter-amount" label="起始金额(元)">
|
|
353
|
+
<el-input v-model="flowFilters.startTxnAmt" placeholder="不限制" inputmode="decimal" :maxlength="40" clearable />
|
|
354
|
+
</el-form-item>
|
|
355
|
+
<el-form-item class="filter-amount" label="截止金额(元)">
|
|
356
|
+
<el-input v-model="flowFilters.endTxnAmt" placeholder="不限制" inputmode="decimal" :maxlength="40" clearable />
|
|
357
|
+
</el-form-item>
|
|
358
|
+
<el-space class="filter-actions" :size="8">
|
|
359
|
+
<el-button :disabled="flowLoading || realtimeChecking" @click="resetFlowFilters">重置</el-button>
|
|
360
|
+
</el-space>
|
|
361
|
+
</el-form>
|
|
362
|
+
</el-card>
|
|
363
|
+
|
|
364
|
+
<el-alert v-if="flowQueryError" :title="flowQueryError" type="error" show-icon :closable="false">
|
|
365
|
+
<el-button link type="primary" :disabled="flowLoading" @click="void loadFlowList()">重新查询</el-button>
|
|
366
|
+
</el-alert>
|
|
367
|
+
|
|
368
|
+
<!-- 实时流水表格:分页由表格内置分页组件承载;工具栏提供查询与实时链路确认两个按钮。 -->
|
|
369
|
+
<div class="table-region">
|
|
370
|
+
<ArtDataTable
|
|
371
|
+
v-model:settings="flowTableSettings"
|
|
372
|
+
class="flow-table"
|
|
373
|
+
fill
|
|
374
|
+
title="数字人民币实时流水"
|
|
375
|
+
toolbar-layout="refresh,size,fullscreen,columns,settings"
|
|
376
|
+
:data="flowRows"
|
|
377
|
+
:columns="flowColumns"
|
|
378
|
+
:loading="flowLoading"
|
|
379
|
+
:pagination="flowPagination"
|
|
380
|
+
:pagination-options="flowPaginationOptions"
|
|
381
|
+
row-key="consumerSeqNo"
|
|
382
|
+
:empty-text="flowQueryError ? '查询失败,请重新查询' : '暂无符合条件的实时流水'"
|
|
383
|
+
@pagination:current-change="changeFlowPage"
|
|
384
|
+
@pagination:size-change="(size: number) => changeFlowPage(1, size)"
|
|
385
|
+
@refresh="void loadFlowList()"
|
|
386
|
+
>
|
|
387
|
+
<template #toolbar-left>
|
|
388
|
+
<el-button type="primary" :size="flowTableSettings.size" :loading="flowLoading" @click="searchFlow">查询</el-button>
|
|
389
|
+
<el-button type="primary" plain :size="flowTableSettings.size" :loading="realtimeChecking" @click="void checkRealtimeFlow()">实时查询流水</el-button>
|
|
390
|
+
</template>
|
|
391
|
+
<template #txnAmount="{ row }"><span class="amount-cell">{{ formatAmount(row.txnAmt) }}</span></template>
|
|
392
|
+
</ArtDataTable>
|
|
393
|
+
</div>
|
|
394
|
+
</section>
|
|
227
395
|
</main>
|
|
228
396
|
</template>
|
|
229
397
|
|
|
230
398
|
<style scoped>
|
|
399
|
+
/* 页面先扣除宿主占用高度,再使用 flex 分配剩余高度,列表内部滚动并保留分页。 */
|
|
231
400
|
.dcps-page {
|
|
232
401
|
box-sizing: border-box;
|
|
233
402
|
display: flex;
|
|
@@ -243,7 +412,36 @@ onBeforeUnmount(() => {
|
|
|
243
412
|
overflow: hidden;
|
|
244
413
|
background: var(--el-bg-color-page, #f7f8fa);
|
|
245
414
|
}
|
|
415
|
+
/* 视图区域:纵向占父页面剩余高度,列表内部滚动并保留分页。 */
|
|
416
|
+
.view-region {
|
|
417
|
+
display: flex;
|
|
418
|
+
flex: 1;
|
|
419
|
+
flex-direction: column;
|
|
420
|
+
gap: 5px;
|
|
421
|
+
min-height: 0;
|
|
422
|
+
min-width: 0;
|
|
423
|
+
}
|
|
424
|
+
/* 筛选项压成一行,等分剩余宽度,窗口过窄时才换行并限制高度,为列表保留空间。 */
|
|
425
|
+
.flow-search {
|
|
426
|
+
flex: 0 0 auto;
|
|
427
|
+
max-height: min(38dvh, 320px);
|
|
428
|
+
overflow-y: auto;
|
|
429
|
+
}
|
|
430
|
+
.filter-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 6px; }
|
|
431
|
+
.filter-form :deep(.el-form-item) { flex: 1 1 76px; min-width: 76px; margin: 0; }
|
|
432
|
+
.filter-form :deep(.el-form-item__label) { height: auto; margin-bottom: 4px; padding: 0; font-size: 12px; line-height: 16px; }
|
|
433
|
+
/* 下拉和日期控件撑满筛选格,避免宽度塌缩。 */
|
|
434
|
+
.filter-form :deep(.el-select), .filter-form :deep(.el-date-editor) { width: 100%; min-width: 0; }
|
|
435
|
+
.filter-form :deep(.filter-date) { flex: 1.5 0 116px; }
|
|
436
|
+
.filter-form :deep(.filter-status) { flex: 1.1 0 96px; }
|
|
437
|
+
.filter-form :deep(.filter-amount) { flex: 1.2 0 92px; }
|
|
438
|
+
.filter-actions { flex: 0 0 auto; }
|
|
246
439
|
.table-region { flex: 1; min-width: 0; min-height: 0; }
|
|
247
440
|
.flow-table { padding: 10px; }
|
|
248
441
|
.amount-cell { color: var(--el-text-color-primary); font-variant-numeric: tabular-nums; }
|
|
442
|
+
|
|
443
|
+
@media (max-width: 640px) {
|
|
444
|
+
.filter-form :deep(.el-form-item) { flex-basis: 100%; }
|
|
445
|
+
.filter-actions { margin-left: 0; }
|
|
446
|
+
}
|
|
249
447
|
</style>
|
|
@@ -1,12 +1,34 @@
|
|
|
1
|
-
/** 数字人民币实时流水查询(140504002
|
|
2
|
-
export
|
|
1
|
+
/** 数字人民币实时流水查询(140504002)的筛选条件;全部可选,空值表示不限制该条件。 */
|
|
2
|
+
export interface Tam140504002InBody {
|
|
3
|
+
/** 业务类型:201 兑回、202 兑出、203 付现。 */
|
|
4
|
+
bizType?: string
|
|
5
|
+
/** 截止金额(元),与起始金额搭配成区间。 */
|
|
6
|
+
endTxnAmt?: string
|
|
7
|
+
/** 机构关键字,模糊匹配付款机构、收款机构或落地支行名称。 */
|
|
8
|
+
orgKeyword?: string
|
|
9
|
+
/** 收支方向:I 来账、O 往账。 */
|
|
10
|
+
txnDirection?: string
|
|
11
|
+
/** 收款人名称关键字。 */
|
|
12
|
+
cdtrNm?: string
|
|
13
|
+
/** 付款人名称关键字。 */
|
|
14
|
+
dbtrNm?: string
|
|
15
|
+
/** 起始金额(元),与截止金额搭配成区间。 */
|
|
16
|
+
startTxnAmt?: string
|
|
17
|
+
/** 交易日期(YYYYMMDD),匹配流水的交易时间所在日期。 */
|
|
18
|
+
txnDate?: string
|
|
19
|
+
/** 交易状态:S 成功、P 处理中、F 失败。 */
|
|
20
|
+
txnSts?: string
|
|
21
|
+
}
|
|
3
22
|
|
|
4
|
-
/** 平铺的公共分页参数;请求层将其放入 head
|
|
5
|
-
export interface FlowQueryParams {
|
|
23
|
+
/** 平铺的公共分页参数;请求层将其放入 head,业务筛选条件保留在 body。 */
|
|
24
|
+
export interface FlowQueryParams extends Tam140504002InBody {
|
|
6
25
|
pageIndex: number // 页码,从 1 开始。
|
|
7
26
|
pageSize: number // 每页条数。
|
|
8
27
|
}
|
|
9
28
|
|
|
29
|
+
/** 页面筛选表单的取值;与请求类型同名字段一一对应,空字符串表示不限制。 */
|
|
30
|
+
export type RealtimeFlowFilters = { [K in keyof Tam140504002InBody]-?: string }
|
|
31
|
+
|
|
10
32
|
/** Tam140504002Out.Body:计数字段遵循接口 integer 类型。 */
|
|
11
33
|
export interface Tam140504002OutBody {
|
|
12
34
|
txnLists?: Tam140504002OutBodyTxnLists[] // 当前页的交易流水。
|
|
@@ -181,7 +181,7 @@ const validateForm = (values: ForecastFormValues, mode: 'create' | 'edit' = 'cre
|
|
|
181
181
|
/** 读取详情并与列表记录合并:详情没有的字段由同一条列表记录补充。 */
|
|
182
182
|
const fetchDetail = async (row: ForecastRow): Promise<ForecastDetail> => {
|
|
183
183
|
if (!row.predRefNo?.trim()) throw new Error('预报流水号缺失,无法读取详情')
|
|
184
|
-
const body = ensureSuccess<any>(await API.getDetailApi({ predRefNo: row.predRefNo }), '读取预报详情失败')
|
|
184
|
+
const body = ensureSuccess<any>(await API.getDetailApi({ predRefNo: row.predRefNo }) as any, '读取预报详情失败')
|
|
185
185
|
if (!body || !Object.keys(body).length) throw new Error('服务端未返回预报详情')
|
|
186
186
|
if (body.predRefNo && body.predRefNo !== row.predRefNo) throw new Error('返回的预报流水号与当前记录不一致')
|
|
187
187
|
const definedBody = Object.fromEntries(Object.entries(body).filter(([, value]) => value !== undefined && value !== null))
|
|
@@ -291,7 +291,7 @@ const loadList = async () => {
|
|
|
291
291
|
clearListSelection()
|
|
292
292
|
try {
|
|
293
293
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
294
|
-
const response = await API.queryListApi({ ...query, opType: 'query', pageIndex, pageSize })
|
|
294
|
+
const response = await API.queryListApi({ ...query, opType: 'query', pageIndex, pageSize }) as any
|
|
295
295
|
if (disposed || currentId !== listRequestId) return
|
|
296
296
|
const page = readPage(ensureSuccess(response, '预报查询失败'))
|
|
297
297
|
const lastPage = Math.max(1, Math.ceil(page.total / pageSize))
|
|
@@ -380,7 +380,7 @@ async function deleteRecords(records: ForecastRow[]) {
|
|
|
380
380
|
buttonSize: listTableSettings.value.size,
|
|
381
381
|
})
|
|
382
382
|
if (disposed) return
|
|
383
|
-
ensureSuccess(await API.deleteApi(references), '删除预报失败')
|
|
383
|
+
ensureSuccess(await API.deleteApi(references) as any, '删除预报失败')
|
|
384
384
|
if (disposed) return
|
|
385
385
|
ElMessage.success('删除请求已处理')
|
|
386
386
|
await loadList()
|
|
@@ -587,7 +587,7 @@ const submit = async () => {
|
|
|
587
587
|
if (key !== 'custRefSeq' && value?.trim()) Object.assign(body, { [key]: value.trim() })
|
|
588
588
|
}
|
|
589
589
|
if (body.predAmt) body.predAmt = normalizeAmount(body.predAmt)
|
|
590
|
-
ensureSuccess(await API.addApi(body), '新增预报失败')
|
|
590
|
+
ensureSuccess(await API.addApi(body) as any, '新增预报失败')
|
|
591
591
|
} else {
|
|
592
592
|
if (!editorPredRefNo.value) throw new Error('预报流水号缺失,无法修改')
|
|
593
593
|
const body: ForecastEditBody = { predRefSeq: editorPredRefNo.value }
|
|
@@ -600,7 +600,7 @@ const submit = async () => {
|
|
|
600
600
|
body.custRefSeq = customerReference
|
|
601
601
|
}
|
|
602
602
|
if (body.predAmt) body.predAmt = normalizeAmount(body.predAmt)
|
|
603
|
-
ensureSuccess(await API.editApi(body), '修改预报失败')
|
|
603
|
+
ensureSuccess(await API.editApi(body) as any, '修改预报失败')
|
|
604
604
|
}
|
|
605
605
|
if (disposed) return
|
|
606
606
|
ElMessage.success(editorMode.value === 'create' ? '新增请求已处理' : '修改请求已处理')
|
|
@@ -275,7 +275,7 @@ const loadList = async () => {
|
|
|
275
275
|
try {
|
|
276
276
|
// head 为公共响应头,body 为包含明细列表的业务数据;
|
|
277
277
|
// body 内的 totalCount、totalPage 供服务端分页时使用,当前接按返回的完整列表本地分页。
|
|
278
|
-
const { head, body } = await API.queryListApi(appliedQuery)
|
|
278
|
+
const { head, body } = await API.queryListApi(appliedQuery) as any
|
|
279
279
|
if (currentRequestId !== requestId) return
|
|
280
280
|
if (head?.retCode !== '00000') {
|
|
281
281
|
throw new Error(head?.retMsg || '查询失败')
|
|
@@ -111,7 +111,7 @@ const loadList = async () => {
|
|
|
111
111
|
clearSelection()
|
|
112
112
|
try {
|
|
113
113
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
114
|
-
const response = await API.queryListApi(params)
|
|
114
|
+
const response = await API.queryListApi(params) as any
|
|
115
115
|
if (disposed || requestId !== listRequestId) return
|
|
116
116
|
const body: ParameterListBody | null = ensureSuccess(response, '参数查询失败')
|
|
117
117
|
if (!body || !Array.isArray(body.resultList)) throw new Error('查询结果缺少参数列表')
|
|
@@ -207,14 +207,14 @@ const submitParameter = async () => {
|
|
|
207
207
|
pendingMutation.value = mode
|
|
208
208
|
try {
|
|
209
209
|
const response = mode === 'create'
|
|
210
|
-
? await API.addApi({ ...values, paraName: values.paraName.trim() })
|
|
210
|
+
? await API.addApi({ ...values, paraName: values.paraName.trim() }) as any
|
|
211
211
|
: await API.editApi({
|
|
212
212
|
paraName: dialogSource.value!.paraName!,
|
|
213
213
|
paraType: values.paraType,
|
|
214
214
|
paraValue: values.paraValue,
|
|
215
215
|
paraDesc: values.paraDesc,
|
|
216
216
|
remark: values.remark,
|
|
217
|
-
})
|
|
217
|
+
}) as any
|
|
218
218
|
if (disposed) return
|
|
219
219
|
ensureSuccess(response, mode === 'create' ? '新增参数失败' : '修改参数失败')
|
|
220
220
|
ElMessage.success(response.head.retMsg?.trim() || (mode === 'create' ? '新增请求成功' : '修改请求成功'))
|
|
@@ -246,7 +246,7 @@ const submitDelete = async () => {
|
|
|
246
246
|
pendingMutation.value = 'delete'
|
|
247
247
|
deleteError.value = ''
|
|
248
248
|
try {
|
|
249
|
-
const response = await API.deleteApi(deleteNames.value)
|
|
249
|
+
const response = await API.deleteApi(deleteNames.value) as any
|
|
250
250
|
if (disposed) return
|
|
251
251
|
ensureSuccess(response, '删除参数失败')
|
|
252
252
|
ElMessage.success(response.head.retMsg?.trim() || '删除请求成功')
|
|
@@ -227,7 +227,7 @@ const submitWriteOff = async () => {
|
|
|
227
227
|
}))
|
|
228
228
|
mutation.value = 'writeOff'
|
|
229
229
|
try {
|
|
230
|
-
ensureSuccess(await API.writeOffApi(tranList.length ? { predList, tranList } : { predList }), '核销提交失败')
|
|
230
|
+
ensureSuccess(await API.writeOffApi(tranList.length ? { predList, tranList } : { predList }) as any, '核销提交失败')
|
|
231
231
|
ElMessage.success('核销请求已提交')
|
|
232
232
|
writeOffVisible.value = false
|
|
233
233
|
await refreshBoth()
|
|
@@ -288,7 +288,7 @@ const cancelWriteOff = async () => {
|
|
|
288
288
|
const payload = predList.length && tranList.length
|
|
289
289
|
? { predList, tranList }
|
|
290
290
|
: predList.length ? { predList } : { tranList }
|
|
291
|
-
ensureSuccess(await API.cancelWriteOffApi(payload), '撤销核销提交失败')
|
|
291
|
+
ensureSuccess(await API.cancelWriteOffApi(payload) as any, '撤销核销提交失败')
|
|
292
292
|
ElMessage.success('撤销核销请求已提交')
|
|
293
293
|
await refreshBoth()
|
|
294
294
|
} catch (error) {
|
|
@@ -406,7 +406,7 @@ const loadForecastList = async () => {
|
|
|
406
406
|
forecastTableRef.value?.getElTable()?.clearSelection()
|
|
407
407
|
try {
|
|
408
408
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
409
|
-
const response = await API.queryForecastApi({ ...query, pageIndex, pageSize })
|
|
409
|
+
const response = await API.queryForecastApi({ ...query, pageIndex, pageSize }) as any
|
|
410
410
|
if (disposed || currentId !== forecastRequestId) return
|
|
411
411
|
const page = readPage<any>(ensureSuccess<any>(response, '核销预报查询失败'), '查询结果缺少预报列表,请联系服务端确认返回数据')
|
|
412
412
|
const lastPage = Math.max(1, Math.ceil(page.total / pageSize))
|
|
@@ -503,7 +503,7 @@ const submitEdit = async () => {
|
|
|
503
503
|
predAmt: editForm.value.predAmt,
|
|
504
504
|
beforeVerifyAmt: editForm.value.beforeVerifyAmt,
|
|
505
505
|
verifyAmt: amount,
|
|
506
|
-
}), '修改提交失败')
|
|
506
|
+
}) as any, '修改提交失败')
|
|
507
507
|
if (disposed) return
|
|
508
508
|
ElMessage.success('修改请求已提交')
|
|
509
509
|
editVisible.value = false
|
|
@@ -614,7 +614,7 @@ const loadFlowList = async () => {
|
|
|
614
614
|
flowTableRef.value?.getElTable()?.clearSelection()
|
|
615
615
|
try {
|
|
616
616
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
617
|
-
const response = await API.queryFlowApi({ ...query, pageIndex, pageSize })
|
|
617
|
+
const response = await API.queryFlowApi({ ...query, pageIndex, pageSize }) as any
|
|
618
618
|
if (disposed || currentId !== flowRequestId) return
|
|
619
619
|
const page = readPage<any>(ensureSuccess<any>(response, '核销流水查询失败'), '查询结果缺少流水列表,请联系服务端确认返回数据')
|
|
620
620
|
const lastPage = Math.max(1, Math.ceil(page.total / pageSize))
|
package/src/view/112.xlsx
DELETED
|
Binary file
|