Blame view

泰额版/Food Labeling Management App UniApp/src/utils/labelPreview/printInputOptions.ts 8.99 KB
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
  import type {
    LabelTemplateData,
    SystemLabelTemplate,
    SystemTemplateElementBase,
  } from '../print/types/printer'
  
  /**
   * 打印/预览 printInputJson 的 key:与接口文档一致优先 inputKey,否则 elementName,最后兜底元素 id。
   * 兼容根字段与 config 内 InputKey(部分模板把键写在 config)。
   */
  export function printInputJsonKeyForElement(el: SystemTemplateElementBase): string {
    const cfg = el.config || {}
    const top =
      el.inputKey ??
      (el as { InputKey?: string }).InputKey ??
      cfg.inputKey ??
      cfg.InputKey ??
      el.elementName ??
      (el as { ElementName?: string }).ElementName ??
      cfg.elementName ??
      cfg.ElementName
    const s = top != null ? String(top).trim() : ''
    if (s) return s
    return String(el.id ?? '').trim()
  }
  
  export function isPrintInputOptionsElement(el: SystemTemplateElementBase): boolean {
    const vst = String(el.valueSourceType || '').toUpperCase()
    if (vst !== 'PRINT_INPUT') return false
    const c = el.config || {}
    const it = String(c.inputType ?? c.InputType ?? '').toLowerCase()
    if (it === 'options') return true
    const mid = c.multipleOptionId ?? c.MultipleOptionId
    return typeof mid === 'string' && mid.trim() !== ''
  }
  
  /** PRINT_INPUT 且非多选项字典(无 effective multipleOptionId):需用户在页面上输入 */
  export function isPrintInputFreeFieldElement(el: SystemTemplateElementBase): boolean {
    const vst = String(el.valueSourceType || '').toUpperCase()
    if (vst !== 'PRINT_INPUT') return false
    return !isPrintInputOptionsElement(el)
  }
  
  /** 从模板初始 config 读出已选(接口预览可能已带 selectedOptionValues) */
  export function readSelectionsFromTemplate(template: SystemLabelTemplate): Record<string, string[]> {
    const out: Record<string, string[]> = {}
    for (const el of template.elements || []) {
      if (!isPrintInputOptionsElement(el)) continue
      const raw = el.config?.selectedOptionValues ?? el.config?.SelectedOptionValues
      if (Array.isArray(raw) && raw.length) {
        out[el.id] = raw.map((x: unknown) => String(x))
      }
    }
    return out
  }
  
  /**
   * 将多选结果写回 config(画布与打印用 text 展示「字典名: 值」或 prefix+值)
   */
  /** 从预览模板 config 初始化自由输入(如 WEIGHT 的 value、DATE 已算好的 text) */
  export function readFreeFieldValuesFromTemplate(template: SystemLabelTemplate): Record<string, string> {
    const out: Record<string, string> = {}
    for (const el of template.elements || []) {
      if (!isPrintInputFreeFieldElement(el)) continue
      const c = el.config || {}
      const type = String(el.type || '').toUpperCase()
      let initial = ''
      if (type === 'WEIGHT') {
        const v = c.value ?? c.Value
        if (v != null && String(v).trim() !== '') initial = String(v).trim()
      } else {
        const fmt = String(c.format ?? c.Format ?? '').trim()
        const t = String(c.text ?? c.Text ?? '').trim()
        if (t && (!fmt || t !== fmt)) initial = t
      }
      out[el.id] = initial
    }
    return out
  }
  
  export function ensureFreeFieldKeys(
    template: SystemLabelTemplate,
    existing: Record<string, string>
  ): Record<string, string> {
    const out = { ...existing }
    for (const el of template.elements || []) {
      if (!isPrintInputFreeFieldElement(el)) continue
      if (!(el.id in out)) out[el.id] = ''
    }
    return out
  }
  
  /**
   * 将自由输入写回 config:画布用 text 展示;若有 unit 则拼在数值后(如 500g)。
   */
  export function mergePrintInputFreeFields(
    template: SystemLabelTemplate,
    values: Record<string, string>
  ): SystemLabelTemplate {
    return {
      ...template,
      elements: (template.elements || []).map((el) => {
        if (!isPrintInputFreeFieldElement(el)) return el
        const cfg = { ...el.config }
        const raw = String(values[el.id] ?? '').trim()
        const unit = String(cfg.unit ?? cfg.Unit ?? '').trim()
        const type = String(el.type || '').toUpperCase()
  
        if (!raw) {
          if (type === 'DATE' || type === 'TIME') {
            const fmt = String(cfg.format ?? cfg.Format ?? '')
            return { ...el, config: { ...cfg, text: fmt } }
          }
          if (type === 'WEIGHT') {
            return { ...el, config: { ...cfg, text: '', value: '' } }
          }
          const ph = String(
            cfg.placeholder ?? cfg.Placeholder ?? cfg.defaultValue ?? cfg.DefaultValue ?? ''
          ).trim()
          return { ...el, config: { ...cfg, text: ph } }
        }
  
        const display = unit && !raw.endsWith(unit) ? `${raw}${unit}` : raw
        const next = { ...cfg, text: display } as Record<string, any>
        if (type === 'WEIGHT') {
          next.value = raw
        }
        return { ...el, config: next }
      }),
    }
  }
  
  export function mergePrintOptionSelections(
    template: SystemLabelTemplate,
    selections: Record<string, string[]>,
    dictNames: Record<string, string>
  ): SystemLabelTemplate {
    return {
      ...template,
      elements: (template.elements || []).map((el) => {
        if (!isPrintInputOptionsElement(el)) return el
        const sel = selections[el.id]
        if (!sel || sel.length === 0) return el
        const cfg = { ...el.config }
        cfg.selectedOptionValues = sel
        const dictLabel = dictNames[el.id] || 'Options'
        const prefix = String(cfg.prefix ?? cfg.Prefix ?? '').trim()
        const answers = sel.join(', ')
        cfg.text = prefix ? `${prefix}${answers}` : `${dictLabel}: ${answers}`
        return { ...el, config: cfg }
      }),
    }
  }
  
  export function printInputJsonFromSelections(
    template: SystemLabelTemplate,
    selections: Record<string, string[]>
  ): Record<string, unknown> {
    const out: Record<string, unknown> = {}
    for (const el of template.elements || []) {
      if (!isPrintInputOptionsElement(el)) continue
      const sel = selections[el.id]
      if (!sel || !sel.length) continue
      const key = printInputJsonKeyForElement(el)
      if (!key) continue
      out[key] = sel.length === 1 ? sel[0] : [...sel]
    }
    return out
  }
  
  export function printInputJsonFromFreeFields(
    template: SystemLabelTemplate,
    values: Record<string, string>
  ): Record<string, unknown> {
    const out: Record<string, unknown> = {}
    for (const el of template.elements || []) {
      if (!isPrintInputFreeFieldElement(el)) continue
      const key = printInputJsonKeyForElement(el)
      if (!key) continue
      const v = String(values[el.id] ?? '').trim()
      if (v === '') continue
      out[key] = v
    }
    return out
  }
  
  export function buildPrintInputJson(
    template: SystemLabelTemplate,
    optionSelections: Record<string, string[]>,
    freeFieldValues: Record<string, string>
  ): Record<string, unknown> {
    return {
      ...printInputJsonFromSelections(template, optionSelections),
      ...printInputJsonFromFreeFields(template, freeFieldValues),
    }
  }
  
  /**
   * 供接口 9 落库 `printInputJson`:在**纯 JSON 克隆**上再合并多选/自由输入,避免 Vue Proxy 嵌套 config
   * 在部分环境下 `JSON.stringify` 丢字段,导致服务端存下的 RenderDataJson 仍是设计器默认值(无日期、无多选)。
   */
  export function buildPrintPersistTemplateSnapshot(
    base: SystemLabelTemplate,
    optionSelections: Record<string, string[]>,
    freeFieldValues: Record<string, string>,
    dictNames: Record<string, string>
  ): SystemLabelTemplate {
    const cloned = JSON.parse(JSON.stringify(base)) as SystemLabelTemplate
    let m = mergePrintOptionSelections(cloned, optionSelections, dictNames)
    m = mergePrintInputFreeFields(m, freeFieldValues)
    return m
  }
  
  /** 本地打印机 / dataJson:与 printInputJson 同键,供模板 {{key}} 或 native 层合并 */
  export function printInputJsonToLabelTemplateData(pj: Record<string, unknown>): LabelTemplateData {
    const out: LabelTemplateData = {}
    for (const k of Object.keys(pj)) {
      const v = pj[k]
      if (v == null) continue
      if (typeof v === 'string' || typeof v === 'number') {
        out[k] = v
      } else if (Array.isArray(v)) {
        out[k] = v.map((x) => String(x)).join(', ')
      } else {
        out[k] = JSON.stringify(v)
      }
    }
    return out
  }
  
  /**
   * PRINT_INPUT 且为多选项字典:未至少选一项则不可打印。
   */
  export function validatePrintInputOptionsBeforePrint(
    template: SystemLabelTemplate,
    selections: Record<string, string[]>,
    dictLabels: Record<string, string>
  ): string | null {
    for (const el of template.elements || []) {
      if (!isPrintInputOptionsElement(el)) continue
      const sel = selections[el.id]
      if (!sel || sel.length === 0) {
        const name =
          dictLabels[el.id] ||
          el.elementName ||
          el.inputKey ||
          'options'
        return `Please select “${name}” before printing.`
      }
    }
    return null
  }
  
  /**
   * PRINT_INPUT 自由字段:未填写则不可打印。
   */
  export function validatePrintInputFreeFieldsBeforePrint(
    template: SystemLabelTemplate,
    values: Record<string, string>
  ): string | null {
    for (const el of template.elements || []) {
      if (!isPrintInputFreeFieldElement(el)) continue
      const raw = String(values[el.id] ?? '').trim()
      if (raw === '') {
        const name = el.elementName || el.inputKey || 'field'
        return `Please fill in “${name}” before printing.`
      }
    }
    return null
  }