vue2server7 7.0.26 → 7.0.28
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.
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="date-range" :class="{ 'is-disabled': disabled }">
|
|
3
|
+
<div class="date-range__row">
|
|
4
|
+
<el-date-picker
|
|
5
|
+
v-model="startVal"
|
|
6
|
+
class="date-range__picker"
|
|
7
|
+
:class="{ 'is-error': showError }"
|
|
8
|
+
:type="pickerType"
|
|
9
|
+
:placeholder="startPlaceholder"
|
|
10
|
+
:disabled="disabled"
|
|
11
|
+
:disabled-date="disabledStartDate"
|
|
12
|
+
:value-format="valueFormat"
|
|
13
|
+
:format="displayFormat"
|
|
14
|
+
clearable
|
|
15
|
+
@change="onStartChange"
|
|
16
|
+
@focus="onStartFocus"
|
|
17
|
+
@blur="onStartBlur"
|
|
18
|
+
/>
|
|
19
|
+
<span class="date-range__separator">{{ separator }}</span>
|
|
20
|
+
<el-date-picker
|
|
21
|
+
v-model="endVal"
|
|
22
|
+
class="date-range__picker"
|
|
23
|
+
:class="{ 'is-error': showError }"
|
|
24
|
+
:type="pickerType"
|
|
25
|
+
:placeholder="endPlaceholder"
|
|
26
|
+
:disabled="disabled"
|
|
27
|
+
:disabled-date="disabledEndDate"
|
|
28
|
+
:value-format="valueFormat"
|
|
29
|
+
:format="displayFormat"
|
|
30
|
+
clearable
|
|
31
|
+
@change="onEndChange"
|
|
32
|
+
@focus="onEndFocus"
|
|
33
|
+
@blur="onEndBlur"
|
|
34
|
+
/>
|
|
35
|
+
</div>
|
|
36
|
+
<span v-if="showError" class="date-range__error">{{ activeErrorMessage }}</span>
|
|
37
|
+
</div>
|
|
38
|
+
</template>
|
|
39
|
+
|
|
40
|
+
<script setup lang="ts">
|
|
41
|
+
import { ref, watch, computed } from 'vue'
|
|
42
|
+
|
|
43
|
+
export type DateRangeValue = [string | null, string | null]
|
|
44
|
+
|
|
45
|
+
export type MaxSpanDaysInput = number | [number]
|
|
46
|
+
|
|
47
|
+
function resolveMaxSpanDays(v: MaxSpanDaysInput | undefined): number | null {
|
|
48
|
+
if (v === undefined) return null
|
|
49
|
+
const n = Array.isArray(v) ? v[0] : v
|
|
50
|
+
if (typeof n !== 'number' || !Number.isFinite(n) || n <= 0) return null
|
|
51
|
+
return Math.floor(n)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function startOfLocalDay(d: Date): Date {
|
|
55
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate())
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** 按自然日计:end 在 start 当天为 0,隔天为 1 … */
|
|
59
|
+
function calendarDayDiff(start: Date, end: Date): number {
|
|
60
|
+
const s = startOfLocalDay(start).getTime()
|
|
61
|
+
const e = startOfLocalDay(end).getTime()
|
|
62
|
+
return Math.round((e - s) / 86400000)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** 含首尾的自然日个数,如 1 月 1 日~1 月 15 日为 15 */
|
|
66
|
+
function inclusiveDaySpan(start: Date, end: Date): number {
|
|
67
|
+
return calendarDayDiff(start, end) + 1
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const props = withDefaults(defineProps<{
|
|
71
|
+
/** 数组模式绑定值 [start, end] */
|
|
72
|
+
modelValue?: DateRangeValue
|
|
73
|
+
/** 双字段模式 - 起始日期 */
|
|
74
|
+
start?: string | null
|
|
75
|
+
/** 双字段模式 - 结束日期 */
|
|
76
|
+
end?: string | null
|
|
77
|
+
startPlaceholder?: string
|
|
78
|
+
endPlaceholder?: string
|
|
79
|
+
separator?: string
|
|
80
|
+
/** date-picker 的 type,如 date / datetime / month / year */
|
|
81
|
+
pickerType?: 'date' | 'datetime' | 'month' | 'year'
|
|
82
|
+
/** 传给 el-date-picker 的 value-format */
|
|
83
|
+
valueFormat?: string
|
|
84
|
+
/** 传给 el-date-picker 的 format(显示格式) */
|
|
85
|
+
displayFormat?: string
|
|
86
|
+
disabled?: boolean
|
|
87
|
+
/** 是否限制结束日期不能早于开始日期(禁用不合法的日期) */
|
|
88
|
+
linkage?: boolean
|
|
89
|
+
/**
|
|
90
|
+
* 最长区间(自然日,含起止当天)。可传数字如 15,或单元素数组 [15]。
|
|
91
|
+
* 仅对 pickerType 为 date / datetime 生效。
|
|
92
|
+
*/
|
|
93
|
+
maxSpanDays?: MaxSpanDaysInput
|
|
94
|
+
errorMessage?: string
|
|
95
|
+
/** 超出 maxSpanDays 时的提示(默认带天数) */
|
|
96
|
+
maxSpanErrorMessage?: string
|
|
97
|
+
}>(), {
|
|
98
|
+
modelValue: undefined,
|
|
99
|
+
start: undefined,
|
|
100
|
+
end: undefined,
|
|
101
|
+
startPlaceholder: '开始日期',
|
|
102
|
+
endPlaceholder: '结束日期',
|
|
103
|
+
separator: '至',
|
|
104
|
+
pickerType: 'date',
|
|
105
|
+
valueFormat: 'YYYY-MM-DD',
|
|
106
|
+
displayFormat: undefined,
|
|
107
|
+
disabled: false,
|
|
108
|
+
linkage: true,
|
|
109
|
+
maxSpanDays: undefined,
|
|
110
|
+
errorMessage: '结束日期不能早于开始日期',
|
|
111
|
+
maxSpanErrorMessage: undefined
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
const emit = defineEmits<{
|
|
115
|
+
'update:modelValue': [value: DateRangeValue]
|
|
116
|
+
'update:start': [value: string | null]
|
|
117
|
+
'update:end': [value: string | null]
|
|
118
|
+
'validate': [valid: boolean]
|
|
119
|
+
}>()
|
|
120
|
+
|
|
121
|
+
const isArrayMode = computed(() => props.modelValue !== undefined)
|
|
122
|
+
|
|
123
|
+
const startVal = ref<string | null>(null)
|
|
124
|
+
const endVal = ref<string | null>(null)
|
|
125
|
+
|
|
126
|
+
const startFocused = ref(false)
|
|
127
|
+
const endFocused = ref(false)
|
|
128
|
+
const hasBlurred = ref(false)
|
|
129
|
+
|
|
130
|
+
function toDate(val: string | null | undefined): Date | null {
|
|
131
|
+
if (!val) return null
|
|
132
|
+
const d = new Date(val)
|
|
133
|
+
return Number.isNaN(d.getTime()) ? null : d
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const effectiveMaxSpan = computed(() => resolveMaxSpanDays(props.maxSpanDays))
|
|
137
|
+
|
|
138
|
+
const spanConstraintApplies = computed(
|
|
139
|
+
() =>
|
|
140
|
+
effectiveMaxSpan.value !== null &&
|
|
141
|
+
(props.pickerType === 'date' || props.pickerType === 'datetime')
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
const orderInvalid = computed(() => {
|
|
145
|
+
const s = toDate(startVal.value)
|
|
146
|
+
const e = toDate(endVal.value)
|
|
147
|
+
return s !== null && e !== null && e < s
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
const spanInvalid = computed(() => {
|
|
151
|
+
if (!spanConstraintApplies.value || effectiveMaxSpan.value === null) return false
|
|
152
|
+
const s = toDate(startVal.value)
|
|
153
|
+
const e = toDate(endVal.value)
|
|
154
|
+
if (s === null || e === null || e < s) return false
|
|
155
|
+
return inclusiveDaySpan(s, e) > effectiveMaxSpan.value
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
const rangeInvalid = computed(() => orderInvalid.value || spanInvalid.value)
|
|
159
|
+
|
|
160
|
+
const showError = computed(
|
|
161
|
+
() => hasBlurred.value && !startFocused.value && !endFocused.value && rangeInvalid.value
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
const activeErrorMessage = computed(() => {
|
|
165
|
+
if (!showError.value) return ''
|
|
166
|
+
if (orderInvalid.value) return props.errorMessage
|
|
167
|
+
if (spanInvalid.value && effectiveMaxSpan.value !== null) {
|
|
168
|
+
return (
|
|
169
|
+
props.maxSpanErrorMessage ??
|
|
170
|
+
`日期区间最长为 ${effectiveMaxSpan.value} 天(含起止当天)`
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
return props.errorMessage
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
const disabledStartDate = (date: Date): boolean => {
|
|
177
|
+
if (props.linkage && endVal.value) {
|
|
178
|
+
const e = toDate(endVal.value)
|
|
179
|
+
if (e !== null && date.getTime() > e.getTime()) return true
|
|
180
|
+
}
|
|
181
|
+
if (
|
|
182
|
+
spanConstraintApplies.value &&
|
|
183
|
+
effectiveMaxSpan.value !== null &&
|
|
184
|
+
endVal.value
|
|
185
|
+
) {
|
|
186
|
+
const e = toDate(endVal.value)
|
|
187
|
+
if (e !== null) {
|
|
188
|
+
const maxDiff = effectiveMaxSpan.value - 1
|
|
189
|
+
if (calendarDayDiff(date, e) > maxDiff) return true
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return false
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const disabledEndDate = (date: Date): boolean => {
|
|
196
|
+
if (props.linkage && startVal.value) {
|
|
197
|
+
const s = toDate(startVal.value)
|
|
198
|
+
if (s !== null && date.getTime() < s.getTime()) return true
|
|
199
|
+
}
|
|
200
|
+
if (
|
|
201
|
+
spanConstraintApplies.value &&
|
|
202
|
+
effectiveMaxSpan.value !== null &&
|
|
203
|
+
startVal.value
|
|
204
|
+
) {
|
|
205
|
+
const s = toDate(startVal.value)
|
|
206
|
+
if (s !== null) {
|
|
207
|
+
const maxDiff = effectiveMaxSpan.value - 1
|
|
208
|
+
if (calendarDayDiff(s, date) > maxDiff) return true
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return false
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function emitValue() {
|
|
215
|
+
const s = startVal.value || null
|
|
216
|
+
const e = endVal.value || null
|
|
217
|
+
if (isArrayMode.value) {
|
|
218
|
+
emit('update:modelValue', [s, e])
|
|
219
|
+
} else {
|
|
220
|
+
emit('update:start', s)
|
|
221
|
+
emit('update:end', e)
|
|
222
|
+
}
|
|
223
|
+
emit('validate', !rangeInvalid.value)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function onStartChange() {
|
|
227
|
+
emitValue()
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function onEndChange() {
|
|
231
|
+
emitValue()
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function onStartFocus() {
|
|
235
|
+
startFocused.value = true
|
|
236
|
+
hasBlurred.value = false
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function onEndFocus() {
|
|
240
|
+
endFocused.value = true
|
|
241
|
+
hasBlurred.value = false
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function onStartBlur() {
|
|
245
|
+
startFocused.value = false
|
|
246
|
+
emitValue()
|
|
247
|
+
if (!endFocused.value) hasBlurred.value = true
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function onEndBlur() {
|
|
251
|
+
endFocused.value = false
|
|
252
|
+
emitValue()
|
|
253
|
+
if (!startFocused.value) hasBlurred.value = true
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function validate(): boolean {
|
|
257
|
+
hasBlurred.value = true
|
|
258
|
+
return !rangeInvalid.value
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function reset() {
|
|
262
|
+
startVal.value = null
|
|
263
|
+
endVal.value = null
|
|
264
|
+
hasBlurred.value = false
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
defineExpose({ validate, reset })
|
|
268
|
+
|
|
269
|
+
watch(
|
|
270
|
+
() => ({
|
|
271
|
+
isArr: isArrayMode.value,
|
|
272
|
+
s: isArrayMode.value ? props.modelValue?.[0] : props.start,
|
|
273
|
+
e: isArrayMode.value ? props.modelValue?.[1] : props.end
|
|
274
|
+
}),
|
|
275
|
+
({ s, e }) => {
|
|
276
|
+
const newS = s || null
|
|
277
|
+
const newE = e || null
|
|
278
|
+
if (newS !== startVal.value) startVal.value = newS
|
|
279
|
+
if (newE !== endVal.value) endVal.value = newE
|
|
280
|
+
},
|
|
281
|
+
{ immediate: true }
|
|
282
|
+
)
|
|
283
|
+
</script>
|
|
284
|
+
|
|
285
|
+
<style scoped>
|
|
286
|
+
.date-range {
|
|
287
|
+
display: flex;
|
|
288
|
+
flex-direction: column;
|
|
289
|
+
width: 100%;
|
|
290
|
+
min-width: 0;
|
|
291
|
+
box-sizing: border-box;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.date-range__row {
|
|
295
|
+
display: flex;
|
|
296
|
+
flex-direction: row;
|
|
297
|
+
flex-wrap: nowrap;
|
|
298
|
+
align-items: center;
|
|
299
|
+
gap: 8px;
|
|
300
|
+
width: 100%;
|
|
301
|
+
min-width: 0;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.date-range__picker {
|
|
305
|
+
flex: 1 1 0;
|
|
306
|
+
min-width: 0;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/* class 往往挂在 .el-date-editor 根上,用行容器做 :deep 更稳 */
|
|
310
|
+
.date-range__row :deep(.el-date-editor) {
|
|
311
|
+
width: 100%;
|
|
312
|
+
max-width: 100%;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.date-range__row :deep(.el-date-editor .el-input__wrapper) {
|
|
316
|
+
width: 100%;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.date-range__separator {
|
|
320
|
+
color: var(--el-text-color-primary);
|
|
321
|
+
font-size: 14px;
|
|
322
|
+
flex-shrink: 0;
|
|
323
|
+
white-space: nowrap;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.date-range.is-disabled .date-range__separator {
|
|
327
|
+
color: var(--el-text-color-placeholder);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.date-range__picker.is-error :deep(.el-input__wrapper) {
|
|
331
|
+
box-shadow: 0 0 0 1px var(--el-color-danger) inset;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.date-range__error {
|
|
335
|
+
display: block;
|
|
336
|
+
width: 100%;
|
|
337
|
+
min-width: 0;
|
|
338
|
+
color: var(--el-color-danger);
|
|
339
|
+
font-size: 12px;
|
|
340
|
+
line-height: 1.4;
|
|
341
|
+
padding-top: 4px;
|
|
342
|
+
}
|
|
343
|
+
</style>
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section class="page date-range-page">
|
|
3
|
+
<h1 class="title">日期区间组件</h1>
|
|
4
|
+
<p class="desc">演示 <code>DateRange</code> 的数组绑定、双字段绑定与不同 <code>pickerType</code>。</p>
|
|
5
|
+
|
|
6
|
+
<el-card class="demo-card" shadow="never">
|
|
7
|
+
<template #header>
|
|
8
|
+
<span>数组绑定 <code>v-model</code></span>
|
|
9
|
+
</template>
|
|
10
|
+
<DateRange v-model="rangeArray" class="demo-control" />
|
|
11
|
+
<div class="demo-output">
|
|
12
|
+
当前值:<code>{{ JSON.stringify(rangeArray) }}</code>
|
|
13
|
+
</div>
|
|
14
|
+
</el-card>
|
|
15
|
+
|
|
16
|
+
<el-card class="demo-card" shadow="never">
|
|
17
|
+
<template #header>
|
|
18
|
+
<span>双字段绑定 <code>start</code> / <code>end</code></span>
|
|
19
|
+
</template>
|
|
20
|
+
<DateRange
|
|
21
|
+
v-model:start="startField"
|
|
22
|
+
v-model:end="endField"
|
|
23
|
+
class="demo-control"
|
|
24
|
+
/>
|
|
25
|
+
<div class="demo-output">
|
|
26
|
+
start:<code>{{ startField ?? 'null' }}</code>,end:<code>{{ endField ?? 'null' }}</code>
|
|
27
|
+
</div>
|
|
28
|
+
</el-card>
|
|
29
|
+
|
|
30
|
+
<el-card class="demo-card" shadow="never">
|
|
31
|
+
<template #header>
|
|
32
|
+
<span>最长区间 <code>max-span-days</code>(如 15 或 <code>[15]</code>,含首尾共 15 个自然日)</span>
|
|
33
|
+
</template>
|
|
34
|
+
<DateRange v-model="rangeMaxSpan" :max-span-days="[15]" class="demo-control" />
|
|
35
|
+
<div class="demo-output">
|
|
36
|
+
当前值:<code>{{ JSON.stringify(rangeMaxSpan) }}</code>
|
|
37
|
+
</div>
|
|
38
|
+
</el-card>
|
|
39
|
+
|
|
40
|
+
<el-card class="demo-card" shadow="never">
|
|
41
|
+
<template #header>
|
|
42
|
+
<span>日期时间 <code>pickerType="datetime"</code></span>
|
|
43
|
+
</template>
|
|
44
|
+
<DateRange
|
|
45
|
+
v-model="rangeDatetime"
|
|
46
|
+
picker-type="datetime"
|
|
47
|
+
value-format="YYYY-MM-DD HH:mm:ss"
|
|
48
|
+
start-placeholder="开始时间"
|
|
49
|
+
end-placeholder="结束时间"
|
|
50
|
+
class="demo-control"
|
|
51
|
+
/>
|
|
52
|
+
<div class="demo-output">
|
|
53
|
+
当前值:<code>{{ JSON.stringify(rangeDatetime) }}</code>
|
|
54
|
+
</div>
|
|
55
|
+
</el-card>
|
|
56
|
+
|
|
57
|
+
<el-card class="demo-card" shadow="never">
|
|
58
|
+
<template #header>
|
|
59
|
+
<span>禁用态</span>
|
|
60
|
+
</template>
|
|
61
|
+
<DateRange
|
|
62
|
+
v-model="rangeDisabled"
|
|
63
|
+
disabled
|
|
64
|
+
class="demo-control"
|
|
65
|
+
/>
|
|
66
|
+
</el-card>
|
|
67
|
+
</section>
|
|
68
|
+
</template>
|
|
69
|
+
|
|
70
|
+
<script setup lang="ts">
|
|
71
|
+
import { ref } from 'vue'
|
|
72
|
+
import DateRange, { type DateRangeValue } from '../components/DateRange.vue'
|
|
73
|
+
|
|
74
|
+
const rangeArray = ref<DateRangeValue>([null, null])
|
|
75
|
+
const startField = ref<string | null>(null)
|
|
76
|
+
const endField = ref<string | null>(null)
|
|
77
|
+
const rangeMaxSpan = ref<DateRangeValue>([null, null])
|
|
78
|
+
const rangeDatetime = ref<DateRangeValue>([null, null])
|
|
79
|
+
const rangeDisabled = ref<DateRangeValue>(['2026-01-01', '2026-01-31'])
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
<style scoped>
|
|
83
|
+
.page.date-range-page {
|
|
84
|
+
padding: 20px 24px;
|
|
85
|
+
max-width: 720px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.title {
|
|
89
|
+
margin: 0 0 8px;
|
|
90
|
+
font-size: 20px;
|
|
91
|
+
font-weight: 600;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.desc {
|
|
95
|
+
margin: 0 0 20px;
|
|
96
|
+
color: var(--el-text-color-secondary);
|
|
97
|
+
font-size: 14px;
|
|
98
|
+
line-height: 1.5;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.demo-card {
|
|
102
|
+
margin-bottom: 16px;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.demo-card:last-child {
|
|
106
|
+
margin-bottom: 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.demo-control {
|
|
110
|
+
max-width: 560px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.demo-output {
|
|
114
|
+
margin-top: 12px;
|
|
115
|
+
font-size: 13px;
|
|
116
|
+
color: var(--el-text-color-regular);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.demo-output code {
|
|
120
|
+
font-size: 12px;
|
|
121
|
+
}
|
|
122
|
+
</style>
|
|
@@ -1,71 +1,80 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<section class="page position-report-page">
|
|
3
|
-
<
|
|
3
|
+
<header class="page-header">
|
|
4
|
+
<h1 class="title">头寸报备信息</h1>
|
|
5
|
+
<span class="header-badge" aria-hidden="true" />
|
|
6
|
+
</header>
|
|
4
7
|
|
|
5
8
|
<el-form
|
|
6
9
|
ref="formRef"
|
|
7
10
|
:model="form"
|
|
8
11
|
:rules="rules"
|
|
9
|
-
label-width="
|
|
12
|
+
label-width="168px"
|
|
10
13
|
label-suffix=":"
|
|
11
14
|
class="report-form"
|
|
12
15
|
>
|
|
13
|
-
<!--
|
|
14
|
-
<el-row :gutter="
|
|
16
|
+
<!-- 按截图三列对齐 -->
|
|
17
|
+
<el-row :gutter="20">
|
|
15
18
|
<el-col :span="8">
|
|
16
|
-
<el-form-item label="头寸报备编号" prop="
|
|
17
|
-
<el-input v-model="form.
|
|
19
|
+
<el-form-item label="头寸报备编号" prop="id">
|
|
20
|
+
<el-input v-model="form.id" placeholder="" clearable />
|
|
18
21
|
</el-form-item>
|
|
19
22
|
</el-col>
|
|
20
23
|
<el-col :span="8">
|
|
21
|
-
<el-form-item label="业务类型" prop="
|
|
22
|
-
<el-
|
|
24
|
+
<el-form-item label="业务类型" prop="forecastType">
|
|
25
|
+
<el-select v-model="form.forecastType" placeholder="请选择" style="width: 100%">
|
|
26
|
+
<el-option
|
|
27
|
+
v-for="o in forecastTypeOptions"
|
|
28
|
+
:key="o.value"
|
|
29
|
+
:label="o.label"
|
|
30
|
+
:value="o.value"
|
|
31
|
+
/>
|
|
32
|
+
</el-select>
|
|
23
33
|
</el-form-item>
|
|
24
34
|
</el-col>
|
|
25
35
|
<el-col :span="8">
|
|
26
|
-
<el-form-item label="客户分类" prop="
|
|
27
|
-
<el-
|
|
28
|
-
<el-option label="对公" value="对公" />
|
|
29
|
-
<el-option label="对私" value="对私" />
|
|
30
|
-
</el-select>
|
|
36
|
+
<el-form-item label="客户分类" prop="clientType">
|
|
37
|
+
<el-input v-model="clientTypeLabel" disabled />
|
|
31
38
|
</el-form-item>
|
|
32
39
|
</el-col>
|
|
33
40
|
</el-row>
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
<el-row :gutter="24">
|
|
42
|
+
<el-row :gutter="20">
|
|
37
43
|
<el-col :span="8">
|
|
38
|
-
<el-form-item label="
|
|
39
|
-
<el-select v-model="form.
|
|
40
|
-
<el-option
|
|
41
|
-
|
|
44
|
+
<el-form-item label="证件类型" prop="priIdCardType">
|
|
45
|
+
<el-select v-model="form.priIdCardType" placeholder="请选择" style="width: 100%">
|
|
46
|
+
<el-option
|
|
47
|
+
v-for="o in priIdCardTypeOptions"
|
|
48
|
+
:key="o.value"
|
|
49
|
+
:label="o.label"
|
|
50
|
+
:value="o.value"
|
|
51
|
+
/>
|
|
42
52
|
</el-select>
|
|
43
53
|
</el-form-item>
|
|
44
54
|
</el-col>
|
|
45
55
|
<el-col :span="8">
|
|
46
|
-
<el-form-item label="
|
|
47
|
-
<el-input v-model="form.
|
|
56
|
+
<el-form-item label="对公组织机构代码" prop="pubOrgCode">
|
|
57
|
+
<el-input v-model="form.pubOrgCode" clearable />
|
|
48
58
|
</el-form-item>
|
|
49
59
|
</el-col>
|
|
50
60
|
<el-col :span="8">
|
|
51
|
-
<el-form-item label="客户名称" prop="
|
|
52
|
-
<el-input v-model="form.
|
|
61
|
+
<el-form-item label="客户名称" prop="custName">
|
|
62
|
+
<el-input v-model="form.custName" disabled />
|
|
53
63
|
</el-form-item>
|
|
54
64
|
</el-col>
|
|
55
65
|
</el-row>
|
|
56
66
|
|
|
57
|
-
|
|
58
|
-
<el-row :gutter="24">
|
|
67
|
+
<el-row :gutter="20">
|
|
59
68
|
<el-col :span="8">
|
|
60
|
-
<el-form-item label="
|
|
61
|
-
<div
|
|
62
|
-
<el-select v-model="form.currency" placeholder="币种"
|
|
69
|
+
<el-form-item label="拟付款币种/金额" prop="currency">
|
|
70
|
+
<div class="currency-amt">
|
|
71
|
+
<el-select v-model="form.currency" placeholder="币种" class="currency-amt__cur">
|
|
63
72
|
<el-option label="CNY - 人民币" value="CNY" />
|
|
64
73
|
<el-option label="USD - 美元" value="USD" />
|
|
65
74
|
<el-option label="EUR - 欧元" value="EUR" />
|
|
66
75
|
<el-option label="HKD - 港币" value="HKD" />
|
|
67
76
|
</el-select>
|
|
68
|
-
<el-input v-model="form.
|
|
77
|
+
<el-input v-model="form.forecastAmt" class="currency-amt__amt" clearable />
|
|
69
78
|
</div>
|
|
70
79
|
</el-form-item>
|
|
71
80
|
</el-col>
|
|
@@ -81,17 +90,14 @@
|
|
|
81
90
|
/>
|
|
82
91
|
</el-form-item>
|
|
83
92
|
</el-col>
|
|
84
|
-
<el-col :span="8">
|
|
85
|
-
<
|
|
86
|
-
<el-input v-model="form.accountName" placeholder="请输入" />
|
|
87
|
-
</el-form-item>
|
|
93
|
+
<el-col :span="8" class="form-col--spacer">
|
|
94
|
+
<div class="form-col-placeholder" aria-hidden="true" />
|
|
88
95
|
</el-col>
|
|
89
96
|
</el-row>
|
|
90
97
|
|
|
91
|
-
|
|
92
|
-
<el-row :gutter="24">
|
|
98
|
+
<el-row :gutter="20">
|
|
93
99
|
<el-col :span="8">
|
|
94
|
-
<el-form-item label="
|
|
100
|
+
<el-form-item label="计划汇款日期" prop="planDate">
|
|
95
101
|
<el-date-picker
|
|
96
102
|
v-model="form.planDate"
|
|
97
103
|
type="date"
|
|
@@ -103,9 +109,9 @@
|
|
|
103
109
|
</el-form-item>
|
|
104
110
|
</el-col>
|
|
105
111
|
<el-col :span="8">
|
|
106
|
-
<el-form-item label="
|
|
112
|
+
<el-form-item label="报备日期" prop="bigForDate">
|
|
107
113
|
<el-date-picker
|
|
108
|
-
v-model="form.
|
|
114
|
+
v-model="form.bigForDate"
|
|
109
115
|
type="date"
|
|
110
116
|
placeholder="请选择日期"
|
|
111
117
|
format="YYYY-MM-DD"
|
|
@@ -115,150 +121,244 @@
|
|
|
115
121
|
</el-form-item>
|
|
116
122
|
</el-col>
|
|
117
123
|
<el-col :span="8">
|
|
118
|
-
<el-form-item label="
|
|
119
|
-
<el-input v-model="form.
|
|
124
|
+
<el-form-item label="报备时间" prop="bigForTime">
|
|
125
|
+
<el-input v-model="form.bigForTime" placeholder="HHmmss" clearable />
|
|
120
126
|
</el-form-item>
|
|
121
127
|
</el-col>
|
|
122
128
|
</el-row>
|
|
123
129
|
|
|
124
|
-
|
|
125
|
-
<el-row :gutter="24">
|
|
130
|
+
<el-row :gutter="20">
|
|
126
131
|
<el-col :span="8">
|
|
127
|
-
<el-form-item label="
|
|
128
|
-
<el-select v-model="form.
|
|
129
|
-
<el-option label="
|
|
130
|
-
<el-option label="
|
|
132
|
+
<el-form-item label="是否退汇" prop="rtnFlag">
|
|
133
|
+
<el-select v-model="form.rtnFlag" placeholder="请选择" style="width: 100%">
|
|
134
|
+
<el-option label="否" value="01" />
|
|
135
|
+
<el-option label="是" value="02" />
|
|
131
136
|
</el-select>
|
|
132
137
|
</el-form-item>
|
|
133
138
|
</el-col>
|
|
134
139
|
<el-col :span="8">
|
|
135
|
-
<el-form-item label="原银行业务编号" prop="
|
|
136
|
-
<el-input
|
|
140
|
+
<el-form-item label="原银行业务编号" prop="oriInnerRefNo">
|
|
141
|
+
<el-input
|
|
142
|
+
v-model="form.oriInnerRefNo"
|
|
143
|
+
maxlength="16"
|
|
144
|
+
show-word-limit
|
|
145
|
+
placeholder="退汇为「是」时必填,16 位"
|
|
146
|
+
clearable
|
|
147
|
+
/>
|
|
137
148
|
</el-form-item>
|
|
138
149
|
</el-col>
|
|
139
150
|
<el-col :span="8">
|
|
140
|
-
<el-form-item label="
|
|
141
|
-
<el-
|
|
142
|
-
<el-option label="CIPSCNSHXXX" value="CIPSCNSHXXX" />
|
|
143
|
-
<el-option label="BKCHCNBJXXX" value="BKCHCNBJXXX" />
|
|
144
|
-
</el-select>
|
|
151
|
+
<el-form-item label="账户行" prop="nostro">
|
|
152
|
+
<el-input v-model="form.nostro" clearable />
|
|
145
153
|
</el-form-item>
|
|
146
154
|
</el-col>
|
|
147
155
|
</el-row>
|
|
148
156
|
|
|
149
|
-
|
|
150
|
-
<el-row :gutter="24">
|
|
157
|
+
<el-row :gutter="20">
|
|
151
158
|
<el-col :span="8">
|
|
152
|
-
<el-form-item label="收款银行" prop="
|
|
153
|
-
<el-input v-model="form.
|
|
159
|
+
<el-form-item label="收款银行" prop="swiftCode">
|
|
160
|
+
<el-input v-model="form.swiftCode" placeholder="最终收款行 SWIFT" clearable />
|
|
154
161
|
</el-form-item>
|
|
155
162
|
</el-col>
|
|
156
163
|
<el-col :span="8">
|
|
157
|
-
<el-form-item label="收款银行开户行" prop="
|
|
158
|
-
<el-input v-model="form.
|
|
164
|
+
<el-form-item label="收款银行开户行" prop="pyeAcctBicSCode">
|
|
165
|
+
<el-input v-model="form.pyeAcctBicSCode" clearable />
|
|
159
166
|
</el-form-item>
|
|
160
167
|
</el-col>
|
|
161
168
|
<el-col :span="8">
|
|
162
|
-
<el-form-item label="
|
|
163
|
-
<el-input v-model="form.
|
|
169
|
+
<el-form-item label="收款银行开户行名称" prop="pyeAcctBicName">
|
|
170
|
+
<el-input v-model="form.pyeAcctBicName" disabled />
|
|
164
171
|
</el-form-item>
|
|
165
172
|
</el-col>
|
|
166
173
|
</el-row>
|
|
167
174
|
|
|
168
|
-
|
|
169
|
-
<el-row :gutter="24">
|
|
175
|
+
<el-row :gutter="20">
|
|
170
176
|
<el-col :span="8">
|
|
171
|
-
<el-form-item label="
|
|
172
|
-
<el-select v-model="form.
|
|
173
|
-
<el-option label="
|
|
174
|
-
<el-option label="
|
|
177
|
+
<el-form-item label="邮件通知服务产品" prop="mailFlag">
|
|
178
|
+
<el-select v-model="form.mailFlag" placeholder="请选择" style="width: 100%">
|
|
179
|
+
<el-option label="否" value="0" />
|
|
180
|
+
<el-option label="是" value="1" />
|
|
175
181
|
</el-select>
|
|
176
182
|
</el-form-item>
|
|
177
183
|
</el-col>
|
|
178
184
|
<el-col :span="8">
|
|
179
|
-
<el-form-item label="多币种汇款产品" prop="
|
|
180
|
-
<el-select v-model="form.
|
|
181
|
-
<el-option label="
|
|
182
|
-
<el-option label="
|
|
185
|
+
<el-form-item label="多币种汇款产品" prop="mulCurFlag">
|
|
186
|
+
<el-select v-model="form.mulCurFlag" placeholder="请选择" style="width: 100%">
|
|
187
|
+
<el-option label="否" value="0" />
|
|
188
|
+
<el-option label="是" value="1" />
|
|
183
189
|
</el-select>
|
|
184
190
|
</el-form-item>
|
|
185
191
|
</el-col>
|
|
186
192
|
<el-col :span="8">
|
|
187
193
|
<el-form-item label="自贸区标识" prop="ftzFlag">
|
|
188
|
-
<el-
|
|
194
|
+
<el-select v-model="form.ftzFlag" placeholder="请选择" style="width: 100%">
|
|
195
|
+
<el-option label="否" value="0" />
|
|
196
|
+
<el-option label="是" value="1" />
|
|
197
|
+
</el-select>
|
|
189
198
|
</el-form-item>
|
|
190
199
|
</el-col>
|
|
191
200
|
</el-row>
|
|
192
201
|
|
|
193
|
-
|
|
194
|
-
<el-row :gutter="24">
|
|
202
|
+
<el-row :gutter="20">
|
|
195
203
|
<el-col :span="8">
|
|
196
|
-
<el-form-item label="报备人" prop="
|
|
197
|
-
<el-input v-model="form.
|
|
204
|
+
<el-form-item label="报备人" prop="linkMan">
|
|
205
|
+
<el-input v-model="form.linkMan" clearable />
|
|
198
206
|
</el-form-item>
|
|
199
207
|
</el-col>
|
|
200
208
|
<el-col :span="8">
|
|
201
|
-
<el-form-item label="联系电话" prop="
|
|
202
|
-
<el-input v-model="form.
|
|
209
|
+
<el-form-item label="联系电话" prop="linkWay">
|
|
210
|
+
<el-input v-model="form.linkWay" clearable />
|
|
203
211
|
</el-form-item>
|
|
204
212
|
</el-col>
|
|
205
213
|
<el-col :span="8">
|
|
206
|
-
<el-form-item label="
|
|
207
|
-
<el-
|
|
214
|
+
<el-form-item label="报备机构" prop="orgId">
|
|
215
|
+
<el-select
|
|
216
|
+
v-model="form.orgId"
|
|
217
|
+
filterable
|
|
218
|
+
allow-create
|
|
219
|
+
default-first-option
|
|
220
|
+
placeholder="请选择或输入"
|
|
221
|
+
style="width: 100%"
|
|
222
|
+
>
|
|
223
|
+
<el-option label="00301-和平里支行营业部" value="00301" />
|
|
224
|
+
</el-select>
|
|
208
225
|
</el-form-item>
|
|
209
226
|
</el-col>
|
|
210
227
|
</el-row>
|
|
211
228
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
<el-col :span="16">
|
|
229
|
+
<el-row :gutter="20">
|
|
230
|
+
<el-col :span="8">
|
|
215
231
|
<el-form-item label="报备说明" prop="remark">
|
|
216
|
-
<el-input v-model="form.remark" type="textarea" :rows="2" placeholder="
|
|
232
|
+
<el-input v-model="form.remark" type="textarea" :rows="2" placeholder="" />
|
|
217
233
|
</el-form-item>
|
|
218
234
|
</el-col>
|
|
235
|
+
<el-col :span="8" class="form-col--spacer">
|
|
236
|
+
<div class="form-col-placeholder" aria-hidden="true" />
|
|
237
|
+
</el-col>
|
|
219
238
|
<el-col :span="8">
|
|
220
|
-
<el-form-item label="
|
|
221
|
-
<el-input v-model="form.
|
|
239
|
+
<el-form-item label="备注(拒绝原因)" prop="rejectRemark">
|
|
240
|
+
<el-input v-model="form.rejectRemark" clearable />
|
|
222
241
|
</el-form-item>
|
|
223
242
|
</el-col>
|
|
224
243
|
</el-row>
|
|
225
244
|
|
|
226
|
-
|
|
227
|
-
<el-row :gutter="24">
|
|
245
|
+
<el-row :gutter="20">
|
|
228
246
|
<el-col :span="8">
|
|
229
|
-
<el-form-item label="使用状态" prop="
|
|
230
|
-
<el-select v-model="form.
|
|
231
|
-
<el-option label="未使用" value="
|
|
232
|
-
<el-option label="已使用" value="
|
|
247
|
+
<el-form-item label="使用状态" prop="isUsedFlg">
|
|
248
|
+
<el-select v-model="form.isUsedFlg" placeholder="请选择" style="width: 100%">
|
|
249
|
+
<el-option label="未使用" value="0" />
|
|
250
|
+
<el-option label="已使用" value="1" />
|
|
233
251
|
</el-select>
|
|
234
252
|
</el-form-item>
|
|
235
253
|
</el-col>
|
|
236
254
|
<el-col :span="8">
|
|
237
|
-
<el-form-item label="
|
|
238
|
-
<el-
|
|
255
|
+
<el-form-item label="当前队列" prop="forecastStatus">
|
|
256
|
+
<el-select v-model="form.forecastStatus" placeholder="请选择" style="width: 100%">
|
|
257
|
+
<el-option
|
|
258
|
+
v-for="o in forecastStatusOptions"
|
|
259
|
+
:key="o.value"
|
|
260
|
+
:label="o.label"
|
|
261
|
+
:value="o.value"
|
|
262
|
+
/>
|
|
263
|
+
</el-select>
|
|
264
|
+
</el-form-item>
|
|
265
|
+
</el-col>
|
|
266
|
+
<el-col :span="8">
|
|
267
|
+
<el-form-item label="业务渠道" prop="businessChannel">
|
|
268
|
+
<el-input v-model="form.businessChannel" disabled />
|
|
269
|
+
</el-form-item>
|
|
270
|
+
</el-col>
|
|
271
|
+
</el-row>
|
|
272
|
+
|
|
273
|
+
<el-divider content-position="left">授权 / 复核及其他</el-divider>
|
|
274
|
+
|
|
275
|
+
<el-row :gutter="20">
|
|
276
|
+
<el-col :span="8">
|
|
277
|
+
<el-form-item label="授权人" prop="author">
|
|
278
|
+
<el-input v-model="form.author" clearable />
|
|
279
|
+
</el-form-item>
|
|
280
|
+
</el-col>
|
|
281
|
+
<el-col :span="8">
|
|
282
|
+
<el-form-item label="授权日期" prop="authorDate">
|
|
283
|
+
<el-input v-model="form.authorDate" placeholder="YYYY-MM-DD" clearable />
|
|
284
|
+
</el-form-item>
|
|
285
|
+
</el-col>
|
|
286
|
+
<el-col :span="8">
|
|
287
|
+
<el-form-item label="授权时间" prop="authorTime">
|
|
288
|
+
<el-input v-model="form.authorTime" placeholder="HHmmss" clearable />
|
|
289
|
+
</el-form-item>
|
|
290
|
+
</el-col>
|
|
291
|
+
</el-row>
|
|
292
|
+
|
|
293
|
+
<el-row :gutter="20">
|
|
294
|
+
<el-col :span="8">
|
|
295
|
+
<el-form-item label="复核人" prop="supervisor">
|
|
296
|
+
<el-input v-model="form.supervisor" clearable />
|
|
297
|
+
</el-form-item>
|
|
298
|
+
</el-col>
|
|
299
|
+
<el-col :span="8">
|
|
300
|
+
<el-form-item label="复核日期" prop="checkDate">
|
|
301
|
+
<el-input v-model="form.checkDate" placeholder="YYYY-MM-DD" clearable />
|
|
302
|
+
</el-form-item>
|
|
303
|
+
</el-col>
|
|
304
|
+
<el-col :span="8">
|
|
305
|
+
<el-form-item label="复核时间" prop="checkTime">
|
|
306
|
+
<el-input v-model="form.checkTime" placeholder="HHmmss" clearable />
|
|
307
|
+
</el-form-item>
|
|
308
|
+
</el-col>
|
|
309
|
+
</el-row>
|
|
310
|
+
|
|
311
|
+
<el-row :gutter="20">
|
|
312
|
+
<el-col :span="8">
|
|
313
|
+
<el-form-item label="大额授权码" prop="posForecastNo">
|
|
314
|
+
<el-input v-model="form.posForecastNo" clearable />
|
|
315
|
+
</el-form-item>
|
|
316
|
+
</el-col>
|
|
317
|
+
<el-col :span="8">
|
|
318
|
+
<el-form-item label="中间行 SWIFT" prop="interBk">
|
|
319
|
+
<el-input v-model="form.interBk" clearable />
|
|
239
320
|
</el-form-item>
|
|
240
321
|
</el-col>
|
|
241
322
|
<el-col :span="8">
|
|
242
|
-
<el-form-item label="
|
|
243
|
-
<el-input v-model="form.
|
|
323
|
+
<el-form-item label="收款人名称" prop="pyeName">
|
|
324
|
+
<el-input v-model="form.pyeName" clearable />
|
|
244
325
|
</el-form-item>
|
|
245
326
|
</el-col>
|
|
246
327
|
</el-row>
|
|
328
|
+
|
|
329
|
+
<el-row :gutter="20">
|
|
330
|
+
<el-col :span="8">
|
|
331
|
+
<el-form-item label="实际付款金额" prop="usedAmt">
|
|
332
|
+
<el-input v-model="form.usedAmt" clearable />
|
|
333
|
+
</el-form-item>
|
|
334
|
+
</el-col>
|
|
335
|
+
<el-col :span="8">
|
|
336
|
+
<el-form-item label="可操作标志" prop="isOperateFlag">
|
|
337
|
+
<el-select v-model="form.isOperateFlag" placeholder="请选择" style="width: 100%">
|
|
338
|
+
<el-option label="不可操作" value="0" />
|
|
339
|
+
<el-option label="可以操作" value="1" />
|
|
340
|
+
</el-select>
|
|
341
|
+
</el-form-item>
|
|
342
|
+
</el-col>
|
|
343
|
+
<el-col :span="8" class="form-col--spacer">
|
|
344
|
+
<div class="form-col-placeholder" aria-hidden="true" />
|
|
345
|
+
</el-col>
|
|
346
|
+
</el-row>
|
|
247
347
|
</el-form>
|
|
248
348
|
|
|
249
349
|
<div class="footer">
|
|
250
|
-
<el-button type="danger" @click="onFlowLog">操作流水</el-button>
|
|
350
|
+
<el-button type="danger" plain @click="onFlowLog">操作流水</el-button>
|
|
251
351
|
<div class="footer-right">
|
|
252
|
-
<el-button type="danger" @click="
|
|
253
|
-
<el-button type="danger" @click="
|
|
254
|
-
<el-button type="danger" @click="
|
|
352
|
+
<el-button type="danger" @click="onPass">通过</el-button>
|
|
353
|
+
<el-button type="danger" plain @click="onReject">驳回</el-button>
|
|
354
|
+
<el-button type="danger" plain @click="onBack">返回</el-button>
|
|
255
355
|
</div>
|
|
256
356
|
</div>
|
|
257
357
|
</section>
|
|
258
358
|
</template>
|
|
259
359
|
|
|
260
360
|
<script setup lang="ts">
|
|
261
|
-
import { reactive, ref } from 'vue'
|
|
361
|
+
import { computed, reactive, ref } from 'vue'
|
|
262
362
|
import { useRouter } from 'vue-router'
|
|
263
363
|
import { ElMessage } from 'element-plus'
|
|
264
364
|
import type { FormInstance, FormRules } from 'element-plus'
|
|
@@ -266,135 +366,232 @@ import type { FormInstance, FormRules } from 'element-plus'
|
|
|
266
366
|
const router = useRouter()
|
|
267
367
|
const formRef = ref<FormInstance>()
|
|
268
368
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
369
|
+
/** 与接口字典一致的表单模型(均为 string,便于直接提交 JSON) */
|
|
370
|
+
interface PositionForecastForm {
|
|
371
|
+
id: string
|
|
372
|
+
author: string
|
|
373
|
+
authorDate: string
|
|
374
|
+
authorTime: string
|
|
375
|
+
bigForDate: string
|
|
376
|
+
bigForTime: string
|
|
377
|
+
checkDate: string
|
|
378
|
+
checkTime: string
|
|
379
|
+
clientType: string
|
|
276
380
|
currency: string
|
|
277
|
-
|
|
278
|
-
valueDate: string
|
|
279
|
-
accountName: string
|
|
280
|
-
planDate: string
|
|
281
|
-
prepareDate: string
|
|
282
|
-
createNo: string
|
|
283
|
-
isNegotiate: string
|
|
284
|
-
origBizNo: string
|
|
285
|
-
linkedBank: string
|
|
286
|
-
receivingBank: string
|
|
287
|
-
receivingBankCode: string
|
|
288
|
-
receivingBankName: string
|
|
289
|
-
emailProduct: string
|
|
290
|
-
multiCurrencyProduct: string
|
|
291
|
-
ftzFlag: boolean
|
|
292
|
-
reporter: string
|
|
293
|
-
phone: string
|
|
294
|
-
department: string
|
|
381
|
+
custName: string
|
|
295
382
|
remark: string
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
383
|
+
forecastAmt: string
|
|
384
|
+
forecastStatus: string
|
|
385
|
+
forecastType: string
|
|
386
|
+
interBk: string
|
|
387
|
+
isOperateFlag: string
|
|
388
|
+
isUsedFlg: string
|
|
389
|
+
linkMan: string
|
|
390
|
+
linkWay: string
|
|
391
|
+
mailFlag: string
|
|
392
|
+
mulCurFlag: string
|
|
393
|
+
nostro: string
|
|
394
|
+
orgId: string
|
|
395
|
+
oriInnerRefNo: string
|
|
396
|
+
planDate: string
|
|
397
|
+
posForecastNo: string
|
|
398
|
+
priIdCardType: string
|
|
399
|
+
pubOrgCode: string
|
|
400
|
+
pyeAcctBicName: string
|
|
401
|
+
pyeAcctBicSCode: string
|
|
402
|
+
pyeName: string
|
|
403
|
+
rtnFlag: string
|
|
404
|
+
supervisor: string
|
|
405
|
+
swiftCode: string
|
|
406
|
+
usedAmt: string
|
|
407
|
+
valueDate: string
|
|
408
|
+
/** 界面专用:驳回说明(若后端与 remark 共用,可在提交时合并) */
|
|
409
|
+
rejectRemark: string
|
|
410
|
+
/** 界面专用:自贸区,字典未给码表时 0/1 */
|
|
411
|
+
ftzFlag: string
|
|
412
|
+
businessChannel: string
|
|
300
413
|
}
|
|
301
414
|
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
415
|
+
const priIdCardTypeOptions = [
|
|
416
|
+
{ value: '0', label: '无证件' },
|
|
417
|
+
{ value: '1', label: '居民身份证' },
|
|
418
|
+
{ value: '2', label: '户口簿' },
|
|
419
|
+
{ value: '3', label: '护照/永久居留证' },
|
|
420
|
+
{ value: '4', label: '军人证' },
|
|
421
|
+
{ value: '5', label: '港澳台通行证' },
|
|
422
|
+
{ value: '6', label: '武警身份证' },
|
|
423
|
+
{ value: '7', label: '边民出入境通行证' }
|
|
424
|
+
]
|
|
425
|
+
|
|
426
|
+
const forecastTypeOptions = [
|
|
427
|
+
{ value: '10', label: '跨境人民币直参(客户)' },
|
|
428
|
+
{ value: '11', label: '跨境人民币直参(同业)' }
|
|
429
|
+
]
|
|
430
|
+
|
|
431
|
+
const forecastStatusOptions = [
|
|
432
|
+
{ value: '00', label: '已授权' },
|
|
433
|
+
{ value: '01', label: '待修改' },
|
|
434
|
+
{ value: '02', label: '待授权' },
|
|
435
|
+
{ value: '05', label: '已核销' },
|
|
436
|
+
{ value: '06', label: '待复核' },
|
|
437
|
+
{ value: '07', label: '总行授权' },
|
|
438
|
+
{ value: '98', label: '已失效' },
|
|
439
|
+
{ value: '99', label: '已删除' }
|
|
440
|
+
]
|
|
441
|
+
|
|
442
|
+
const clientTypeLabels: Record<string, string> = {
|
|
443
|
+
'01': '对公',
|
|
444
|
+
'02': '对私居民',
|
|
445
|
+
'03': '对私非居民'
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const form = reactive<PositionForecastForm>({
|
|
449
|
+
id: '',
|
|
450
|
+
author: '',
|
|
451
|
+
authorDate: '',
|
|
452
|
+
authorTime: '',
|
|
453
|
+
bigForDate: '2026-03-23',
|
|
454
|
+
bigForTime: '100053',
|
|
455
|
+
checkDate: '',
|
|
456
|
+
checkTime: '',
|
|
457
|
+
clientType: '01',
|
|
309
458
|
currency: 'CNY',
|
|
310
|
-
|
|
311
|
-
valueDate: '',
|
|
312
|
-
accountName: '',
|
|
313
|
-
planDate: '2026-03-23',
|
|
314
|
-
prepareDate: '2026-03-23',
|
|
315
|
-
createNo: '183423',
|
|
316
|
-
isNegotiate: '否',
|
|
317
|
-
origBizNo: '',
|
|
318
|
-
linkedBank: 'CIPSCNSHXXX',
|
|
319
|
-
receivingBank: '',
|
|
320
|
-
receivingBankCode: 'BKCHCNBJXXX',
|
|
321
|
-
receivingBankName: '中国银行国际金融有限公司',
|
|
322
|
-
emailProduct: '',
|
|
323
|
-
multiCurrencyProduct: '',
|
|
324
|
-
ftzFlag: false,
|
|
325
|
-
reporter: '0601bx',
|
|
326
|
-
phone: '13051636/66',
|
|
327
|
-
department: 'HGS1:利率及外汇业务处',
|
|
459
|
+
custName: '北京广联顺和科技有限公司SFD(脱敏)',
|
|
328
460
|
remark: '',
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
461
|
+
forecastAmt: '200,000,000.00',
|
|
462
|
+
forecastStatus: '07',
|
|
463
|
+
forecastType: '10',
|
|
464
|
+
interBk: '',
|
|
465
|
+
isOperateFlag: '1',
|
|
466
|
+
isUsedFlg: '0',
|
|
467
|
+
linkMan: '0001tx',
|
|
468
|
+
linkWay: '15631312',
|
|
469
|
+
mailFlag: '',
|
|
470
|
+
mulCurFlag: '',
|
|
471
|
+
nostro: 'CIPSCNSHXXX',
|
|
472
|
+
orgId: '00301',
|
|
473
|
+
oriInnerRefNo: '',
|
|
474
|
+
planDate: '2026-03-23',
|
|
475
|
+
posForecastNo: '',
|
|
476
|
+
priIdCardType: '',
|
|
477
|
+
pubOrgCode: '20489952-1',
|
|
478
|
+
pyeAcctBicName: '中国银行股份有限公司',
|
|
479
|
+
pyeAcctBicSCode: 'BKCHCNBJXXX',
|
|
480
|
+
pyeName: '',
|
|
481
|
+
rtnFlag: '01',
|
|
482
|
+
supervisor: '',
|
|
483
|
+
swiftCode: '',
|
|
484
|
+
usedAmt: '',
|
|
485
|
+
valueDate: '',
|
|
486
|
+
rejectRemark: '',
|
|
487
|
+
ftzFlag: '0',
|
|
488
|
+
businessChannel: '柜面系统'
|
|
333
489
|
})
|
|
334
490
|
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
currency: [{ required: true, message: '请选择币种', trigger: 'change' }],
|
|
340
|
-
planDate: [{ required: true, message: '请选择计划日期', trigger: 'change' }],
|
|
341
|
-
reporter: [{ required: true, message: '请输入报备人', trigger: 'blur' }],
|
|
342
|
-
phone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }]
|
|
491
|
+
const clientTypeLabel = computed(() => clientTypeLabels[form.clientType] ?? form.clientType)
|
|
492
|
+
|
|
493
|
+
const rules: FormRules<PositionForecastForm> = {
|
|
494
|
+
valueDate: [{ required: true, message: '起息日不能为空', trigger: 'change' }]
|
|
343
495
|
}
|
|
344
496
|
|
|
345
497
|
function onFlowLog() {
|
|
346
|
-
ElMessage.info('
|
|
498
|
+
ElMessage.info('操作流水(可对接流水查询)')
|
|
347
499
|
}
|
|
348
500
|
|
|
349
|
-
function
|
|
501
|
+
function onPass() {
|
|
350
502
|
formRef.value?.validate((valid) => {
|
|
351
503
|
if (!valid) return
|
|
352
|
-
ElMessage.success('
|
|
504
|
+
ElMessage.success('通过')
|
|
353
505
|
})
|
|
354
506
|
}
|
|
355
507
|
|
|
356
|
-
function
|
|
357
|
-
ElMessage.
|
|
508
|
+
function onReject() {
|
|
509
|
+
ElMessage.warning('驳回:可将「备注(拒绝原因)」写入接口后提交')
|
|
358
510
|
}
|
|
359
511
|
|
|
360
|
-
function
|
|
512
|
+
function onBack() {
|
|
361
513
|
router.back()
|
|
362
514
|
}
|
|
363
515
|
</script>
|
|
364
516
|
|
|
365
517
|
<style scoped>
|
|
366
518
|
.position-report-page {
|
|
367
|
-
padding: 20px;
|
|
519
|
+
padding: 20px 24px 32px;
|
|
520
|
+
background: #fff;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.page-header {
|
|
524
|
+
display: flex;
|
|
525
|
+
align-items: center;
|
|
526
|
+
justify-content: space-between;
|
|
527
|
+
margin-bottom: 8px;
|
|
528
|
+
padding-bottom: 12px;
|
|
529
|
+
border-bottom: 1px solid #e4e7ed;
|
|
368
530
|
}
|
|
369
531
|
|
|
370
532
|
.title {
|
|
533
|
+
margin: 0;
|
|
371
534
|
font-size: 18px;
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
535
|
+
font-weight: 600;
|
|
536
|
+
color: #303133;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.header-badge {
|
|
540
|
+
width: 12px;
|
|
541
|
+
height: 12px;
|
|
542
|
+
border-radius: 50%;
|
|
543
|
+
background: #c00;
|
|
544
|
+
flex-shrink: 0;
|
|
375
545
|
}
|
|
376
546
|
|
|
377
547
|
.report-form {
|
|
378
|
-
max-width:
|
|
548
|
+
max-width: 1440px;
|
|
549
|
+
margin-top: 8px;
|
|
379
550
|
}
|
|
380
551
|
|
|
381
552
|
.report-form :deep(.el-form-item__label) {
|
|
382
553
|
font-weight: normal;
|
|
383
|
-
|
|
554
|
+
color: #606266;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
.currency-amt {
|
|
558
|
+
display: flex;
|
|
559
|
+
gap: 8px;
|
|
560
|
+
width: 100%;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.currency-amt__cur {
|
|
564
|
+
width: 150px;
|
|
565
|
+
flex-shrink: 0;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.currency-amt__amt {
|
|
569
|
+
flex: 1;
|
|
570
|
+
min-width: 0;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/* 第三行第三列:空白占位,撑开与同行表单项相近高度 */
|
|
574
|
+
.form-col--spacer {
|
|
575
|
+
min-height: 51px;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
.form-col-placeholder {
|
|
579
|
+
width: 100%;
|
|
580
|
+
min-height: 32px;
|
|
384
581
|
}
|
|
385
582
|
|
|
386
583
|
.footer {
|
|
387
584
|
display: flex;
|
|
388
585
|
justify-content: space-between;
|
|
389
586
|
align-items: center;
|
|
390
|
-
margin-top:
|
|
587
|
+
margin-top: 28px;
|
|
391
588
|
padding-top: 16px;
|
|
392
|
-
border-top: 1px solid #
|
|
393
|
-
max-width:
|
|
589
|
+
border-top: 1px solid #e4e7ed;
|
|
590
|
+
max-width: 1440px;
|
|
394
591
|
}
|
|
395
592
|
|
|
396
593
|
.footer-right {
|
|
397
594
|
display: flex;
|
|
398
|
-
gap:
|
|
595
|
+
gap: 10px;
|
|
399
596
|
}
|
|
400
597
|
</style>
|
|
@@ -3,6 +3,7 @@ import CascaderPage from '../pages/CascaderPage.vue'
|
|
|
3
3
|
import ExportExcelPage from '../pages/ExportExcelPage.vue'
|
|
4
4
|
import ImportTablePage from '../pages/ImportTablePage.vue'
|
|
5
5
|
import PositionReportPage from '../pages/PositionReportPage.vue'
|
|
6
|
+
import DateRangePage from '../pages/DateRangePage.vue'
|
|
6
7
|
|
|
7
8
|
export const routes = [
|
|
8
9
|
{
|
|
@@ -50,7 +51,16 @@ export const routes = [
|
|
|
50
51
|
name: 'PositionReport',
|
|
51
52
|
component: PositionReportPage,
|
|
52
53
|
meta: {
|
|
53
|
-
title: '
|
|
54
|
+
title: '头寸报备信息',
|
|
55
|
+
showInMenu: true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
path: '/date-range',
|
|
60
|
+
name: 'DateRange',
|
|
61
|
+
component: DateRangePage,
|
|
62
|
+
meta: {
|
|
63
|
+
title: '日期区间',
|
|
54
64
|
showInMenu: true
|
|
55
65
|
}
|
|
56
66
|
}
|
package/package.json
CHANGED
package/test/fun.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function addIdText(list = []) {
|
|
2
|
+
const stack = [...list]
|
|
3
|
+
|
|
4
|
+
while (stack.length) {
|
|
5
|
+
const node = stack.pop()
|
|
6
|
+
|
|
7
|
+
node.idText = `${node.id}-${node.text}`
|
|
8
|
+
|
|
9
|
+
if (Array.isArray(node.children) && node.children.length) {
|
|
10
|
+
stack.push(...node.children)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return list
|
|
15
|
+
}
|