fix(agent): 修复规则中心表格版本和修改记录
补齐规则资产 JSON 读写接口和前端调用,修复 AuditView 导入缺失。 Excel 在线编辑改为比对所有页签并生成最近修改记录,版本快照统一保存到 rules/finance-rules/.versions。 隔离规则表测试存储,避免测试或旧入口写入真实规则目录与 storage/agent_assets。
This commit is contained in:
@@ -136,6 +136,18 @@ export function fetchAgentAssetVersionTimeline(assetId) {
|
||||
return apiRequest(`/agent-assets/${assetId}/version-timeline`)
|
||||
}
|
||||
|
||||
export function fetchAgentAssetRuleJson(assetId) {
|
||||
return apiRequest(`/agent-assets/${assetId}/rule-json`)
|
||||
}
|
||||
|
||||
export function saveAgentAssetRuleJson(assetId, payload, options = {}) {
|
||||
return apiRequest(`/agent-assets/${assetId}/rule-json`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
headers: buildWriteHeaders(options)
|
||||
})
|
||||
}
|
||||
|
||||
export function compareAgentAssetSpreadsheetVersions(assetId, baseVersion, targetVersion) {
|
||||
const query = new URLSearchParams({
|
||||
base_version: String(baseVersion || '').trim(),
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
<div v-if="selectedSpreadsheetChangeRecords.length" class="version-center-list">
|
||||
<button
|
||||
v-for="item in selectedSpreadsheetChangeRecords"
|
||||
:key="`spreadsheet-change-${item.changed_at}-${item.actor}`"
|
||||
:key="`spreadsheet-change-${item.id || item.changed_at}-${item.actor}`"
|
||||
type="button"
|
||||
class="version-center-item change-record-item"
|
||||
@click="openSpreadsheetChangeDetail(item)"
|
||||
@@ -175,9 +175,14 @@
|
||||
<strong>{{ item.actor }}</strong>
|
||||
<span>{{ item.time }}</span>
|
||||
</div>
|
||||
<b>{{ item.changed_cell_count }} 处改动</b>
|
||||
<b>{{ item.changeCountLabel }}</b>
|
||||
</div>
|
||||
<p>{{ item.summary }}</p>
|
||||
<small v-if="item.version">关联版本:{{ item.version }}</small>
|
||||
<small v-if="item.sheetPreview.length">
|
||||
涉及工作表:{{ item.sheetPreview.join('、') }}
|
||||
<template v-if="item.remainingSheetCount"> 等 {{ item.changedSheetNames.length }} 个</template>
|
||||
</small>
|
||||
<div v-if="item.previewChanges.length" class="change-record-preview">
|
||||
<span
|
||||
v-for="change in item.previewChanges"
|
||||
@@ -1124,6 +1129,10 @@
|
||||
<span>修改时间</span>
|
||||
<strong>{{ selectedSpreadsheetChangeRecord.time }}</strong>
|
||||
</article>
|
||||
<article v-if="selectedSpreadsheetChangeRecord.version">
|
||||
<span>关联版本</span>
|
||||
<strong>{{ selectedSpreadsheetChangeRecord.version }}</strong>
|
||||
</article>
|
||||
<article>
|
||||
<span>修改工作表</span>
|
||||
<strong>{{ selectedSpreadsheetChangeRecord.changed_sheet_count }}</strong>
|
||||
@@ -1154,7 +1163,7 @@
|
||||
{{ item.sheet_name }} · {{ item.meta.label }}
|
||||
</span>
|
||||
</div>
|
||||
<p v-else>本次没有新增或删除工作表。</p>
|
||||
<p v-else>本次没有工作表级变化。</p>
|
||||
</section>
|
||||
|
||||
<section class="compare-panel compare-cell-panel">
|
||||
|
||||
@@ -1695,12 +1695,30 @@ export default {
|
||||
}
|
||||
return (spreadsheetChangeRecordsByAsset.value[selectedSkill.value.id] || [])
|
||||
.filter((item) => item?.changed_at)
|
||||
.map((item) => ({
|
||||
...item,
|
||||
time: formatDateTime(item.changed_at),
|
||||
previewChanges: Array.isArray(item.cell_changes) ? item.cell_changes.slice(0, 3) : [],
|
||||
remainingChangeCount: Math.max((item.changed_cell_count || 0) - 3, 0)
|
||||
}))
|
||||
.map((item) => {
|
||||
const sheetNames = [
|
||||
...(Array.isArray(item.sheet_changes)
|
||||
? item.sheet_changes.map((change) => normalizeText(change.sheet_name))
|
||||
: []),
|
||||
...(Array.isArray(item.cell_changes)
|
||||
? item.cell_changes.map((change) => normalizeText(change.sheet_name))
|
||||
: [])
|
||||
].filter(Boolean)
|
||||
const changedSheetNames = [...new Set(sheetNames)]
|
||||
const previewChanges = Array.isArray(item.cell_changes) ? item.cell_changes.slice(0, 3) : []
|
||||
return {
|
||||
...item,
|
||||
time: formatDateTime(item.changed_at),
|
||||
changeCountLabel: item.changed_cell_count
|
||||
? `${item.changed_cell_count} 处改动`
|
||||
: `${item.changed_sheet_count || changedSheetNames.length || 0} 个工作表`,
|
||||
changedSheetNames,
|
||||
sheetPreview: changedSheetNames.slice(0, 4),
|
||||
remainingSheetCount: Math.max(changedSheetNames.length - 4, 0),
|
||||
previewChanges,
|
||||
remainingChangeCount: Math.max((item.changed_cell_count || 0) - previewChanges.length, 0)
|
||||
}
|
||||
})
|
||||
})
|
||||
const selectedSpreadsheetChangeSheetRows = computed(() =>
|
||||
Array.isArray(selectedSpreadsheetChangeRecord.value?.sheet_changes)
|
||||
@@ -2133,13 +2151,24 @@ export default {
|
||||
)
|
||||
.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.version,
|
||||
latest.summary,
|
||||
latest.changed_sheet_count,
|
||||
latest.changed_cell_count,
|
||||
sheetSignature,
|
||||
previewSignature
|
||||
]
|
||||
.map((value) => normalizeText(value))
|
||||
@@ -2538,7 +2567,21 @@ export default {
|
||||
loadSpreadsheetChangeRecords(assetId).catch(() => {})
|
||||
}
|
||||
if (selectedSkill.value.usesJsonRiskRule) {
|
||||
await loadRiskRuleJson(assetId)
|
||||
try {
|
||||
await loadRiskRuleJson(assetId)
|
||||
} catch (jsonError) {
|
||||
console.warn('Failed to load risk rule JSON:', jsonError)
|
||||
const jsonMessage =
|
||||
jsonError?.message || '风险规则 JSON 文件缺失或无法读取,请同步规则库后重试。'
|
||||
toast(jsonMessage)
|
||||
selectedSkill.value = {
|
||||
...selectedSkill.value,
|
||||
riskRuleJsonText: '{}',
|
||||
riskRuleDescription:
|
||||
selectedSkill.value.riskRuleDescription ||
|
||||
'规则 JSON 尚未就绪,请联系管理员执行平台风险规则同步。'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user