import type { TemplateBinding, TemplateCheckboxGroup } from './types';
|
|
export interface CheckboxGroupSummary {
|
anomalies: string[];
|
code: string;
|
members: TemplateBinding[];
|
scopes: string[];
|
}
|
|
interface CheckboxGroupScope {
|
repeatGroupCode?: null | string;
|
stepId?: null | string;
|
}
|
|
function liveBinding(binding: TemplateBinding): boolean {
|
return binding.status === 'ACTIVE' || binding.status === 'PENDING';
|
}
|
|
function eligibleMember(binding: TemplateBinding): boolean {
|
return (
|
(binding.controlRole === 'PRIMARY' || binding.controlRole === 'REPEAT') &&
|
binding.controlType === 'CHECKBOX' &&
|
!binding.readOnly
|
);
|
}
|
|
function scopeKey(binding: CheckboxGroupScope): string {
|
return binding.repeatGroupCode ? `repeat:${binding.repeatGroupCode}` : `step:${binding.stepId || ''}`;
|
}
|
|
function scopeLabel(binding: CheckboxGroupScope): string {
|
return binding.repeatGroupCode ? `重复组:${binding.repeatGroupCode}` : `步骤:${binding.stepId || '未设置'}`;
|
}
|
|
function defaultChecked(binding: TemplateBinding): boolean {
|
return binding.controlConfig?.defaultChecked === true;
|
}
|
|
export function checkboxGroupCodeValid(code: string): boolean {
|
return /^[\w-]{1,80}$/u.test(code.trim());
|
}
|
|
export function summarizeCheckboxGroups(
|
bindings: TemplateBinding[],
|
configuredGroups: TemplateCheckboxGroup[] = [],
|
): CheckboxGroupSummary[] {
|
const groups = new Map<string, TemplateBinding[]>();
|
const rules = new Map(configuredGroups.map((group) => [group.groupCode, group]));
|
for (const binding of bindings) {
|
const code = binding.checkboxGroupCode?.trim();
|
if (!liveBinding(binding) || !code) continue;
|
groups.set(code, [...(groups.get(code) ?? []), binding]);
|
}
|
|
return [...groups.entries()]
|
.sort(([left], [right]) => left.localeCompare(right))
|
.map(([code, members]) => {
|
const anomalies: string[] = [];
|
const scopes = [...new Set(members.map(scopeKey))];
|
if (!checkboxGroupCodeValid(code)) anomalies.push('选择组编码格式无效');
|
if (members.some((member) => !eligibleMember(member))) anomalies.push('包含不允许入组的字段');
|
if (scopes.length > 1) anomalies.push('同一选择组跨越多个作用域');
|
if (members.length < 2) anomalies.push('只有一个成员,发布前需要补充同组复选框');
|
const rule = rules.get(code) ?? { maxSelected: 1, minSelected: 0 };
|
const defaultCount = members.filter(defaultChecked).length;
|
if (defaultCount < rule.minSelected || (rule.maxSelected !== null && defaultCount > rule.maxSelected)) {
|
anomalies.push('默认勾选数不符合数量规则');
|
}
|
return { anomalies, code, members, scopes: [...new Set(members.map(scopeLabel))] };
|
});
|
}
|
|
export function checkboxGroupOptions(
|
bindings: TemplateBinding[],
|
scope: CheckboxGroupScope,
|
): Array<{ label: string; value: string }> {
|
const targetScope = scopeKey(scope);
|
return summarizeCheckboxGroups(bindings)
|
.filter(
|
(group) =>
|
checkboxGroupCodeValid(group.code) &&
|
group.members.every(eligibleMember) &&
|
group.members.every((member) => scopeKey(member) === targetScope),
|
)
|
.map((group) => ({ label: `${group.code}(${group.members.length} 个成员)`, value: group.code }));
|
}
|