import { normalizeText, readConfigJson, resolveRuleTemplateLabel } from './auditViewModel.js' export function incrementVersion(version) { const normalized = normalizeText(version).replace(/^v/i, '') const match = normalized.match(/^(\d+)\.(\d+)\.(\d+)$/) if (!match) { return 'v1.0.0' } const major = Number(match[1]) const minor = Number(match[2]) const patch = Number(match[3]) + 1 return `v${major}.${minor}.${patch}` } export function buildReviewNote(status) { if (status === 'approved') { return '通过任务规则中心审核。' } if (status === 'rejected') { return '在任务规则中心驳回当前版本。' } return '提交任务规则中心待审核。' } export function buildRuleConfigPayload(asset, runtimeRule) { const configJson = { ...readConfigJson(asset), runtime_kind: normalizeText(runtimeRule?.kind) || asset.runtimeKind || 'policy_rule_draft', runtime_rule: runtimeRule } const templateKey = normalizeText(runtimeRule?.template_key) || asset.ruleTemplateKey if (templateKey) { configJson.rule_template_key = templateKey configJson.rule_template_label = resolveRuleTemplateLabel(templateKey) } return configJson } export function buildSpreadsheetChangeRecordKey(records = []) { const latest = records.find((item) => item?.changed_at) if (!latest) { return '' } const previewSignature = Array.isArray(latest.cell_changes) ? latest.cell_changes .slice(0, 8) .map((item) => [ item?.sheet_name, item?.cell, item?.change_type, item?.before_value, item?.after_value ] .map((value) => normalizeText(value)) .join(':') ) .join('|') : '' const sheetSignature = Array.isArray(latest.sheet_changes) ? latest.sheet_changes .map((item) => [item?.sheet_name, item?.change_type] .map((value) => normalizeText(value)) .join(':') ) .join('|') : '' return [ latest.id, latest.changed_at, latest.actor, latest.summary, latest.changed_sheet_count, latest.changed_cell_count, sheetSignature, previewSignature ] .map((value) => normalizeText(value)) .join('-') } export function filterAuditAssets(assets = [], filters = {}) { const normalizedKeyword = normalizeText(filters.keyword).toLowerCase() return assets.filter((item) => { const matchesKeyword = normalizedKeyword ? [item.name, item.code, item.summary, item.owner, item.scope] .filter(Boolean) .some((value) => String(value).toLowerCase().includes(normalizedKeyword)) : true const matchesDomain = filters.selectedDomain ? item.domainValue === filters.selectedDomain : true const matchesOwner = filters.selectedOwner ? item.owner === filters.selectedOwner : true const matchesStatus = filters.showStatusFilter ? filters.selectedStatus ? item.statusValue === filters.selectedStatus : true : true const matchesRiskScenario = filters.showRiskScenarioFilter ? filters.selectedRiskScenario ? item.riskCategory === filters.selectedRiskScenario : true : true return matchesKeyword && matchesDomain && matchesOwner && matchesStatus && matchesRiskScenario }) }