刘光辉
5 小时以前 cf11e63b659afcc9792ab3e395f1b45d844431a8
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
import type { FieldDataType } from '#/api/x/eln/fields';
 
export interface ControlConfigFormValues {
  controlDateFormat?: string;
  controlDefaultChecked?: boolean;
  controlDefaultDate?: string;
  controlDefaultOption?: string;
  controlDefaultValue?: string;
  controlOptionsText?: string;
  controlPlaceholder?: string;
}
 
export interface DropdownOption {
  display: string;
  value: string;
}
 
const MANAGED_KEYS = new Set(['dateFormat', 'defaultChecked', 'defaultValue', 'options', 'placeholder']);
 
export function controlConfigFormValues(config?: Record<string, unknown>): { extras: Record<string, unknown>; values: ControlConfigFormValues } {
  const source = config || {};
  const values: ControlConfigFormValues = {
    controlDateFormat: stringValue(source.dateFormat),
    controlDefaultChecked: Boolean(source.defaultChecked),
    controlDefaultDate: stringValue(source.defaultValue),
    controlDefaultOption: stringValue(source.defaultValue),
    controlDefaultValue: stringValue(source.defaultValue),
    controlOptionsText: formatDropdownOptions(source.options),
    controlPlaceholder: stringValue(source.placeholder),
  };
  const extras = Object.fromEntries(Object.entries(source).filter(([key]) => !MANAGED_KEYS.has(key)));
  return { extras, values };
}
 
export function buildControlConfig(
  dataType: FieldDataType,
  values: ControlConfigFormValues,
  extras: Record<string, unknown> = {},
): Record<string, unknown> | undefined {
  const config: Record<string, unknown> = { ...extras };
  if (dataType === 'CHECKBOX') {
    if (values.controlDefaultChecked) config.defaultChecked = true;
    return Object.keys(config).length ? config : undefined;
  }
 
  if (['DECIMAL', 'SELECT', 'TEXT', 'TEXTAREA'].includes(dataType)) {
    assignTrimmed(config, 'placeholder', values.controlPlaceholder);
  }
  if (dataType === 'SELECT') {
    const options = parseDropdownOptions(values.controlOptionsText || '');
    if (options.length) config.options = options;
    assignTrimmed(config, 'defaultValue', values.controlDefaultOption);
  } else if (dataType === 'DATE' || dataType === 'DATETIME') {
    assignTrimmed(config, 'dateFormat', values.controlDateFormat);
    assignTrimmed(config, 'defaultValue', values.controlDefaultDate);
  } else {
    assignTrimmed(config, 'defaultValue', values.controlDefaultValue);
  }
  return Object.keys(config).length ? config : undefined;
}
 
export function dropdownOptionsFromText(value?: string): DropdownOption[] {
  return parseDropdownOptions(value || '');
}
 
export function dropdownOptionsForSelect(value?: string): DropdownOption[] {
  try {
    return parseDropdownOptions(value || '');
  } catch {
    return [];
  }
}
 
export function validateDropdownOptions(value?: string): Promise<void> {
  try {
    const options = parseDropdownOptions(value || '');
    if (options.length < 2) throw new Error('请至少填写两个下拉选项');
    return Promise.resolve();
  } catch (error) {
    return Promise.reject(error);
  }
}
 
function assignTrimmed(config: Record<string, unknown>, key: string, value?: string) {
  const trimmed = value?.trim();
  if (trimmed) config[key] = trimmed;
}
 
function formatDropdownOptions(value: unknown): string {
  if (!Array.isArray(value)) return '';
  return value
    .filter((option): option is Record<string, unknown> => Boolean(option) && typeof option === 'object')
    .map((option) => `${stringValue(option.display)}|${stringValue(option.value)}`)
    .join('\n');
}
 
function parseDropdownOptions(value: string): DropdownOption[] {
  const lines = value
    .split(/\r?\n/)
    .map((line) => line.trim())
    .filter(Boolean);
  const options = lines.map((line) => {
    const separator = line.indexOf('|');
    if (separator < 1 || separator === line.length - 1) throw new Error('每个下拉选项均应填写“显示文本|业务值”');
    const display = line.slice(0, separator).trim();
    const optionValue = line.slice(separator + 1).trim();
    if (!display || !optionValue) throw new Error('下拉选项的显示文本和业务值不能为空');
    return { display, value: optionValue };
  });
  if (new Set(options.map((option) => option.value)).size !== options.length) throw new Error('下拉选项的业务值不能重复');
  return options;
}
 
function stringValue(value: unknown): string {
  return typeof value === 'string' ? value : '';
}