数据
This commit is contained in:
94
src/utils.ts
94
src/utils.ts
@@ -155,9 +155,63 @@ export function applyRowVariableMapping(
|
||||
export const DEFAULT_EXPORT_RANGE: ExportRangeConfig = { mode: 'all' };
|
||||
|
||||
export const exportRangeEquals = (a: ExportRangeConfig, b: ExportRangeConfig) =>
|
||||
a.mode === b.mode &&
|
||||
(a.custom ?? '') === (b.custom ?? '') &&
|
||||
JSON.stringify(a.filterRules ?? []) === JSON.stringify(b.filterRules ?? []);
|
||||
a.mode === b.mode && (a.custom ?? '') === (b.custom ?? '');
|
||||
|
||||
/** 模板数据过滤规则(仅 variable 目标) */
|
||||
export function resolveDataFilterRules(
|
||||
template: Pick<LabelTemplate, 'dataFilterRules'>
|
||||
): VisibilityRule[] {
|
||||
return resolveVariableFilterRules(template.dataFilterRules);
|
||||
}
|
||||
|
||||
/** 按模板数据过滤条件筛选 0-based 行索引 */
|
||||
export function getDataFilteredIndices(
|
||||
rows: RecordRow[],
|
||||
template: Pick<LabelTemplate, 'dataFilterRules'>,
|
||||
variableDefaults?: Record<string, string> | null
|
||||
): number[] {
|
||||
const total = rows.length;
|
||||
if (total <= 0) return [];
|
||||
const rules = getActiveVisibilityRules(resolveDataFilterRules(template));
|
||||
if (rules.length === 0) return Array.from({ length: total }, (_, i) => i);
|
||||
return Array.from({ length: total }, (_, i) => i).filter((i) =>
|
||||
rowMatchesVariableFilterRules(rows[i], i, rules, variableDefaults)
|
||||
);
|
||||
}
|
||||
|
||||
/** 在候选行上应用排版过滤(奇偶/自定义序号,基于原始 1-based 行号) */
|
||||
export function getLayoutRangeIndices(
|
||||
candidateIndices: number[],
|
||||
totalRows: number,
|
||||
range: ExportRangeConfig
|
||||
): number[] {
|
||||
if (candidateIndices.length === 0) return [];
|
||||
switch (range.mode) {
|
||||
case 'odd':
|
||||
return candidateIndices.filter((i) => (i + 1) % 2 === 1);
|
||||
case 'even':
|
||||
return candidateIndices.filter((i) => (i + 1) % 2 === 0);
|
||||
case 'custom': {
|
||||
const parsed = parseCustomExportRange(range.custom ?? '', totalRows);
|
||||
const candidateSet = new Set(candidateIndices);
|
||||
return parsed.filter((i) => candidateSet.has(i));
|
||||
}
|
||||
case 'all':
|
||||
default:
|
||||
return candidateIndices;
|
||||
}
|
||||
}
|
||||
|
||||
/** 按数据过滤 + 排版过滤得到最终 0-based 行索引(保持升序) */
|
||||
export function getExportRangeIndices(
|
||||
rows: RecordRow[],
|
||||
range: ExportRangeConfig,
|
||||
template: Pick<LabelTemplate, 'dataFilterRules'>,
|
||||
variableDefaults?: Record<string, string> | null
|
||||
): number[] {
|
||||
const dataFiltered = getDataFilteredIndices(rows, template, variableDefaults);
|
||||
return getLayoutRangeIndices(dataFiltered, rows.length, range);
|
||||
}
|
||||
|
||||
export const DEFAULT_CUT_LINE_CONFIG: CutLineConfig = {
|
||||
enabled: true,
|
||||
@@ -247,34 +301,6 @@ export interface PrintableLabel {
|
||||
sourceIndex: number;
|
||||
}
|
||||
|
||||
/** 按导出范围筛选 0-based 行索引(保持升序) */
|
||||
export function getExportRangeIndices(
|
||||
rows: RecordRow[],
|
||||
range: ExportRangeConfig,
|
||||
variableDefaults?: Record<string, string> | null
|
||||
): number[] {
|
||||
const total = rows.length;
|
||||
if (total <= 0) return [];
|
||||
switch (range.mode) {
|
||||
case 'odd':
|
||||
return Array.from({ length: total }, (_, i) => i).filter((i) => (i + 1) % 2 === 1);
|
||||
case 'even':
|
||||
return Array.from({ length: total }, (_, i) => i).filter((i) => (i + 1) % 2 === 0);
|
||||
case 'custom':
|
||||
return parseCustomExportRange(range.custom ?? '', total);
|
||||
case 'conditional': {
|
||||
const rules = resolveVariableFilterRules(range.filterRules);
|
||||
if (rules.length === 0) return Array.from({ length: total }, (_, i) => i);
|
||||
return Array.from({ length: total }, (_, i) => i).filter((i) =>
|
||||
rowMatchesVariableFilterRules(rows[i], i, rules, variableDefaults)
|
||||
);
|
||||
}
|
||||
case 'all':
|
||||
default:
|
||||
return Array.from({ length: total }, (_, i) => i);
|
||||
}
|
||||
}
|
||||
|
||||
/** 解析自定义范围字符串(1-based 序号) */
|
||||
export function parseCustomExportRange(input: string, total: number): number[] {
|
||||
const trimmed = input.trim();
|
||||
@@ -300,13 +326,13 @@ export function parseCustomExportRange(input: string, total: number): number[] {
|
||||
export function buildPrintablePages(
|
||||
rows: RecordRow[],
|
||||
paper: PaperConfig,
|
||||
labelSize: { width: number; height: number },
|
||||
template: Pick<LabelTemplate, 'width' | 'height' | 'dataFilterRules'>,
|
||||
exportRange: ExportRangeConfig,
|
||||
variableDefaults?: Record<string, string> | null
|
||||
) {
|
||||
const gridInfo = calculateGrid(paper, labelSize);
|
||||
const gridInfo = calculateGrid(paper, template);
|
||||
const labelsPerPage = gridInfo.cols * gridInfo.rows;
|
||||
const indices = getExportRangeIndices(rows, exportRange, variableDefaults);
|
||||
const indices = getExportRangeIndices(rows, exportRange, template, variableDefaults);
|
||||
const selected: PrintableLabel[] = indices.map((i) => ({ row: rows[i], sourceIndex: i }));
|
||||
const totalPages = Math.ceil(selected.length / labelsPerPage) || 1;
|
||||
const pages: (PrintableLabel | null)[][] = [];
|
||||
|
||||
Reference in New Issue
Block a user