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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue3-element-plus-app-chu",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "files": [
@@ -4,8 +4,8 @@ import type { FlowQueryParams } from './typs'
4
4
  export default {
5
5
  /**
6
6
  * 分页查询数字人民币实时流水(140504002)。
7
- * 接口业务 body 为空,不声明日期、姓名、金额或核销状态筛选。
8
- * @param params 公共分页参数,由请求层放入 head 并转换为字符串。
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 disposed = false
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
- /** 公共 head 承载分页,140504002 的业务 body 不发送旧核销筛选条件。 */
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
- <el-alert v-if="flowQueryError" :title="flowQueryError" type="error" show-icon :closable="false">
199
- <el-button link type="primary" :disabled="flowLoading" @click="void loadFlowList()">重新查询</el-button>
200
- </el-alert>
201
-
202
- <div class="table-region">
203
- <ArtDataTable
204
- v-model:settings="flowTableSettings"
205
- class="flow-table"
206
- fill
207
- title="数字人民币实时流水"
208
- toolbar-layout="refresh,size,fullscreen,columns,settings"
209
- :data="flowRows"
210
- :columns="flowColumns"
211
- :loading="flowLoading"
212
- :pagination="flowPagination"
213
- :pagination-options="flowPaginationOptions"
214
- row-key="consumerSeqNo"
215
- :empty-text="flowQueryError ? '查询失败,请重新查询' : '暂无实时流水信息'"
216
- @pagination:current-change="changeFlowPage"
217
- @pagination:size-change="(size: number) => changeFlowPage(1, size)"
218
- @refresh="void loadFlowList()"
219
- >
220
- <template #toolbar-left>
221
- <el-button type="primary" :size="flowTableSettings.size" :loading="flowLoading" @click="searchFlow">查询</el-button>
222
- <el-button type="primary" plain :size="flowTableSettings.size" :loading="realtimeChecking" @click="void checkRealtimeFlow()">实时查询流水</el-button>
223
- </template>
224
- <template #txnAmount="{ row }"><span class="amount-cell">{{ formatAmount(row.txnAmt) }}</span></template>
225
- </ArtDataTable>
226
- </div>
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)的业务 body 为空。 */
2
- export type Tam140504002InBody = Record<string, never>
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,业务 body 保持为空。 */
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