import type { OnlyOfficeContentControl, OnlyOfficeParagraph, UpdateControlSpec } from './types';
|
|
export function setFormulaResultLockCommand(): string {
|
try {
|
const spec = Asc.scope.elnTemplateFormulaLocks;
|
if (!spec || !['lock', 'restore', 'unlock', 'verify'].includes(spec.mode)) throw new Error('缺少公式结果锁配置');
|
const primaryTag = spec.mode === 'restore' ? spec.snapshot?.primaryTag : spec.primaryTag;
|
if (!primaryTag || !primaryTag.startsWith('eln.field.')) throw new Error('公式结果主控件 Tag 无效');
|
const fieldCode = primaryTag.slice('eln.field.'.length);
|
if (!fieldCode) throw new Error('公式结果主控件 Tag 无效');
|
const controls = Api.GetDocument().GetAllContentControls();
|
const matches = controls.filter((control) => {
|
const tag = String(control.GetTag?.() ?? '');
|
return tag === primaryTag || tag.startsWith(`eln.ref.${fieldCode}.`);
|
});
|
if (matches.filter((control) => String(control.GetTag?.() ?? '') === primaryTag).length !== 1) throw new Error('无法按 Tag 定位唯一结果主控件');
|
const snapshot =
|
spec.mode === 'restore'
|
? spec.snapshot
|
: {
|
primaryTag,
|
locks: matches.map((control) => ({ tag: String(control.GetTag?.() ?? ''), lock: String(control.GetLock?.() ?? '') })),
|
};
|
if (!snapshot || !Array.isArray(snapshot.locks) || snapshot.locks.length !== matches.length) throw new Error('公式结果锁快照不完整');
|
const mode: string = spec.mode;
|
const expected = new Map(
|
snapshot.locks.map((item) => [item.tag, mode === 'lock' || mode === 'verify' ? 'sdtContentLocked' : mode === 'unlock' ? 'unlocked' : item.lock]),
|
);
|
if (expected.size !== matches.length || matches.some((control) => !expected.has(String(control.GetTag?.() ?? ''))))
|
throw new Error('公式结果锁快照与文档不一致');
|
if (spec.mode !== 'verify') {
|
const original = matches.map((control) => ({ control, lock: String(control.GetLock?.() ?? '') }));
|
try {
|
for (const control of matches) {
|
const tag = String(control.GetTag?.() ?? '');
|
if (control.SetLock?.(expected.get(tag)!) !== true) throw new Error('设置公式结果控件锁失败');
|
}
|
} catch (error) {
|
for (const item of original) item.control.SetLock?.(item.lock);
|
throw error;
|
}
|
}
|
for (const control of matches) {
|
const tag = String(control.GetTag?.() ?? '');
|
if (String(control.GetLock?.() ?? '') !== expected.get(tag)) throw new Error('公式结果控件锁回读不一致');
|
}
|
return JSON.stringify({ ok: true, snapshot });
|
} catch (error: unknown) {
|
return JSON.stringify({ ok: false, error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error) });
|
}
|
}
|
|
export function disableTrackRevisionsCommand(): string {
|
try {
|
if (!Asc.scope.elnTemplateReview) {
|
throw new Error('缺少修订配置');
|
}
|
const doc = Api.GetDocument();
|
if (typeof doc.AcceptAllRevisionChanges !== 'function') {
|
throw new Error('当前编辑器不支持接受修订');
|
}
|
if (typeof doc.SetTrackRevisions !== 'function') {
|
throw new Error('当前编辑器不支持关闭修订');
|
}
|
if (typeof doc.IsTrackRevisions !== 'function') {
|
throw new Error('当前编辑器不支持确认修订状态');
|
}
|
if (typeof doc.Document?.HaveRevisionChanges !== 'function') {
|
throw new Error('当前编辑器不支持确认历史修订状态');
|
}
|
if (typeof doc.Document.SetTrackRevisions !== 'function') {
|
throw new Error('当前编辑器不支持关闭本地修订');
|
}
|
if (doc.AcceptAllRevisionChanges() === false) {
|
throw new Error('接受历史修订失败');
|
}
|
if (doc.Document.HaveRevisionChanges(true) !== false) {
|
throw new Error('历史修订仍未全部接受');
|
}
|
if (doc.SetTrackRevisions(false) === false) {
|
throw new Error('关闭修订失败');
|
}
|
doc.Document.SetTrackRevisions(false);
|
if (doc.IsTrackRevisions() !== false) {
|
throw new Error('修订跟踪仍处于开启状态');
|
}
|
return JSON.stringify({ ok: true });
|
} catch (error: unknown) {
|
return JSON.stringify({
|
ok: false,
|
error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error),
|
});
|
}
|
}
|
|
export function readTrackRevisionsStateCommand(): string {
|
try {
|
if (!Asc.scope.elnTemplateReviewState) {
|
throw new Error('缺少修订状态读取配置');
|
}
|
const doc = Api.GetDocument();
|
if (typeof doc.IsTrackRevisions !== 'function') {
|
throw new Error('当前编辑器不支持确认修订状态');
|
}
|
if (typeof doc.Document?.HaveRevisionChanges !== 'function') {
|
throw new Error('当前编辑器不支持确认历史修订状态');
|
}
|
return JSON.stringify({
|
hasRevisionChanges: doc.Document.HaveRevisionChanges(true),
|
ok: true,
|
trackRevisions: doc.IsTrackRevisions(),
|
});
|
} catch (error: unknown) {
|
return JSON.stringify({
|
ok: false,
|
error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error),
|
});
|
}
|
}
|
|
export function listContentControlsCommand(): string {
|
try {
|
if (!Asc.scope.elnTemplateList) {
|
throw new Error('缺少内容控件列表配置');
|
}
|
|
const controls = Api.GetDocument().GetAllContentControls();
|
const result = controls.map((control) => {
|
let controlType = 'text';
|
if (control.IsCheckBox?.()) controlType = 'checkbox';
|
else if (control.IsComboBox?.() || control.IsDropDownList?.()) controlType = 'dropdown';
|
else if (control.IsDatePicker?.()) controlType = 'date';
|
else if (control.IsBlockLevel?.()) controlType = 'multiline';
|
|
const tag = String(control.GetTag?.() ?? '');
|
const controlRole = tag.startsWith('eln.ref.')
|
? 'REFERENCE'
|
: tag.startsWith('eln.field.')
|
? 'PRIMARY'
|
: tag.startsWith('eln.repeat.')
|
? 'REPEAT'
|
: 'UNKNOWN';
|
const config: Record<string, unknown> = {};
|
const placeholder = String(control.GetPlaceholderText?.() ?? '');
|
if (controlType === 'dropdown') {
|
const items = control.GetDropdownList?.().GetAllItems?.();
|
if (!Array.isArray(items)) throw new Error('无法读取下拉控件选项');
|
const options = items.map((item) => ({ display: String(item.GetText?.() ?? ''), value: String(item.GetValue?.() ?? '') }));
|
config.options = options;
|
config.placeholder = placeholder;
|
if (controlRole === 'PRIMARY') {
|
const currentText = String(control.GetRange?.()?.GetText?.() ?? '');
|
const selected =
|
currentText && currentText !== placeholder ? options.find((option) => option.display === currentText || option.value === currentText) : undefined;
|
if (currentText && currentText !== placeholder && !selected) throw new Error('下拉控件当前值不在选项中');
|
config.defaultValue = selected?.value ?? '';
|
}
|
} else if (controlType === 'checkbox') {
|
if (typeof control.IsCheckBoxChecked !== 'function') throw new Error('无法读取复选框状态');
|
config.defaultChecked = Boolean(control.IsCheckBoxChecked());
|
} else if (controlType === 'date') {
|
const json = control.ToJSON?.(false);
|
if (typeof json !== 'string') throw new Error('无法读取日期控件格式');
|
let dateFormat: unknown;
|
try {
|
dateFormat = (JSON.parse(json) as { sdtPr?: { date?: { dateFormat?: unknown } } }).sdtPr?.date?.dateFormat;
|
} catch {
|
throw new Error('日期控件结构数据无效');
|
}
|
if (typeof dateFormat !== 'string' || !dateFormat) throw new Error('无法读取日期控件格式');
|
config.dateFormat = dateFormat;
|
config.placeholder = placeholder;
|
} else {
|
config.placeholder = placeholder;
|
}
|
|
return {
|
Alias: String(control.GetAlias?.() ?? ''),
|
ControlConfig: config,
|
ControlRole: controlRole,
|
ControlType: controlType,
|
InternalId: String(control.GetInternalId?.() ?? ''),
|
Lock: String(control.GetLock?.() ?? ''),
|
Tag: tag,
|
};
|
});
|
|
return JSON.stringify({ ok: true, controls: result });
|
} catch (error: unknown) {
|
return JSON.stringify({
|
ok: false,
|
error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error),
|
});
|
}
|
}
|
|
export function readControlTextCommand(): string {
|
try {
|
const spec = Asc.scope.elnTemplateReadText;
|
if (!spec) throw new Error('缺少文本读取配置');
|
const matches = Api.GetDocument()
|
.GetAllContentControls()
|
.filter((control) => control.GetTag() === spec.tag);
|
if (matches.length !== 1) throw new Error('无法按 Tag 定位唯一主字段控件');
|
const range = matches[0]!.GetRange?.();
|
if (!range || typeof range.GetText !== 'function') throw new Error('当前编辑器不支持读取控件文本');
|
return JSON.stringify({ ok: true, text: String(range.GetText()) });
|
} catch (error: unknown) {
|
return JSON.stringify({ ok: false, error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error) });
|
}
|
}
|
|
export function updateControlSpecCommand(): string {
|
function requireSuccess(result: unknown, label: string): void {
|
if (result !== true) throw new Error(`${label}失败`);
|
}
|
|
function typeOf(control: OnlyOfficeContentControl): string {
|
if (control.IsCheckBox?.()) return 'CHECKBOX';
|
if (control.IsComboBox?.() || control.IsDropDownList?.()) return 'DROPDOWN';
|
if (control.IsDatePicker?.()) return 'DATE';
|
if (control.IsBlockLevel?.()) return 'MULTILINE';
|
return 'TEXT';
|
}
|
|
function optionsOf(config: Record<string, unknown>): Array<{ display: string; value: string }> {
|
if (!Array.isArray(config.options)) return [];
|
return config.options.map((option) => {
|
if (typeof option === 'object' && option && 'display' in option && 'value' in option) {
|
return { display: String(option.display), value: String(option.value) };
|
}
|
return { display: String(option), value: String(option) };
|
});
|
}
|
|
function controlOptions(control: OnlyOfficeContentControl): Array<{ display: string; value: string }> {
|
const items = control.GetDropdownList?.().GetAllItems?.();
|
if (!Array.isArray(items)) throw new Error('无法读取下拉控件选项');
|
return items.map((item) => ({ display: String(item.GetText?.() ?? ''), value: String(item.GetValue?.() ?? '') }));
|
}
|
|
function dateFormatOf(control: OnlyOfficeContentControl): string {
|
const json = control.ToJSON?.(false);
|
if (typeof json !== 'string') throw new Error('无法读取日期控件格式');
|
let value: unknown;
|
try {
|
value = (JSON.parse(json) as { sdtPr?: { date?: { dateFormat?: unknown } } }).sdtPr?.date?.dateFormat;
|
} catch {
|
throw new Error('日期控件结构数据无效');
|
}
|
if (value === undefined) return 'yyyy-MM-dd';
|
if (typeof value !== 'string' || !value) throw new Error('无法读取日期控件格式');
|
return value;
|
}
|
|
function snapshot(control: OnlyOfficeContentControl) {
|
const controlType = typeOf(control);
|
return {
|
alias: String(control.GetAlias?.() ?? ''),
|
checked: controlType === 'CHECKBOX' ? Boolean(control.IsCheckBoxChecked?.()) : false,
|
control,
|
controlType,
|
currentText: String(control.GetRange?.()?.GetText?.() ?? ''),
|
dateFormat: controlType === 'DATE' ? dateFormatOf(control) : '',
|
lock: String(control.GetLock?.() ?? ''),
|
options: controlType === 'DROPDOWN' ? controlOptions(control) : [],
|
placeholder: String(control.GetPlaceholderText?.() ?? ''),
|
tag: String(control.GetTag()),
|
};
|
}
|
|
function rollbackCall(action: () => unknown): boolean {
|
try {
|
return action() === true;
|
} catch {
|
return false;
|
}
|
}
|
|
function restore(original: ReturnType<typeof snapshot>): boolean {
|
const control = original.control;
|
let restored = true;
|
const apply = (action: () => unknown) => {
|
if (!rollbackCall(action)) restored = false;
|
};
|
apply(() => control.SetTag?.(original.tag));
|
apply(() => control.SetAlias?.(original.alias));
|
apply(() => control.SetLock?.(original.lock));
|
if (original.controlType !== 'CHECKBOX') apply(() => control.SetPlaceholderText?.(original.placeholder));
|
if (original.controlType === 'DROPDOWN') {
|
const list = control.GetDropdownList?.();
|
apply(() => list?.Clear?.());
|
for (const option of original.options) apply(() => list?.Add?.(option.display, option.value));
|
const selected = original.options.find((option) => option.display === original.currentText || option.value === original.currentText);
|
if (selected) apply(() => control.SelectListItem?.(selected.value));
|
} else if (original.controlType === 'CHECKBOX') {
|
apply(() => control.SetCheckBoxChecked?.(original.checked));
|
} else if (original.controlType === 'DATE') {
|
apply(() => control.SetDateFormat?.(original.dateFormat));
|
}
|
return restored;
|
}
|
|
function configure(control: OnlyOfficeContentControl, item: UpdateControlSpec, currentText: string): void {
|
const config = item.controlConfig || {};
|
requireSuccess(control.SetTag?.(item.tag), '设置 Tag');
|
requireSuccess(control.SetAlias?.(item.alias), '设置字段名称');
|
requireSuccess(control.SetLock?.(item.lock), '设置控件锁定状态');
|
const placeholder = typeof config.placeholder === 'string' ? config.placeholder : '';
|
if (placeholder && item.controlType !== 'CHECKBOX') requireSuccess(control.SetPlaceholderText?.(placeholder), '设置占位文本');
|
if (item.controlType === 'DROPDOWN') {
|
const list = control.GetDropdownList?.();
|
if (!list || typeof list.Clear !== 'function' || typeof list.Add !== 'function') throw new Error('当前编辑器不支持更新下拉选项');
|
requireSuccess(list.Clear(), '清空下拉选项');
|
const options = optionsOf(config);
|
for (const option of options) requireSuccess(list.Add(option.display, option.value), '写入下拉选项');
|
const selected = options.find((option) => option.display === currentText || option.value === currentText);
|
if (selected && typeof control.SelectListItem === 'function') requireSuccess(control.SelectListItem(selected.value), '恢复下拉当前值');
|
} else if (item.controlType === 'DATE') {
|
const format = typeof config.dateFormat === 'string' ? config.dateFormat : 'yyyy-MM-dd';
|
requireSuccess(control.SetDateFormat?.(format), '设置日期格式');
|
}
|
}
|
|
try {
|
const spec = Asc.scope.elnTemplateUpdateControls;
|
if (!spec || !Array.isArray(spec.updates)) throw new Error('缺少控件更新配置');
|
const removals = spec.removals ?? [];
|
if (!Array.isArray(removals)) throw new Error('控件删除配置无效');
|
if (removals.length > 1) throw new Error('当前阶段不支持一次删除多个控件');
|
const controls = Api.GetDocument().GetAllContentControls();
|
const updateTags = new Set<string>();
|
const removalTags = new Set<string>();
|
const prepared = spec.updates.map((item) => {
|
if (updateTags.has(item.currentTag)) throw new Error('同一控件不能重复更新');
|
updateTags.add(item.currentTag);
|
const matches = controls.filter((control) => control.GetTag() === item.currentTag);
|
if (matches.length !== 1) throw new Error('无法按 Tag 定位唯一待更新控件');
|
return { item, original: snapshot(matches[0]!) };
|
});
|
for (const { item, original } of prepared) {
|
const config = item.controlConfig || {};
|
if (item.controlType !== 'CHECKBOX' && config.placeholder === '' && original.placeholder !== '') {
|
throw new Error('当前编辑器不支持清空已有占位文本');
|
}
|
if (item.controlType !== 'CHECKBOX' && typeof config.placeholder === 'string' && config.placeholder !== '' && original.placeholder === '') {
|
throw new Error('当前编辑器不支持为已有控件设置占位文本');
|
}
|
if (item.controlType === 'DROPDOWN' && original.currentText && original.currentText !== original.placeholder) {
|
const options = optionsOf(config);
|
if (!options.some((option) => option.display === original.currentText || option.value === original.currentText)) {
|
throw new Error('下拉控件当前值不在新选项中');
|
}
|
}
|
}
|
const removalControls = removals.map((tag) => {
|
if (removalTags.has(tag)) throw new Error('同一控件不能重复删除');
|
removalTags.add(tag);
|
if (updateTags.has(tag)) throw new Error('同一控件不能同时更新和删除');
|
const matches = controls.filter((control) => control.GetTag() === tag);
|
if (matches.length !== 1) throw new Error('无法按 Tag 定位唯一待删除控件');
|
return matches[0]!;
|
});
|
const finalTags = new Set(
|
controls.filter((control) => !updateTags.has(control.GetTag()) && !removalTags.has(control.GetTag())).map((control) => control.GetTag()),
|
);
|
for (const { item } of prepared) {
|
if (finalTags.has(item.tag)) throw new Error('更新后的控件 Tag 重复');
|
finalTags.add(item.tag);
|
}
|
const rebuilds = prepared.filter(({ item, original }) => original.controlType !== item.controlType);
|
if (rebuilds.length) throw new Error('当前阶段不支持修改已有控件类型');
|
|
const promotion = removalControls.length === 1 ? prepared.find(({ item }) => item.tag === removals[0]) : undefined;
|
let temporaryTag = '';
|
if (promotion) {
|
let suffix = 0;
|
do {
|
temporaryTag = `eln.tmp.${Date.now().toString(36)}.${suffix}`;
|
suffix += 1;
|
} while (controls.some((control) => control.GetTag() === temporaryTag));
|
}
|
|
const applied: Array<ReturnType<typeof snapshot>> = [];
|
let promotionTagAttempted = false;
|
let updated = 0;
|
try {
|
if (promotion) {
|
promotionTagAttempted = true;
|
requireSuccess(removalControls[0]!.SetTag?.(temporaryTag), '暂存旧主控件 Tag');
|
}
|
for (const { item, original } of prepared) {
|
applied.push(original);
|
configure(original.control, item, original.currentText);
|
updated += 1;
|
}
|
for (const control of removalControls) requireSuccess(control.Delete?.(false), '删除旧控件');
|
} catch (error: unknown) {
|
let rollbackFailed = false;
|
for (let index = applied.length - 1; index >= 0; index -= 1) {
|
if (!restore(applied[index]!)) rollbackFailed = true;
|
}
|
if (promotionTagAttempted && !rollbackCall(() => removalControls[0]!.SetTag?.(removals[0]!))) rollbackFailed = true;
|
if (rollbackFailed) {
|
const message = error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error);
|
throw new Error(`${message};文档回滚失败`);
|
}
|
throw error;
|
}
|
return JSON.stringify({ ok: true, updated });
|
} catch (error: unknown) {
|
return JSON.stringify({ ok: false, error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error) });
|
}
|
}
|
|
export function insertTypedControlCommand(): string {
|
const spec = Asc.scope.elnTemplateInsert;
|
|
function requireMethod(target: unknown, name: string, label: string): void {
|
if (!target || typeof (target as Record<string, unknown>)[name] !== 'function') {
|
throw new Error(`当前编辑器不支持${label}`);
|
}
|
}
|
|
function requireSuccess(result: unknown, label: string): void {
|
if (result !== true) {
|
throw new Error(`${label}失败`);
|
}
|
}
|
|
function debug(event: string, details: Record<string, unknown>): void {
|
if (spec?.debug && typeof console !== 'undefined') {
|
console.info('[ELN annotator command]', new Date().toISOString(), 'insertTypedControlCommand', event, details);
|
}
|
}
|
|
try {
|
if (!spec) {
|
throw new Error('缺少字段控件配置');
|
}
|
|
debug('start', { controlType: spec.controlType, tag: spec.tag });
|
const doc = Api.GetDocument();
|
const selectedTextPr = doc.GetRangeBySelect?.()?.GetTextPr?.() ?? doc.GetCurrentRun?.()?.GetTextPr?.();
|
let control: OnlyOfficeContentControl | null = null;
|
let inlineContainer: OnlyOfficeParagraph | null = null;
|
let isBlock = false;
|
|
if (spec.controlType === 'text') {
|
if (typeof Api.CreateInlineLvlSdt !== 'function') {
|
throw new Error('当前编辑器不支持单行文本控件');
|
}
|
control = Api.CreateInlineLvlSdt();
|
} else if (spec.controlType === 'dropdown') {
|
if (typeof Api.CreateComboBoxContentControl !== 'function') {
|
throw new Error('当前编辑器不支持下拉控件');
|
}
|
control = Api.CreateComboBoxContentControl(spec.options, spec.selectedIndex);
|
} else if (spec.controlType === 'checkbox') {
|
if (typeof Api.CreateCheckBoxContentControl !== 'function') {
|
throw new Error('当前编辑器不支持复选框控件');
|
}
|
control = Api.CreateCheckBoxContentControl({
|
checked: Boolean(spec.defaultChecked),
|
checkedSymbol: 0x2611,
|
uncheckedSymbol: 0x2610,
|
});
|
} else if (spec.controlType === 'date') {
|
if (typeof Api.CreateDatePickerContentControl !== 'function') {
|
throw new Error('当前编辑器不支持日期控件');
|
}
|
const format = typeof spec.dateFormat === 'string' && spec.dateFormat ? spec.dateFormat : 'yyyy-MM-dd';
|
control = Api.CreateDatePickerContentControl({
|
format,
|
lang: 'zh-CN',
|
});
|
if (spec.defaultValue) {
|
const parts = /^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?$/.exec(spec.defaultValue);
|
if (!parts) throw new Error('日期默认值格式无效');
|
const values = parts.slice(1).map((item) => Number(item || 0));
|
const value = new Date(values[0], values[1] - 1, values[2], values[3], values[4], values[5]);
|
if (
|
value.getFullYear() !== values[0] ||
|
value.getMonth() !== values[1] - 1 ||
|
value.getDate() !== values[2] ||
|
value.getHours() !== values[3] ||
|
value.getMinutes() !== values[4] ||
|
value.getSeconds() !== values[5]
|
) {
|
throw new Error('日期默认值无效');
|
}
|
requireMethod(control, 'SetDate', '设置日期默认值');
|
requireSuccess(control.SetDate!(value), '设置日期默认值');
|
} else {
|
requireMethod(control, 'RemoveAllElements', '清空日期默认值');
|
requireSuccess(control.RemoveAllElements!(), '清空日期默认值');
|
}
|
} else if (spec.controlType === 'multiline') {
|
if (typeof Api.CreateBlockLvlSdt !== 'function') {
|
throw new Error('当前编辑器不支持多行文本控件');
|
}
|
control = Api.CreateBlockLvlSdt();
|
isBlock = true;
|
|
if (spec.defaultValue) {
|
requireMethod(control, 'RemoveAllElements', '写入多行默认值');
|
requireSuccess(control.RemoveAllElements!(), '清空多行默认值');
|
spec.defaultValue.split(/\r?\n/).forEach((text, index) => {
|
const paragraph = Api.CreateParagraph();
|
paragraph.AddText(text);
|
requireMethod(control, 'AddElement', '写入多行默认值');
|
requireSuccess(control!.AddElement!(paragraph, index), '写入多行默认值');
|
});
|
}
|
} else {
|
throw new Error('不支持的字段控件类型');
|
}
|
|
if (!isBlock) {
|
inlineContainer = Api.CreateParagraph();
|
requireMethod(inlineContainer, 'AddInlineLvlSdt', '将文本控件挂入段落');
|
inlineContainer.AddInlineLvlSdt(control);
|
debug('attached-to-paragraph', { controlType: spec.controlType, tag: spec.tag });
|
}
|
|
if (spec.controlType === 'text' && spec.defaultValue) {
|
const run = Api.CreateRun();
|
requireMethod(run, 'AddText', '写入文本默认值');
|
requireMethod(control, 'RemoveAllElements', '写入文本默认值');
|
requireMethod(control, 'AddElement', '写入文本默认值');
|
requireSuccess(run.AddText!(spec.defaultValue), '写入文本默认值');
|
requireSuccess(control.RemoveAllElements!(), '清空文本默认值');
|
requireSuccess(control.AddElement!(run, 0), '写入文本默认值');
|
}
|
|
requireMethod(control, 'SetTag', '设置 Tag');
|
requireMethod(control, 'SetAlias', '设置字段名称');
|
requireMethod(control, 'SetLock', '设置控件锁定状态');
|
requireMethod(control, 'SetAppearance', '设置控件外观');
|
const tagResult = control.SetTag!(spec.tag);
|
debug('set-tag', { result: tagResult, tag: spec.tag });
|
requireSuccess(tagResult, '设置 Tag');
|
const aliasResult = control.SetAlias!(spec.alias);
|
debug('set-alias', { result: aliasResult });
|
requireSuccess(aliasResult, '设置字段名称');
|
const lockResult = control.SetLock!(spec.lock ?? 'unlocked');
|
debug('set-lock', { result: lockResult });
|
requireSuccess(lockResult, '设置控件锁定状态');
|
control.SetAppearance!('boundingBox');
|
|
if (spec.color) {
|
requireMethod(Api, 'CreateRGBColor', '创建控件颜色');
|
requireMethod(control, 'SetColor', '设置控件颜色');
|
requireSuccess(control.SetColor!(Api.CreateRGBColor!(spec.color.R, spec.color.G, spec.color.B)), '设置控件颜色');
|
}
|
|
const hasDefault = spec.controlType === 'dropdown' ? spec.selectedIndex >= 0 : Boolean(spec.defaultValue);
|
|
if (spec.controlType !== 'checkbox' && !hasDefault && spec.placeholder) {
|
requireMethod(control, 'SetPlaceholderText', '设置占位文本');
|
requireSuccess(control.SetPlaceholderText!(spec.placeholder), '设置占位文本');
|
}
|
|
requireMethod(doc, 'InsertContent', '插入内容控件');
|
if (isBlock) {
|
const insertResult = doc.InsertContent!([control], false);
|
debug('insert-content', { isBlock, result: insertResult });
|
requireSuccess(insertResult, '插入内容控件');
|
} else {
|
const insertResult = doc.InsertContent!([inlineContainer!], true);
|
debug('insert-content', { isBlock, result: insertResult });
|
requireSuccess(insertResult, '插入内容控件');
|
}
|
|
if (selectedTextPr) {
|
const insertedControls = doc.GetAllContentControls().filter((item) => item.GetTag() === spec.tag);
|
if (insertedControls.length !== 1) {
|
throw new Error('无法按 Tag 定位唯一的新控件');
|
}
|
const insertedControl = insertedControls[0]!;
|
requireMethod(insertedControl, 'GetRange', '读取新控件格式范围');
|
const controlRange = insertedControl.GetRange!();
|
requireMethod(controlRange, 'SetTextPr', '继承选区格式');
|
if (!controlRange.SetTextPr!(selectedTextPr)) {
|
throw new Error('继承选区格式失败');
|
}
|
}
|
|
return JSON.stringify({
|
ok: true,
|
controlType: spec.controlType,
|
});
|
} catch (error: unknown) {
|
debug('error', { error: error && (error as { message?: unknown }).message ? String((error as { message: unknown }).message) : String(error) });
|
return JSON.stringify({
|
ok: false,
|
error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error),
|
});
|
}
|
}
|
|
export function writeTextDefaultCommand(): string {
|
const spec = Asc.scope.elnTemplateTextDefault;
|
|
function requireMethod(target: unknown, name: string, label: string): void {
|
if (!target || typeof (target as Record<string, unknown>)[name] !== 'function') {
|
throw new Error(`当前编辑器不支持${label}`);
|
}
|
}
|
|
function requireSuccess(result: unknown, label: string): void {
|
if (result !== true) {
|
throw new Error(`${label}失败`);
|
}
|
}
|
|
try {
|
if (!spec) {
|
throw new Error('缺少文本默认值配置');
|
}
|
|
const controls = Api.GetDocument().GetAllContentControls();
|
const matches: OnlyOfficeContentControl[] = [];
|
|
for (let index = 0; index < controls.length; index += 1) {
|
if (controls[index]!.GetTag() === spec.tag) {
|
matches.push(controls[index]!);
|
}
|
}
|
|
if (matches.length !== 1) {
|
throw new Error('无法按 Tag 定位唯一控件');
|
}
|
|
const control = matches[0]!;
|
requireMethod(control, 'GetRange', '读取文本默认值');
|
const originalTextPr = control.GetRange!().GetTextPr?.();
|
const run = Api.CreateRun();
|
requireMethod(run, 'AddText', '写入文本默认值');
|
requireMethod(control, 'RemoveAllElements', '写入文本默认值');
|
requireMethod(control, 'AddElement', '写入文本默认值');
|
requireSuccess(run.AddText!(spec.value), '写入文本默认值');
|
control.RemoveAllElements!();
|
requireSuccess(control.AddElement!(run, 0), '写入文本默认值');
|
const range = control.GetRange!();
|
if (originalTextPr) {
|
requireMethod(range, 'SetTextPr', '保留文本格式');
|
if (!range.SetTextPr!(originalTextPr)) {
|
throw new Error('保留文本格式失败');
|
}
|
}
|
requireMethod(range, 'GetText', '回读文本默认值');
|
if (range.GetText!() !== spec.value) {
|
throw new Error('文本默认值回读不一致');
|
}
|
|
return JSON.stringify({ ok: true });
|
} catch (error: unknown) {
|
return JSON.stringify({
|
ok: false,
|
error: error && (error as { message?: unknown }).message ? (error as { message: unknown }).message : String(error),
|
});
|
}
|
}
|