feat: 编辑器增加版本状态(预览版/正式版)和未保存提示

This commit is contained in:
mediabot-pt
2026-07-07 12:19:18 +08:00
parent 090fab8883
commit e99de15703
5 changed files with 192 additions and 12 deletions

View File

@@ -32,11 +32,18 @@
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;flex-shrink:0">
<div style="display:flex;align-items:center;gap:12px">
<h2 style="margin:0">编辑: {{ editSiteName }}</h2>
<!-- 快照状态 -->
<el-tag v-if="snapshotStatus" size="small" :type="snapshotStatus.hasPendingPublish ? 'warning' : snapshotStatus.draft.exists ? 'info' : 'success'">
{{ snapshotStatus.hasPendingPublish ? '预览版 v' + snapshotStatus.draft.version : snapshotStatus.draft.exists ? '预览版 v' + snapshotStatus.draft.version : snapshotStatus.published.exists ? '正式版 v' + snapshotStatus.published.version : '未发布' }}
</el-tag>
<el-tag v-if="hasUnsavedChanges" size="small" type="danger" effect="dark">未保存</el-tag>
<el-tag size="small" type="info">{{ parsed.length }} 条规则</el-tag>
</div>
<div style="display:flex;gap:8px">
<el-button size="small" type="primary" @click="saveRules" :loading="saving">保存</el-button>
<el-button size="small" @click="uploadRules" :loading="uploading">上传</el-button>
<el-button v-if="snapshotStatus" size="small" @click="savePreview" :loading="savingPreview">保存预览版</el-button>
<el-button v-if="snapshotStatus?.draft.exists" size="small" type="success" @click="publishSnapshot" :loading="publishing">发布正式版</el-button>
<el-button size="small" @click="editType=''">返回列表</el-button>
</div>
</div>
@@ -272,11 +279,18 @@ const presets = [
]
// ============ 状态 ============
const loading = ref(false), saving = ref(false), uploading = ref(false)
const loading = ref(false), saving = ref(false), uploading = ref(false), savingPreview = ref(false), publishing = ref(false)
const sites = ref([]), rulesMap = ref({})
const editType = ref(''), editorJson = ref('[]')
const editType = ref(''), editorJson = ref('[]'), originalJson = ref('')
const snapshotStatus = ref(null)
const dragIdx = ref(null)
const hasUnsavedChanges = computed(() => {
if (!editType.value) return false
try { return JSON.stringify(JSON.parse(editorJson.value)) !== JSON.stringify(JSON.parse(originalJson.value || '[]')) }
catch { return false }
})
const fmt = (t) => t ? (t.substring(0,19)||'').replace('T',' ') : '-'
const parsed = computed({
@@ -366,6 +380,27 @@ const editRule = async (row) => {
const r = await api.raw.get('/admin/risk-rules/'+row.siteId)
editorJson.value = (r?.data||r)?.rules ? JSON.stringify((r.data||r).rules, null, 2) : '[]'
} catch { editorJson.value = '[]' }
originalJson.value = editorJson.value
fetchSnapshotStatus()
}
const fetchSnapshotStatus = async () => {
try { snapshotStatus.value = (await api.raw.get('/admin/sites/' + editType.value + '/snapshot-status')).data || null }
catch { snapshotStatus.value = null }
}
const savePreview = async () => {
savingPreview.value = true
try { await api.raw.post('/admin/sites/' + editType.value + '/save-preview'); ElMessage.success('预览版已保存'); fetchSnapshotStatus() }
catch { ElMessage.error('保存预览版失败') }
finally { savingPreview.value = false }
}
const publishSnapshot = async () => {
publishing.value = true
try { await api.raw.post('/admin/sites/' + editType.value + '/publish'); ElMessage.success('已发布为正式版'); fetchSnapshotStatus() }
catch { ElMessage.error('发布失败') }
finally { publishing.value = false }
}
const sync = () => { editorJson.value = JSON.stringify(parsed.value, null, 2) }
@@ -429,6 +464,7 @@ const saveRules = async () => {
saving.value = true
try {
await api.raw.post('/risk-rules/'+editType.value, { rules: parsed.value })
originalJson.value = editorJson.value
ElMessage.success('已保存')
} catch { ElMessage.error('保存失败') }
finally { saving.value = false }