af-mobile-client-vue3 1.4.85 → 1.4.87
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
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import dayjs from 'dayjs/esm/index'
|
|
3
|
+
import {
|
|
4
|
+
DatePicker as VanDatePicker,
|
|
5
|
+
Field as VanField,
|
|
6
|
+
PickerGroup as VanPickerGroup,
|
|
7
|
+
Popup as VanPopup,
|
|
8
|
+
TimePicker as VanTimePicker,
|
|
9
|
+
} from 'vant'
|
|
10
|
+
import { computed, ref } from 'vue'
|
|
11
|
+
|
|
12
|
+
interface Props {
|
|
13
|
+
attr: any
|
|
14
|
+
form?: any
|
|
15
|
+
mode?: string
|
|
16
|
+
readonly?: boolean
|
|
17
|
+
placeholder?: string
|
|
18
|
+
labelData?: string
|
|
19
|
+
labelAlign?: string
|
|
20
|
+
inputAlign?: string
|
|
21
|
+
required?: boolean
|
|
22
|
+
showLabel?: boolean
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
26
|
+
mode: '查询',
|
|
27
|
+
readonly: false,
|
|
28
|
+
showLabel: true,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const emits = defineEmits(['update:modelValue', 'change'])
|
|
32
|
+
|
|
33
|
+
// 双向绑定
|
|
34
|
+
const modelData = defineModel<string | number | boolean | any[] | Record<string, any>>()
|
|
35
|
+
|
|
36
|
+
// 日期时间选择数据
|
|
37
|
+
const dateTimePickerValue = ref<any>({})
|
|
38
|
+
const showDatePicker = ref(false)
|
|
39
|
+
|
|
40
|
+
// 配置的表单值格式(仅针对 datePicker 生效)
|
|
41
|
+
// 作用:统一控制日期值的格式化输入/输出与选择器展示粒度
|
|
42
|
+
// 可选:'YYYY' | 'YYYY-MM' | 'YYYY-MM-DD' | 'YYYY-MM-DD HH' | 'YYYY-MM-DD HH:mm' | 'YYYY-MM-DD HH:mm:ss'
|
|
43
|
+
const formValueFormat = computed(() => {
|
|
44
|
+
// 默认全格式
|
|
45
|
+
return (props.attr && (props.attr as any).formValueFormat) || 'YYYY-MM-DD HH:mm:ss'
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// 根据 formValueFormat 动态计算日期列类型(决定 VanDatePicker 展示年/月/日)
|
|
49
|
+
// 例如:YYYY 只显示年;YYYY-MM 显示年、月;YYYY-MM-DD 显示年、月、日
|
|
50
|
+
const dateColumnsType = computed(() => {
|
|
51
|
+
const format = formValueFormat.value
|
|
52
|
+
const columns: string[] = ['year']
|
|
53
|
+
if (format.includes('MM'))
|
|
54
|
+
columns.push('month')
|
|
55
|
+
if (format.includes('DD'))
|
|
56
|
+
columns.push('day')
|
|
57
|
+
return columns as any
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// 是否包含时间(决定是否展示时间页签与 VanTimePicker)
|
|
61
|
+
const hasTime = computed(() => formValueFormat.value.includes('HH'))
|
|
62
|
+
|
|
63
|
+
// 根据 formValueFormat 动态计算时间列类型(决定时/分/秒的展示)
|
|
64
|
+
// 例如:包含 HH 显示小时;包含 mm 显示分钟;包含 ss 显示秒
|
|
65
|
+
const timeColumnsType = computed(() => {
|
|
66
|
+
const format = formValueFormat.value
|
|
67
|
+
const columns: string[] = []
|
|
68
|
+
if (format.includes('HH'))
|
|
69
|
+
columns.push('hour')
|
|
70
|
+
if (format.includes('mm'))
|
|
71
|
+
columns.push('minute')
|
|
72
|
+
if (format.includes('ss'))
|
|
73
|
+
columns.push('second')
|
|
74
|
+
return columns as any
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
// 根据 attr.dateRangeOption 计算 VanDatePicker/VanCalendar 的可选范围
|
|
78
|
+
// attr.dateRangeOption 结构示例:
|
|
79
|
+
// { type: 'beforeToday' | 'afterToday' | 'custom', beforeDays?: number, afterDays?: number }
|
|
80
|
+
// 语义说明:
|
|
81
|
+
// - beforeToday: 只能选择今天之前(不包含今天),无下限
|
|
82
|
+
// - afterToday: 只能选择今天之后(不包含今天),无上限
|
|
83
|
+
// - custom: 使用 beforeDays/afterDays 相对于今天进行偏移计算
|
|
84
|
+
const datePickerMinDate = computed(() => {
|
|
85
|
+
const opt = (props.attr as any).dateRangeOption
|
|
86
|
+
if (!opt || !opt.type || props.mode === '查询')
|
|
87
|
+
return undefined
|
|
88
|
+
// beforeToday 不限制最小日期
|
|
89
|
+
if (opt.type === 'beforeToday') {
|
|
90
|
+
return undefined
|
|
91
|
+
}
|
|
92
|
+
// afterToday 从今天开始(包含今天)
|
|
93
|
+
if (opt.type === 'afterToday') {
|
|
94
|
+
return dayjs().startOf('day').toDate()
|
|
95
|
+
}
|
|
96
|
+
// custom 使用 beforeDays 进行计算(支持负值),仅 custom 类型生效
|
|
97
|
+
if (opt.type === 'custom') {
|
|
98
|
+
return typeof opt.beforeDays === 'number' ? dayjs().add(opt.beforeDays, 'day').startOf('day').toDate() : undefined
|
|
99
|
+
}
|
|
100
|
+
return undefined
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
const datePickerMaxDate = computed(() => {
|
|
104
|
+
const opt = (props.attr as any).dateRangeOption
|
|
105
|
+
if (!opt || !opt.type || props.mode === '查询')
|
|
106
|
+
return undefined
|
|
107
|
+
// beforeToday 最多到今天结束(包含今天)
|
|
108
|
+
if (opt.type === 'beforeToday') {
|
|
109
|
+
return dayjs().endOf('day').toDate()
|
|
110
|
+
}
|
|
111
|
+
// afterToday 默认不限制上限;只有 custom 类型会依据 afterDays 计算上限
|
|
112
|
+
if (opt.type === 'afterToday') {
|
|
113
|
+
return undefined
|
|
114
|
+
}
|
|
115
|
+
// custom 使用 afterDays 进行计算(支持负值),仅 custom 类型生效
|
|
116
|
+
if (opt.type === 'custom') {
|
|
117
|
+
return typeof opt.afterDays === 'number' ? dayjs().add(opt.afterDays, 'day').endOf('day').toDate() : undefined
|
|
118
|
+
}
|
|
119
|
+
return undefined
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
// 根据 attr.dateRangeOption 限制时间选择器的列选项
|
|
123
|
+
// 如果 type 为 'afterToday',则根据选择的日期决定小时起始值
|
|
124
|
+
const timePickerColumns = computed(() => {
|
|
125
|
+
const opt = (props.attr as any).dateRangeOption
|
|
126
|
+
if (!opt || opt.type !== 'afterToday' || props.mode === '查询')
|
|
127
|
+
return undefined
|
|
128
|
+
|
|
129
|
+
const columns: any[] = []
|
|
130
|
+
const pad = (n: number) => n.toString().padStart(2, '0')
|
|
131
|
+
const now = dayjs()
|
|
132
|
+
|
|
133
|
+
// 获取用户选择的日期
|
|
134
|
+
const selectedDate = dateTimePickerValue.value.date
|
|
135
|
+
let startHour = 0 // 默认从00:00开始
|
|
136
|
+
|
|
137
|
+
// 如果选择的日期是今天,才限制从当前小时+1开始
|
|
138
|
+
if (selectedDate && selectedDate.length >= 3) {
|
|
139
|
+
const selectedYear = parseInt(selectedDate[0])
|
|
140
|
+
const selectedMonth = parseInt(selectedDate[1])
|
|
141
|
+
const selectedDay = parseInt(selectedDate[2] || '1')
|
|
142
|
+
|
|
143
|
+
const selectedDateTime = dayjs().year(selectedYear).month(selectedMonth - 1).date(selectedDay).startOf('day')
|
|
144
|
+
const today = now.startOf('day')
|
|
145
|
+
|
|
146
|
+
// 如果选择的是今天,才从当前小时+1开始
|
|
147
|
+
if (selectedDateTime.isSame(today, 'day')) {
|
|
148
|
+
startHour = now.hour() + 1
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
// 如果没有选择日期,默认为今天,限制时间
|
|
152
|
+
startHour = now.hour() + 1
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 小时列从计算出的起始小时开始到23
|
|
156
|
+
const hourOptions = []
|
|
157
|
+
for (let h = startHour; h < 24; h++) {
|
|
158
|
+
hourOptions.push({ text: pad(h), value: pad(h) })
|
|
159
|
+
}
|
|
160
|
+
// 如果没有可选小时(例如当前为23),允许选择23
|
|
161
|
+
if (hourOptions.length === 0) {
|
|
162
|
+
hourOptions.push({ text: pad(23), value: pad(23) })
|
|
163
|
+
}
|
|
164
|
+
columns.push(hourOptions)
|
|
165
|
+
|
|
166
|
+
// 分钟列(如果需要)
|
|
167
|
+
if (timeColumnsType.value.includes('minute')) {
|
|
168
|
+
const minutes = Array.from({ length: 60 }, (_, i) => ({ text: i.toString().padStart(2, '0'), value: i.toString().padStart(2, '0') }))
|
|
169
|
+
columns.push(minutes)
|
|
170
|
+
}
|
|
171
|
+
// 秒列(如果需要)
|
|
172
|
+
if (timeColumnsType.value.includes('second')) {
|
|
173
|
+
const seconds = Array.from({ length: 60 }, (_, i) => ({ text: i.toString().padStart(2, '0'), value: i.toString().padStart(2, '0') }))
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return columns
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
// 展示日期时间选择器:根据 formValueFormat 初始化 VanDatePicker/VanTimePicker 的当前值
|
|
180
|
+
// 规则:
|
|
181
|
+
// - 若已有字符串值,按 formValueFormat 解析并拆分为日期/时间数组
|
|
182
|
+
// - 若无值,按当前时间生成匹配格式的默认数组
|
|
183
|
+
function showDataTimePicker() {
|
|
184
|
+
if (modelData.value && typeof modelData.value === 'string') {
|
|
185
|
+
const base = dayjs(modelData.value as string, formValueFormat.value)
|
|
186
|
+
const dateArr: string[] = []
|
|
187
|
+
dateArr.push(base.format('YYYY'))
|
|
188
|
+
if (dateColumnsType.value.includes('month'))
|
|
189
|
+
dateArr.push(base.format('MM'))
|
|
190
|
+
if (dateColumnsType.value.includes('day'))
|
|
191
|
+
dateArr.push(base.format('DD'))
|
|
192
|
+
const timeArr: string[] = []
|
|
193
|
+
if (hasTime.value) {
|
|
194
|
+
if (timeColumnsType.value.includes('hour'))
|
|
195
|
+
timeArr.push(base.format('HH'))
|
|
196
|
+
if (timeColumnsType.value.includes('minute'))
|
|
197
|
+
timeArr.push(base.format('mm'))
|
|
198
|
+
if (timeColumnsType.value.includes('second'))
|
|
199
|
+
timeArr.push(base.format('ss'))
|
|
200
|
+
}
|
|
201
|
+
dateTimePickerValue.value = {
|
|
202
|
+
date: dateArr,
|
|
203
|
+
time: timeArr.length ? timeArr : ['00', '00', '00'].slice(0, timeColumnsType.value.length),
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
const now = dayjs()
|
|
208
|
+
const dateArr: string[] = []
|
|
209
|
+
dateArr.push(now.format('YYYY'))
|
|
210
|
+
if (dateColumnsType.value.includes('month'))
|
|
211
|
+
dateArr.push(now.format('MM'))
|
|
212
|
+
if (dateColumnsType.value.includes('day'))
|
|
213
|
+
dateArr.push(now.format('DD'))
|
|
214
|
+
const timeArr: string[] = []
|
|
215
|
+
if (hasTime.value) {
|
|
216
|
+
if (timeColumnsType.value.includes('hour'))
|
|
217
|
+
timeArr.push(now.format('HH'))
|
|
218
|
+
if (timeColumnsType.value.includes('minute'))
|
|
219
|
+
timeArr.push(now.format('mm'))
|
|
220
|
+
if (timeColumnsType.value.includes('second'))
|
|
221
|
+
timeArr.push(now.format('ss'))
|
|
222
|
+
}
|
|
223
|
+
dateTimePickerValue.value = {
|
|
224
|
+
date: dateArr,
|
|
225
|
+
time: timeArr.length ? timeArr : ['00', '00', '00'].slice(0, timeColumnsType.value.length),
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
showDatePicker.value = true
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// 日期时间选择确认:将选择的年月日(+时分秒)拼装后,最终使用 formValueFormat 输出到 v-model
|
|
232
|
+
function onDateTimePickerConfirm() {
|
|
233
|
+
showDatePicker.value = false
|
|
234
|
+
const dateParts = dateTimePickerValue.value.date as string[]
|
|
235
|
+
const timeParts = (dateTimePickerValue.value.time as string[]) || []
|
|
236
|
+
const year = dateParts[0]
|
|
237
|
+
const month = dateParts[1] || '01'
|
|
238
|
+
const day = dateParts[2] || '01'
|
|
239
|
+
const hour = hasTime.value && timeParts[0] ? timeParts[0] : '00'
|
|
240
|
+
const minute = hasTime.value && timeParts[1] ? timeParts[1] : '00'
|
|
241
|
+
const second = hasTime.value && timeParts[2] ? timeParts[2] : '00'
|
|
242
|
+
const full = `${year}-${month}-${day} ${hour}:${minute}:${second}`
|
|
243
|
+
modelData.value = dayjs(full, 'YYYY-MM-DD HH:mm:ss').format(formValueFormat.value)
|
|
244
|
+
emits('change')
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function onPickerCancel() {
|
|
248
|
+
showDatePicker.value = false
|
|
249
|
+
}
|
|
250
|
+
</script>
|
|
251
|
+
|
|
252
|
+
<template>
|
|
253
|
+
<div>
|
|
254
|
+
<!-- 日期选择-非查询 -->
|
|
255
|
+
<VanField
|
|
256
|
+
v-if="mode !== '查询'"
|
|
257
|
+
v-model="(modelData as string | number)"
|
|
258
|
+
name="datePicker"
|
|
259
|
+
:label="labelData"
|
|
260
|
+
v-bind="{
|
|
261
|
+
'label-align': labelAlign,
|
|
262
|
+
'input-align': inputAlign,
|
|
263
|
+
}"
|
|
264
|
+
readonly
|
|
265
|
+
:is-link="true"
|
|
266
|
+
:placeholder="placeholder"
|
|
267
|
+
:rules="[{ required, message: `请选择${attr.name}` }]"
|
|
268
|
+
:required="required"
|
|
269
|
+
@click="readonly ? null : showDataTimePicker()"
|
|
270
|
+
/>
|
|
271
|
+
|
|
272
|
+
<!-- 日期选择-查询 -->
|
|
273
|
+
<VanField
|
|
274
|
+
v-if="mode === '查询'"
|
|
275
|
+
v-model="(modelData as string | number)"
|
|
276
|
+
name="datePicker"
|
|
277
|
+
:label="labelData"
|
|
278
|
+
v-bind="{
|
|
279
|
+
'label-align': labelAlign,
|
|
280
|
+
'input-align': inputAlign,
|
|
281
|
+
}"
|
|
282
|
+
readonly
|
|
283
|
+
:is-link="true"
|
|
284
|
+
:placeholder="placeholder"
|
|
285
|
+
:rules="[{ required, message: `请选择${attr.name}` }]"
|
|
286
|
+
@click="readonly ? null : showDataTimePicker()"
|
|
287
|
+
/>
|
|
288
|
+
|
|
289
|
+
<VanPopup
|
|
290
|
+
v-model:show="showDatePicker"
|
|
291
|
+
position="bottom"
|
|
292
|
+
teleport="body"
|
|
293
|
+
overlay-class="date-picker-overlay"
|
|
294
|
+
>
|
|
295
|
+
<VanPickerGroup
|
|
296
|
+
:title="attr.name"
|
|
297
|
+
:tabs="hasTime ? ['选择日期', '选择时间'] : ['选择日期']"
|
|
298
|
+
next-step-text="下一步"
|
|
299
|
+
:confirm-button-text="attr.confirmButtonText ? attr.confirmButtonText : '确认'"
|
|
300
|
+
:cancel-button-text="attr.cancelButtonText ? attr.cancelButtonText : '取消'"
|
|
301
|
+
@confirm="onDateTimePickerConfirm"
|
|
302
|
+
@cancel="onPickerCancel"
|
|
303
|
+
>
|
|
304
|
+
<VanDatePicker
|
|
305
|
+
v-model="dateTimePickerValue.date"
|
|
306
|
+
:columns-type="attr.dateColumnsType || dateColumnsType"
|
|
307
|
+
:min-date="datePickerMinDate"
|
|
308
|
+
:max-date="datePickerMaxDate"
|
|
309
|
+
/>
|
|
310
|
+
<VanTimePicker
|
|
311
|
+
v-if="hasTime"
|
|
312
|
+
v-model="dateTimePickerValue.time"
|
|
313
|
+
:columns-type="attr.timeColumnsType || timeColumnsType"
|
|
314
|
+
v-bind="timePickerColumns ? { columns: timePickerColumns } : {}"
|
|
315
|
+
:min-time="attr.minTime ? attr.minTime : '00:00:00'"
|
|
316
|
+
:max-time="attr.maxTime ? attr.maxTime : '23:59:59'"
|
|
317
|
+
/>
|
|
318
|
+
</VanPickerGroup>
|
|
319
|
+
</VanPopup>
|
|
320
|
+
</div>
|
|
321
|
+
</template>
|
|
322
|
+
|
|
323
|
+
<style scoped>
|
|
324
|
+
.date-picker-overlay {
|
|
325
|
+
background-color: rgba(0, 0, 0, 0.2); /* 设置为半透明的黑色 */
|
|
326
|
+
}
|
|
327
|
+
</style>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { FieldType } from 'vant'
|
|
3
3
|
import type { Numeric } from 'vant/es/utils'
|
|
4
4
|
import ImageUploader from '@af-mobile-client-vue3/components/core/ImageUploader/index.vue'
|
|
5
|
+
import XDatePicker from '@af-mobile-client-vue3/components/core/XDatePicker/index.vue'
|
|
5
6
|
import XGridDropOption from '@af-mobile-client-vue3/components/core/XGridDropOption/index.vue'
|
|
6
7
|
import XMultiSelect from '@af-mobile-client-vue3/components/core/XMultiSelect/index.vue'
|
|
7
8
|
import XSelect from '@af-mobile-client-vue3/components/core/XSelect/index.vue'
|
|
@@ -26,10 +27,8 @@ import {
|
|
|
26
27
|
Cascader as VanCascader,
|
|
27
28
|
Checkbox as VanCheckbox,
|
|
28
29
|
CheckboxGroup as vanCheckboxGroup,
|
|
29
|
-
DatePicker as VanDatePicker,
|
|
30
30
|
Field as VanField,
|
|
31
31
|
Picker as VanPicker,
|
|
32
|
-
PickerGroup as VanPickerGroup,
|
|
33
32
|
Popup as VanPopup,
|
|
34
33
|
Radio as VanRadio,
|
|
35
34
|
RadioGroup as VanRadioGroup,
|
|
@@ -136,131 +135,12 @@ let debouncedUpdateOptions: (() => void) | null = null
|
|
|
136
135
|
const selectValueTypeHandler = createSelectValueTypeHandler()
|
|
137
136
|
|
|
138
137
|
const { attr, form, mode, serviceName, getDataParams, columnsField } = props
|
|
139
|
-
// 配置的表单值格式(仅针对 datePicker 生效)
|
|
140
|
-
// 作用:统一控制日期值的格式化输入/输出与选择器展示粒度
|
|
141
|
-
// 可选:'YYYY' | 'YYYY-MM' | 'YYYY-MM-DD' | 'YYYY-MM-DD HH' | 'YYYY-MM-DD HH:mm' | 'YYYY-MM-DD HH:mm:ss'
|
|
142
|
-
const formValueFormat = computed(() => {
|
|
143
|
-
// 默认全格式
|
|
144
|
-
return (attr && (attr as any).formValueFormat) || 'YYYY-MM-DD HH:mm:ss'
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
// 根据 formValueFormat 动态计算日期列类型(决定 VanDatePicker 展示年/月/日)
|
|
148
|
-
// 例如:YYYY 只显示年;YYYY-MM 显示年、月;YYYY-MM-DD 显示年、月、日
|
|
149
|
-
const dateColumnsType = computed(() => {
|
|
150
|
-
const format = formValueFormat.value
|
|
151
|
-
const columns: string[] = ['year']
|
|
152
|
-
if (format.includes('MM'))
|
|
153
|
-
columns.push('month')
|
|
154
|
-
if (format.includes('DD'))
|
|
155
|
-
columns.push('day')
|
|
156
|
-
return columns as any
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
// 是否包含时间(决定是否展示时间页签与 VanTimePicker)
|
|
160
|
-
const hasTime = computed(() => formValueFormat.value.includes('HH'))
|
|
161
|
-
|
|
162
|
-
// 根据 formValueFormat 动态计算时间列类型(决定时/分/秒的展示)
|
|
163
|
-
// 例如:包含 HH 显示小时;包含 mm 显示分钟;包含 ss 显示秒
|
|
164
|
-
const timeColumnsType = computed(() => {
|
|
165
|
-
const format = formValueFormat.value
|
|
166
|
-
const columns: string[] = []
|
|
167
|
-
if (format.includes('HH'))
|
|
168
|
-
columns.push('hour')
|
|
169
|
-
if (format.includes('mm'))
|
|
170
|
-
columns.push('minute')
|
|
171
|
-
if (format.includes('ss'))
|
|
172
|
-
columns.push('second')
|
|
173
|
-
return columns as any
|
|
174
|
-
})
|
|
175
|
-
// 根据 attr.dateRangeOption 计算 VanDatePicker/VanCalendar 的可选范围
|
|
176
|
-
// attr.dateRangeOption 结构示例:
|
|
177
|
-
// { type: 'beforeToday' | 'afterToday' | 'custom', beforeDays?: number, afterDays?: number }
|
|
178
|
-
// 语义说明:
|
|
179
|
-
// - beforeToday: 只能选择今天之前(不包含今天),无下限
|
|
180
|
-
// - afterToday: 只能选择今天之后(不包含今天),无上限
|
|
181
|
-
// - custom: 使用 beforeDays/afterDays 相对于今天进行偏移计算
|
|
182
|
-
const datePickerMinDate = computed(() => {
|
|
183
|
-
const opt = (attr as any).dateRangeOption
|
|
184
|
-
if (!opt || !opt.type || mode === '查询')
|
|
185
|
-
return undefined
|
|
186
|
-
// beforeToday 不限制最小日期
|
|
187
|
-
if (opt.type === 'beforeToday') {
|
|
188
|
-
return undefined
|
|
189
|
-
}
|
|
190
|
-
// afterToday 从今天开始(包含今天)
|
|
191
|
-
if (opt.type === 'afterToday') {
|
|
192
|
-
return dayjs().startOf('day').toDate()
|
|
193
|
-
}
|
|
194
|
-
// custom 使用 beforeDays 进行计算(支持负值),仅 custom 类型生效
|
|
195
|
-
if (opt.type === 'custom') {
|
|
196
|
-
return typeof opt.beforeDays === 'number' ? dayjs().add(opt.beforeDays, 'day').startOf('day').toDate() : undefined
|
|
197
|
-
}
|
|
198
|
-
return undefined
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
const datePickerMaxDate = computed(() => {
|
|
202
|
-
const opt = (attr as any).dateRangeOption
|
|
203
|
-
if (!opt || !opt.type || mode === '查询')
|
|
204
|
-
return undefined
|
|
205
|
-
// beforeToday 最多到今天结束(包含今天)
|
|
206
|
-
if (opt.type === 'beforeToday') {
|
|
207
|
-
return dayjs().endOf('day').toDate()
|
|
208
|
-
}
|
|
209
|
-
// afterToday 默认不限制上限;只有 custom 类型会依据 afterDays 计算上限
|
|
210
|
-
if (opt.type === 'afterToday') {
|
|
211
|
-
return undefined
|
|
212
|
-
}
|
|
213
|
-
// custom 使用 afterDays 进行计算(支持负值),仅 custom 类型生效
|
|
214
|
-
if (opt.type === 'custom') {
|
|
215
|
-
return typeof opt.afterDays === 'number' ? dayjs().add(opt.afterDays, 'day').endOf('day').toDate() : undefined
|
|
216
|
-
}
|
|
217
|
-
return undefined
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
// 根据 attr.dateRangeOption 限制时间选择器的列选项
|
|
221
|
-
// 如果 type 为 'afterToday',则小时列从当前小时+1开始
|
|
222
|
-
const timePickerColumns = computed(() => {
|
|
223
|
-
const opt = (attr as any).dateRangeOption
|
|
224
|
-
if (!opt || opt.type !== 'afterToday' || mode === '查询')
|
|
225
|
-
return undefined
|
|
226
|
-
|
|
227
|
-
const columns: any[] = []
|
|
228
|
-
const pad = (n: number) => n.toString().padStart(2, '0')
|
|
229
|
-
const now = dayjs()
|
|
230
|
-
const start = now.hour() + 1
|
|
231
|
-
|
|
232
|
-
// 小时列从当前小时+1开始到23
|
|
233
|
-
const hourOptions = []
|
|
234
|
-
for (let h = start; h < 24; h++) {
|
|
235
|
-
hourOptions.push({ text: pad(h), value: pad(h) })
|
|
236
|
-
}
|
|
237
|
-
// 如果没有可选小时(例如当前为23),允许选择23
|
|
238
|
-
if (hourOptions.length === 0) {
|
|
239
|
-
hourOptions.push({ text: pad(23), value: pad(23) })
|
|
240
|
-
}
|
|
241
|
-
columns.push(hourOptions)
|
|
242
|
-
|
|
243
|
-
// 分钟列(如果需要)
|
|
244
|
-
if (timeColumnsType.value.includes('minute')) {
|
|
245
|
-
const minutes = Array.from({ length: 60 }, (_, i) => ({ text: i.toString().padStart(2, '0'), value: i.toString().padStart(2, '0') }))
|
|
246
|
-
columns.push(minutes)
|
|
247
|
-
}
|
|
248
|
-
// 秒列(如果需要)
|
|
249
|
-
if (timeColumnsType.value.includes('second')) {
|
|
250
|
-
const seconds = Array.from({ length: 60 }, (_, i) => ({ text: i.toString().padStart(2, '0'), value: i.toString().padStart(2, '0') }))
|
|
251
|
-
columns.push(seconds)
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return columns
|
|
255
|
-
})
|
|
256
|
-
|
|
257
138
|
const calendarShow = ref(false)
|
|
258
139
|
const option = ref([])
|
|
259
140
|
const pickerValue = ref(undefined)
|
|
260
141
|
const timePickerValue = ref(undefined)
|
|
261
142
|
const area = ref<any>(undefined)
|
|
262
143
|
const showPicker = ref(false)
|
|
263
|
-
const showDatePicker = ref(false)
|
|
264
144
|
const showTimePicker = ref(false)
|
|
265
145
|
const showArea = ref(false)
|
|
266
146
|
const errorMessage = ref('')
|
|
@@ -328,14 +208,7 @@ function checkModel(val = props.modelValue) {
|
|
|
328
208
|
*/
|
|
329
209
|
function getDefaultValue() {
|
|
330
210
|
const val = props.modelValue
|
|
331
|
-
// 如果有有效值,直接返回(datePicker 初始值需按 formValueFormat 归一)
|
|
332
|
-
// 目的:外部通过 formData 传入的初始值在组件挂载即与配置格式一致
|
|
333
211
|
if (checkModel(val)) {
|
|
334
|
-
if (attr.type === 'datePicker' && typeof val === 'string') {
|
|
335
|
-
const parsed = dayjs(val)
|
|
336
|
-
if (parsed.isValid())
|
|
337
|
-
return parsed.format(formValueFormat.value)
|
|
338
|
-
}
|
|
339
212
|
return val
|
|
340
213
|
}
|
|
341
214
|
|
|
@@ -381,7 +254,6 @@ function getDefaultValue() {
|
|
|
381
254
|
return specialDefaults[attr.type]
|
|
382
255
|
}
|
|
383
256
|
|
|
384
|
-
// 日期时间类型:调用 getDateRange,并传入 formValueFormat
|
|
385
257
|
// 说明:让初始化/查询默认值同样遵循配置的格式显示
|
|
386
258
|
const dateTypes = ['rangePicker', 'yearPicker', 'monthPicker', 'yearRangePicker', 'monthRangePicker', 'datePicker', 'timePicker']
|
|
387
259
|
if (dateTypes.includes(attr.type)) {
|
|
@@ -392,7 +264,6 @@ function getDefaultValue() {
|
|
|
392
264
|
queryType: attr.queryType,
|
|
393
265
|
queryValueFormat: attr.queryValueFormat,
|
|
394
266
|
name: attr.name ?? '',
|
|
395
|
-
formValueFormat: formValueFormat.value,
|
|
396
267
|
}) ?? []
|
|
397
268
|
}
|
|
398
269
|
|
|
@@ -411,7 +282,6 @@ function getDateRange({
|
|
|
411
282
|
queryType,
|
|
412
283
|
queryValueFormat: defaultFormat,
|
|
413
284
|
name,
|
|
414
|
-
formValueFormat: formFormat,
|
|
415
285
|
}: {
|
|
416
286
|
type: string
|
|
417
287
|
formDefault: string
|
|
@@ -419,8 +289,6 @@ function getDateRange({
|
|
|
419
289
|
queryType?: string
|
|
420
290
|
queryValueFormat?: string
|
|
421
291
|
name: string
|
|
422
|
-
// 新增:用于优先覆盖 datePicker 的显示/存储格式
|
|
423
|
-
formValueFormat?: string
|
|
424
292
|
}): string | [string, string] | undefined {
|
|
425
293
|
const formatMap: Record<string, string> = {
|
|
426
294
|
yearPicker: 'YYYY',
|
|
@@ -431,8 +299,7 @@ function getDateRange({
|
|
|
431
299
|
rangePicker: 'YYYY-MM-DD HH:mm:ss',
|
|
432
300
|
}
|
|
433
301
|
if (mode) {
|
|
434
|
-
|
|
435
|
-
const preferFormat = type === 'datePicker' ? (formFormat || defaultFormat) : defaultFormat
|
|
302
|
+
const preferFormat = defaultFormat
|
|
436
303
|
const format = preferFormat || formatMap[type]
|
|
437
304
|
const val = mode === '查询' ? queryFormDefault : defaultValue
|
|
438
305
|
let start: string, end: string
|
|
@@ -892,65 +759,6 @@ function onPickerConfirm({ selectedOptions }) {
|
|
|
892
759
|
modelData.value = selectedOptions[0].text
|
|
893
760
|
}
|
|
894
761
|
|
|
895
|
-
// 日期时间选择数据
|
|
896
|
-
const dateTimePickerValue = ref<any>({})
|
|
897
|
-
// 展示日期时间选择器:根据 formValueFormat 初始化 VanDatePicker/VanTimePicker 的当前值
|
|
898
|
-
// 规则:
|
|
899
|
-
// - 若已有字符串值,按 formValueFormat 解析并拆分为日期/时间数组
|
|
900
|
-
// - 若无值,按当前时间生成匹配格式的默认数组
|
|
901
|
-
function showDataTimePicker() {
|
|
902
|
-
if (props.modelValue && typeof props.modelValue === 'string') {
|
|
903
|
-
const base = dayjs(props.modelValue as string, formValueFormat.value)
|
|
904
|
-
const dateArr: string[] = []
|
|
905
|
-
dateArr.push(base.format('YYYY'))
|
|
906
|
-
if (dateColumnsType.value.includes('month'))
|
|
907
|
-
dateArr.push(base.format('MM'))
|
|
908
|
-
if (dateColumnsType.value.includes('day'))
|
|
909
|
-
dateArr.push(base.format('DD'))
|
|
910
|
-
const timeArr: string[] = []
|
|
911
|
-
if (hasTime.value) {
|
|
912
|
-
if (timeColumnsType.value.includes('hour'))
|
|
913
|
-
timeArr.push(base.format('HH'))
|
|
914
|
-
if (timeColumnsType.value.includes('minute'))
|
|
915
|
-
timeArr.push(base.format('mm'))
|
|
916
|
-
if (timeColumnsType.value.includes('second'))
|
|
917
|
-
timeArr.push(base.format('ss'))
|
|
918
|
-
}
|
|
919
|
-
dateTimePickerValue.value = {
|
|
920
|
-
date: dateArr,
|
|
921
|
-
time: timeArr.length ? timeArr : ['00', '00', '00'].slice(0, timeColumnsType.value.length),
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
else {
|
|
925
|
-
const now = dayjs()
|
|
926
|
-
const dateArr: string[] = []
|
|
927
|
-
dateArr.push(now.format('YYYY'))
|
|
928
|
-
if (dateColumnsType.value.includes('month'))
|
|
929
|
-
dateArr.push(now.format('MM'))
|
|
930
|
-
if (dateColumnsType.value.includes('day'))
|
|
931
|
-
dateArr.push(now.format('DD'))
|
|
932
|
-
const timeArr: string[] = []
|
|
933
|
-
if (hasTime.value) {
|
|
934
|
-
if (timeColumnsType.value.includes('hour'))
|
|
935
|
-
timeArr.push(now.format('HH'))
|
|
936
|
-
if (timeColumnsType.value.includes('minute'))
|
|
937
|
-
timeArr.push(now.format('mm'))
|
|
938
|
-
if (timeColumnsType.value.includes('second'))
|
|
939
|
-
timeArr.push(now.format('ss'))
|
|
940
|
-
}
|
|
941
|
-
dateTimePickerValue.value = {
|
|
942
|
-
date: dateArr,
|
|
943
|
-
time: timeArr.length ? timeArr : ['00', '00', '00'].slice(0, timeColumnsType.value.length),
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
showDatePicker.value = true
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
function onDatePickerConfirm({ selectedValues }) {
|
|
950
|
-
showDatePicker.value = false
|
|
951
|
-
modelData.value = selectedValues.join('-')
|
|
952
|
-
}
|
|
953
|
-
|
|
954
762
|
// 已废弃 不进行维护
|
|
955
763
|
function onTimePickerConfirm({ selectedValues }) {
|
|
956
764
|
showTimePicker.value = false
|
|
@@ -969,25 +777,6 @@ function onAreaConfirm({ selectedOptions }) {
|
|
|
969
777
|
}]
|
|
970
778
|
}
|
|
971
779
|
|
|
972
|
-
// 日期时间选择确认:将选择的年月日(+时分秒)拼装后,最终使用 formValueFormat 输出到 v-model
|
|
973
|
-
function onDateTimePickerConfirm() {
|
|
974
|
-
showDatePicker.value = false
|
|
975
|
-
const dateParts = dateTimePickerValue.value.date as string[]
|
|
976
|
-
const timeParts = (dateTimePickerValue.value.time as string[]) || []
|
|
977
|
-
const year = dateParts[0]
|
|
978
|
-
const month = dateParts[1] || '01'
|
|
979
|
-
const day = dateParts[2] || '01'
|
|
980
|
-
const hour = hasTime.value && timeParts[0] ? timeParts[0] : '00'
|
|
981
|
-
const minute = hasTime.value && timeParts[1] ? timeParts[1] : '00'
|
|
982
|
-
const second = hasTime.value && timeParts[2] ? timeParts[2] : '00'
|
|
983
|
-
const full = `${year}-${month}-${day} ${hour}:${minute}:${second}`
|
|
984
|
-
modelData.value = dayjs(full, 'YYYY-MM-DD HH:mm:ss').format(formValueFormat.value)
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
function onPickerCancel() {
|
|
988
|
-
showDatePicker.value = false
|
|
989
|
-
}
|
|
990
|
-
|
|
991
780
|
const showAddressPicker = ref(false)
|
|
992
781
|
const addressValue = ref('')
|
|
993
782
|
|
|
@@ -1527,68 +1316,26 @@ function commChange() {
|
|
|
1527
1316
|
type="range"
|
|
1528
1317
|
teleport="body"
|
|
1529
1318
|
overlay-class="date-picker-overlay"
|
|
1530
|
-
:min-date="datePickerMinDate"
|
|
1531
|
-
:max-date="datePickerMaxDate"
|
|
1532
1319
|
:show-confirm="attr.showConfirm"
|
|
1533
1320
|
@confirm="onCalendarConfirm"
|
|
1534
1321
|
/>
|
|
1535
1322
|
|
|
1536
|
-
<!--
|
|
1537
|
-
<
|
|
1538
|
-
v-if="
|
|
1539
|
-
v-model="
|
|
1540
|
-
|
|
1541
|
-
:
|
|
1542
|
-
:
|
|
1543
|
-
:
|
|
1544
|
-
readonly
|
|
1545
|
-
:is-link="true"
|
|
1323
|
+
<!-- 日期选择器 -->
|
|
1324
|
+
<XDatePicker
|
|
1325
|
+
v-if="attr.type === 'datePicker' && showItem"
|
|
1326
|
+
v-model="modelData"
|
|
1327
|
+
:attr="attr"
|
|
1328
|
+
:form="form"
|
|
1329
|
+
:mode="mode"
|
|
1330
|
+
:readonly="readonly"
|
|
1546
1331
|
:placeholder="placeholder"
|
|
1547
|
-
:
|
|
1548
|
-
:required="attr.rule.required === 'true'"
|
|
1549
|
-
@click="readonly ? null : showDataTimePicker()"
|
|
1550
|
-
/>
|
|
1551
|
-
|
|
1552
|
-
<!-- 日期选择-查询 -->
|
|
1553
|
-
<VanField
|
|
1554
|
-
v-if="attr.type === 'datePicker' && mode === '查询' && showItem"
|
|
1555
|
-
v-model="(modelData as string | number)"
|
|
1556
|
-
name="datePicker"
|
|
1557
|
-
:label="labelData"
|
|
1332
|
+
:label-data="labelData"
|
|
1558
1333
|
:label-align="labelAlign"
|
|
1559
|
-
:input-align="attr.inputAlign
|
|
1560
|
-
|
|
1561
|
-
:
|
|
1562
|
-
|
|
1563
|
-
:rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
|
|
1564
|
-
@click="readonly ? null : showDataTimePicker()"
|
|
1334
|
+
:input-align="attr.inputAlign"
|
|
1335
|
+
:required="attr.rule.required === 'true'"
|
|
1336
|
+
:show-label="showLabel"
|
|
1337
|
+
@change="commChange"
|
|
1565
1338
|
/>
|
|
1566
|
-
<VanPopup v-model:show="showDatePicker" position="bottom" teleport="body" overlay-class="date-picker-overlay">
|
|
1567
|
-
<VanPickerGroup
|
|
1568
|
-
:title="attr.name"
|
|
1569
|
-
:tabs="hasTime ? ['选择日期', '选择时间'] : ['选择日期']"
|
|
1570
|
-
next-step-text="下一步"
|
|
1571
|
-
:confirm-button-text="attr.confirmButtonText ? attr.confirmButtonText : '确认'"
|
|
1572
|
-
:cancel-button-text="attr.cancelButtonText ? attr.cancelButtonText : '取消'"
|
|
1573
|
-
@confirm="onDateTimePickerConfirm"
|
|
1574
|
-
@cancel="onPickerCancel"
|
|
1575
|
-
>
|
|
1576
|
-
<VanDatePicker
|
|
1577
|
-
v-model="dateTimePickerValue.date"
|
|
1578
|
-
:columns-type="attr.dateColumnsType || dateColumnsType"
|
|
1579
|
-
:min-date="datePickerMinDate"
|
|
1580
|
-
:max-date="datePickerMaxDate"
|
|
1581
|
-
/>
|
|
1582
|
-
<VanTimePicker
|
|
1583
|
-
v-if="hasTime"
|
|
1584
|
-
v-model="dateTimePickerValue.time"
|
|
1585
|
-
:columns-type="attr.timeColumnsType || timeColumnsType"
|
|
1586
|
-
v-bind="timePickerColumns ? { columns: timePickerColumns } : {}"
|
|
1587
|
-
:min-time="attr.minTime ? attr.minTime : '00:00:00'"
|
|
1588
|
-
:max-time="attr.maxTime ? attr.maxTime : '23:59:59'"
|
|
1589
|
-
/>
|
|
1590
|
-
</VanPickerGroup>
|
|
1591
|
-
</VanPopup>
|
|
1592
1339
|
|
|
1593
1340
|
<!-- 时间选择 --该配置未在pc找到不进行维护 后续将删除 -->
|
|
1594
1341
|
<VanField
|