import type { DraftField } from '../domain/draft';
|
import type { FieldConflict } from '../domain/conflict';
|
import type { FieldApplyResult, FillFieldValue, RepeatGroup, StepFillStructure } from '../domain/types';
|
|
import { defineStore } from 'pinia';
|
|
import { checkboxGroupTransition, checkboxGroupViolations } from '../domain/checkbox-group';
|
import { isReferenceTag } from '../domain/draft';
|
import { reconcileDocumentValue } from '../domain/conflict';
|
import { parseTag } from '../domain/tags';
|
|
function syncReferenceDrafts(fields: DraftField[], primaryTag: string, value: FillFieldValue) {
|
const primary = parseTag(primaryTag);
|
if (primary?.type !== 'single') return;
|
const prefix = `eln.ref.${primary.fieldCode}.`;
|
fields.filter((item) => item.tag.startsWith(prefix)).forEach((item) => {
|
item.draftValue = value;
|
});
|
}
|
|
export const useFillerStore = defineStore('filler', {
|
state: () => ({
|
status: 'initializing' as 'error' | 'initializing' | 'ready' | 'working',
|
conflicts: {} as Record<string, FieldConflict>,
|
checkboxGroupError: '',
|
checkboxGroupNotice: '',
|
fields: [] as DraftField[],
|
fieldErrors: {} as Record<string, string>,
|
formulaResultsStale: false,
|
focusedTag: null as null | string,
|
documentSyncError: '',
|
repeatError: '',
|
sourceSyncError: '',
|
repeatGroups: [] as RepeatGroup[],
|
stepStructure: undefined as StepFillStructure | undefined,
|
currentStepId: null as null | string,
|
message: '正在连接文档...',
|
}),
|
actions: {
|
setStepStructure(structure?: StepFillStructure) {
|
this.stepStructure = structure;
|
const steps = [...(structure?.configuration.steps ?? [])].sort((left, right) => left.order - right.order);
|
this.currentStepId = steps.some((step) => step.id === this.currentStepId)
|
? this.currentStepId
|
: (steps[0]?.id ?? null);
|
},
|
selectStep(stepId: string) {
|
if (this.stepStructure?.configuration.steps.some((step) => step.id === stepId)) {
|
this.currentStepId = stepId;
|
}
|
},
|
refreshCheckboxGroupError() {
|
const violation = checkboxGroupViolations(this.fields, this.stepStructure)[0];
|
if (!violation) this.checkboxGroupError = '';
|
else if (violation.kind === 'invalid') {
|
this.checkboxGroupError = `选择组“${violation.checkboxGroupCode}”数量规则无效`;
|
} else if (violation.kind === 'minimum') {
|
this.checkboxGroupError = `选择组“${violation.checkboxGroupCode}”至少选择 ${violation.minSelected} 项`;
|
} else {
|
this.checkboxGroupError = `选择组“${violation.checkboxGroupCode}”最多选择 ${violation.maxSelected} 项`;
|
}
|
},
|
setDraft(tag: string, value: FillFieldValue) {
|
if (isReferenceTag(tag)) return false;
|
const field = this.fields.find((item) => item.tag === tag);
|
if (!field || field.readOnly) return false;
|
const transition = checkboxGroupTransition(this.fields, field, value, this.stepStructure);
|
if (!transition.accepted) {
|
this.checkboxGroupNotice = transition.message ?? '';
|
return false;
|
}
|
this.checkboxGroupNotice = '';
|
const changes = transition.changes;
|
for (const change of changes) {
|
const changedField = this.fields.find((item) => item.tag === change.tag);
|
if (!changedField || changedField.readOnly || isReferenceTag(change.tag)) continue;
|
if (changedField.draftValue !== change.value) this.formulaResultsStale = true;
|
changedField.draftValue = change.value;
|
const conflict = this.conflicts[change.tag];
|
if (conflict) {
|
const reconciliation = reconcileDocumentValue(conflict.baseValue, change.value, conflict.documentValue);
|
if (reconciliation.conflict) this.conflicts[change.tag] = reconciliation.conflict;
|
else delete this.conflicts[change.tag];
|
}
|
syncReferenceDrafts(this.fields, change.tag, change.value);
|
}
|
this.refreshCheckboxGroupError();
|
return true;
|
},
|
syncDocumentField(tag: string, value: FillFieldValue) {
|
const field = this.fields.find((item) => item.tag === tag);
|
if (!field || (field.type === 'checkbox') !== (typeof value === 'boolean')) return;
|
if (field.documentValue !== value) this.formulaResultsStale = true;
|
if (isReferenceTag(tag)) {
|
field.currentValue = value;
|
field.documentValue = value;
|
delete this.conflicts[tag];
|
return;
|
}
|
const baseValue = this.conflicts[tag]?.baseValue ?? field.documentValue;
|
const reconciliation = reconcileDocumentValue(baseValue, field.draftValue, value);
|
field.currentValue = value;
|
field.documentValue = reconciliation.documentValue;
|
field.draftValue = reconciliation.draftValue;
|
if (reconciliation.conflict) this.conflicts[tag] = reconciliation.conflict;
|
else delete this.conflicts[tag];
|
if (!reconciliation.conflict) syncReferenceDrafts(this.fields, tag, reconciliation.draftValue);
|
this.refreshCheckboxGroupError();
|
},
|
resolveConflict(tag: string, resolution: 'document' | 'draft') {
|
const field = this.fields.find((item) => item.tag === tag);
|
const conflict = this.conflicts[tag];
|
if (!field || !conflict) return;
|
if (resolution === 'document') {
|
field.draftValue = conflict.documentValue;
|
syncReferenceDrafts(this.fields, tag, conflict.documentValue);
|
}
|
field.documentValue = conflict.documentValue;
|
delete this.conflicts[tag];
|
this.refreshCheckboxGroupError();
|
},
|
applyResults(results: FieldApplyResult[], options: { preserveExistingErrors?: boolean } = {}) {
|
if (!options.preserveExistingErrors) this.fieldErrors = {};
|
for (const result of results) {
|
const field = this.fields.find((item) => item.tag === result.tag);
|
if (!field) continue;
|
delete this.fieldErrors[result.tag];
|
if (result.ok) field.documentValue = field.draftValue;
|
else this.fieldErrors[result.tag] = result.error || '应用失败';
|
}
|
},
|
},
|
});
|