59e51671
“wangming”
1
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
/**
* 与 Web 管理端 labelFormDatePreview 一致:templateProductDefaults 中日期/时间/时长存 JSON
* `{"unit":"Days","value":"2"}`,预览与打印时按 BaseTime 解析为 config.text。
*/
import type { SystemTemplateElementBase } from '../print/types/printer'
const OFFSET_UNITS = new Set([
'Minutes',
'Hours',
'Days',
'Weeks',
'Months (30 Day)',
'Years',
])
export function applyOffsetToDate (base: Date, amount: number, unit: string): Date {
const d = new Date(base.getTime())
const u = String(unit ?? '').trim()
switch (u) {
case 'Minutes':
d.setMinutes(d.getMinutes() + amount)
break
case 'Hours':
d.setHours(d.getHours() + amount)
break
case 'Days':
d.setDate(d.getDate() + amount)
break
case 'Weeks':
d.setDate(d.getDate() + amount * 7)
break
case 'Months (30 Day)':
d.setDate(d.getDate() + amount * 30)
break
case 'Years':
d.setFullYear(d.getFullYear() + amount)
break
default:
d.setDate(d.getDate() + amount)
}
return d
}
function formatDateByPreset (format: string, date: Date): string {
const yyyy = String(date.getFullYear())
const yy = yyyy.slice(-2)
const mm = String(date.getMonth() + 1).padStart(2, '0')
const dd = String(date.getDate()).padStart(2, '0')
const hh = String(date.getHours()).padStart(2, '0')
const min = String(date.getMinutes()).padStart(2, '0')
switch (format) {
case 'DD/MM/YYYY':
return `${dd}/${mm}/${yyyy}`
case 'MM/DD/YYYY':
return `${mm}/${dd}/${yyyy}`
case 'DD/MM/YY':
return `${dd}/${mm}/${yy}`
case 'MM/DD/YY':
return `${mm}/${dd}/${yy}`
case 'MM/YY':
return `${mm}/${yy}`
case 'MM/DD':
return `${mm}/${dd}`
case 'MM':
return mm
case 'DD':
return dd
case 'YY':
return yy
case 'YYYY-MM-DD':
return `${yyyy}-${mm}-${dd}`
case 'YYYY-MM-DD HH:mm':
return `${yyyy}-${mm}-${dd} ${hh}:${min}`
case 'HH:mm':
return `${hh}:${min}`
default:
return String(format || '')
.replace(/YYYY/g, yyyy)
.replace(/YY/g, yy)
.replace(/MM/g, mm)
.replace(/DD/g, dd)
.replace(/HH/g, hh)
.replace(/mm/g, min)
}
}
export function tryParsePrintInputOffsetStored (
raw: string | null | undefined,
): { unit: string; value: string } | null {
const t = String(raw ?? '').trim()
if (!t.startsWith('{')) return null
try {
const o = JSON.parse(t) as unknown
if (o == null || typeof o !== 'object' || Array.isArray(o)) return null
const rec = o as Record<string, unknown>
const unit = String(rec.unit ?? rec.Unit ?? '').trim()
const value = String(rec.value ?? rec.Value ?? '')
if (!unit || !OFFSET_UNITS.has(unit)) return null
return { unit, value }
} catch {
return null
}
}
/** 与 Web isDateTimeDataEntryField 对齐(App 侧元素无 typeAdd 时用命名兜底) */
export function isUniAppDateTimeOffsetField (el: SystemTemplateElementBase): boolean {
const type = String(el.type || '').toUpperCase()
const cfg = (el.config || {}) as Record<string, unknown>
if (type === 'TIME' || type === 'DURATION') return true
if (type !== 'DATE') return false
const it = String(cfg.inputType ?? cfg.InputType ?? '').toLowerCase()
if (it === 'datetime' || it === 'date') return true
const ta = String((el as { typeAdd?: string }).typeAdd ?? '').trim().toLowerCase().replace(/\s+/g, ' ')
if (ta === 'label_duration date' || ta.includes('duration date')) return true
const nameHint = `${el.elementName ?? ''} ${el.inputKey ?? ''}`.toLowerCase()
if (/(durationdate|duration_date|duration\s*date)/.test(nameHint)) return true
return false
}
/**
* 将 templateProductDefaults 里单格字符串转为画布用的展示文案(相对 now)。
* 非 JSON 或无法解析时返回原串(兼容旧版已展开的日期文案)。
*/
export function resolveTemplateDefaultValueForElement (
el: SystemTemplateElementBase,
stored: string,
now: Date,
): string {
const s = String(stored ?? '').trim()
if (!s) return ''
if (!isUniAppDateTimeOffsetField(el)) return s
const parsed = tryParsePrintInputOffsetStored(s)
if (!parsed) return s
const amount = Number(String(parsed.value).trim())
const unit = parsed.unit || 'Days'
if (!Number.isFinite(amount) || String(parsed.value).trim() === '') return ''
const type = String(el.type || '').toUpperCase()
const cfg = (el.config || {}) as Record<string, unknown>
const d = applyOffsetToDate(now, amount, unit)
if (type === 'DATE') {
const it = String(cfg.inputType ?? cfg.InputType ?? '').toLowerCase()
const format =
(typeof cfg.format === 'string' && cfg.format.trim()
? cfg.format
: typeof cfg.Format === 'string' && cfg.Format.trim()
? cfg.Format
: it === 'datetime'
? 'YYYY-MM-DD HH:mm'
: 'DD/MM/YYYY') || 'DD/MM/YYYY'
return formatDateByPreset(format, d)
}
if (type === 'TIME') {
return formatDateByPreset('HH:mm', d)
}
return `${amount} ${unit}`
}
|