import type { FillFieldType } from '../domain/types';
|
|
export function inspectFieldsCommand(): string {
|
function errorMessage(error: unknown): string {
|
return error instanceof Error ? error.message : String(error);
|
}
|
|
function textOf(control: any): string {
|
return String(control.GetRange().GetText() ?? '');
|
}
|
|
function kindOf(control: any): FillFieldType {
|
if (control.IsCheckBox?.()) return 'checkbox';
|
if (control.IsComboBox?.() || control.IsDropDownList?.()) return 'select';
|
if (control.IsDatePicker?.()) return 'date';
|
if (control.IsBlockLevel?.()) return 'multiline';
|
return 'text';
|
}
|
|
function optionsOf(control: any): Array<{ display: string; value: string }> {
|
const list = control.GetDropdownList?.();
|
if (!list?.GetElementsCount || !list.GetItem) return [];
|
const options = [];
|
for (let index = 0; index < list.GetElementsCount(); index += 1) {
|
const item = list.GetItem(index);
|
options.push({ display: String(item.GetText()), value: String(item.GetValue()) });
|
}
|
return options;
|
}
|
|
function readValue(control: any, type: FillFieldType): boolean | string {
|
const text = textOf(control);
|
if (type === 'checkbox') return ['☒', '☑'].includes(text);
|
if (type === 'select') return optionsOf(control).find((item) => item.display === text)?.value ?? '';
|
return text;
|
}
|
|
try {
|
const controls = Api.GetDocument().GetAllContentControls();
|
const fields = controls.filter((control: any) => /^eln\.(field\.[^.]+|repeat\.[^.]+\.[^.]+\.[^.]+)$/u.test(control.GetTag())).map((control: any) => {
|
const type = kindOf(control);
|
return {
|
alias: String(control.GetAlias?.() ?? ''),
|
currentValue: readValue(control, type),
|
internalId: String(control.GetInternalId?.() ?? ''),
|
options: type === 'select' ? optionsOf(control) : [],
|
tag: String(control.GetTag()),
|
type,
|
};
|
});
|
const tags = fields.map((field: any) => field.tag);
|
if (new Set(tags).size !== tags.length) throw new Error('文档存在重复字段 Tag');
|
return JSON.stringify({ ok: true, fields });
|
} catch (error) {
|
return JSON.stringify({ ok: false, error: errorMessage(error), fields: [] });
|
}
|
}
|
|
export function applyFieldsCommand(): string {
|
function errorMessage(error: unknown): string {
|
return error instanceof Error ? error.message : String(error);
|
}
|
|
function textOf(control: any): string {
|
return String(control.GetRange().GetText() ?? '');
|
}
|
|
function kindOf(control: any): FillFieldType {
|
if (control.IsCheckBox?.()) return 'checkbox';
|
if (control.IsComboBox?.() || control.IsDropDownList?.()) return 'select';
|
if (control.IsDatePicker?.()) return 'date';
|
if (control.IsBlockLevel?.()) return 'multiline';
|
return 'text';
|
}
|
|
function optionsOf(control: any): Array<{ display: string; value: string }> {
|
const list = control.GetDropdownList?.();
|
if (!list?.GetElementsCount || !list.GetItem) return [];
|
const options = [];
|
for (let index = 0; index < list.GetElementsCount(); index += 1) {
|
const item = list.GetItem(index);
|
options.push({ display: String(item.GetText()), value: String(item.GetValue()) });
|
}
|
return options;
|
}
|
|
function readValue(control: any, type: FillFieldType): boolean | string {
|
const text = textOf(control);
|
if (type === 'checkbox') return ['☒', '☑'].includes(text);
|
if (type === 'select') return optionsOf(control).find((item) => item.display === text)?.value ?? '';
|
return text;
|
}
|
|
function writeValue(control: any, type: FillFieldType, value: boolean | string): void {
|
if (type === 'checkbox') {
|
control.SetCheckBoxChecked(Boolean(value));
|
return;
|
}
|
if (type === 'select') {
|
if (!optionsOf(control).some((item) => item.value === value)) throw new Error('下拉值不在文档选项中');
|
control.SelectListItem(value);
|
return;
|
}
|
if (type === 'date') {
|
const parts = String(value).split('-').map(Number);
|
if (parts.length !== 3 || parts.some((part) => !Number.isInteger(part))) throw new Error('日期格式无效');
|
control.SetDate(new Date(parts[0]!, parts[1]! - 1, parts[2]!));
|
return;
|
}
|
control.RemoveAllElements();
|
if (type === 'multiline') {
|
String(value).split('\n').forEach((line, index) => {
|
const paragraph = Api.CreateParagraph();
|
const run = Api.CreateRun();
|
run.AddText(line);
|
paragraph.AddElement(run);
|
control.AddElement(paragraph, index);
|
});
|
return;
|
}
|
const run = Api.CreateRun();
|
run.AddText(String(value));
|
control.AddElement(run, 0);
|
}
|
|
const changes = Asc.scope.elnTemplateFillChanges;
|
if (!Array.isArray(changes)) return JSON.stringify({ ok: false, error: '缺少字段修改', results: [] });
|
const controls = Api.GetDocument().GetAllContentControls();
|
const results = changes.map((change) => {
|
const matches = controls.filter((control: any) => control.GetTag() === change.tag);
|
if (matches.length !== 1) return { tag: change.tag, ok: false, error: '无法按 Tag 定位唯一控件' };
|
const control = matches[0];
|
const actualType = kindOf(control);
|
if (actualType !== change.type) return { tag: change.tag, ok: false, error: '字段类型与文档控件不一致' };
|
const before = readValue(control, actualType);
|
try {
|
writeValue(control, actualType, change.value);
|
if (readValue(control, actualType) !== change.value) throw new Error('字段写入后回读不一致');
|
return { tag: change.tag, ok: true };
|
} catch (error) {
|
try { writeValue(control, actualType, before); } catch { /* 原生撤销是最终恢复手段。 */ }
|
return { tag: change.tag, ok: false, error: errorMessage(error) };
|
}
|
});
|
return JSON.stringify({ ok: true, results });
|
}
|