feat: 配置审核页增加查看详情(语法高亮JSON)
This commit is contained in:
@@ -39,6 +39,7 @@ export default {
|
||||
configs: {
|
||||
list: () => api.get('/configs'),
|
||||
pending: () => api.get('/configs/pending'),
|
||||
download: (siteId, version) => api.get(`/configs/${siteId}/${version}`, { responseType: 'text' }),
|
||||
approve: (id, comment) => api.post(`/admin/reviews/${id}/approve`, null, { params: { comment } }),
|
||||
reject: (id, comment) => api.post(`/admin/reviews/${id}/reject`, null, { params: { comment } })
|
||||
},
|
||||
|
||||
@@ -11,14 +11,29 @@
|
||||
<el-table-column prop="schemaVersion" label="Schema" width="100" />
|
||||
<el-table-column prop="submitterId" label="提交者" width="100" />
|
||||
<el-table-column prop="createdAt" label="提交时间" width="180" />
|
||||
<el-table-column label="操作" width="200">
|
||||
<el-table-column label="操作" width="280">
|
||||
<template #default="scope">
|
||||
<el-button size="small" type="primary" @click="handleView(scope.row)">查看</el-button>
|
||||
<el-button size="small" type="success" @click="handleApprove(scope.row)">通过</el-button>
|
||||
<el-button size="small" type="danger" @click="handleReject(scope.row)">拒绝</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="viewVisible" title="配置详情" width="700px" :close-on-click-modal="false">
|
||||
<div class="config-info">
|
||||
<span class="label">站点:</span> {{ viewing.siteId }}
|
||||
<span class="label">版本:</span> {{ viewing.version }}
|
||||
<span class="label">提交者:</span> {{ viewing.submitterId || '-' }}
|
||||
</div>
|
||||
<div style="margin-top: 12px; max-height: 500px; overflow: auto">
|
||||
<pre class="config-json" v-html="highlightedJson"></pre>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="viewVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -27,6 +42,9 @@ import api from '../api'
|
||||
|
||||
const pendingConfigs = ref([])
|
||||
const loading = ref(false)
|
||||
const viewVisible = ref(false)
|
||||
const viewing = ref({})
|
||||
const configContent = ref('')
|
||||
|
||||
const fetchPending = async () => {
|
||||
loading.value = true
|
||||
@@ -40,6 +58,48 @@ const fetchPending = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleView = async (row) => {
|
||||
viewing.value = row
|
||||
configContent.value = ''
|
||||
viewVisible.value = true
|
||||
try {
|
||||
const res = await api.configs.download(row.siteId, row.version)
|
||||
configContent.value = typeof res === 'string' ? res : JSON.stringify(res, null, 2)
|
||||
} catch {
|
||||
configContent.value = '(加载失败)'
|
||||
}
|
||||
}
|
||||
|
||||
const highlightedJson = computed(() => {
|
||||
try {
|
||||
const obj = JSON.parse(configContent.value)
|
||||
return syntaxHighlight(JSON.stringify(obj, null, 2))
|
||||
} catch {
|
||||
return escapeHtml(configContent.value)
|
||||
}
|
||||
})
|
||||
|
||||
const syntaxHighlight = (json) => {
|
||||
return escapeHtml(json).replace(
|
||||
/("(\\u[a-fA-F0-9]{4}|\\[^u]|[^"\\])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
|
||||
(match) => {
|
||||
let cls = 'number'
|
||||
if (/^"/.test(match)) {
|
||||
cls = /:$/.test(match) ? 'key' : 'string'
|
||||
} else if (/true|false/.test(match)) {
|
||||
cls = 'boolean'
|
||||
} else if (/null/.test(match)) {
|
||||
cls = 'null'
|
||||
}
|
||||
return `<span class="${cls}">${match}</span>`
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const escapeHtml = (str) => {
|
||||
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
}
|
||||
|
||||
const handleApprove = async (row) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确认通过站点 ${row.siteId} 的配置版本 ${row.version}?`, '提示')
|
||||
@@ -68,3 +128,30 @@ const handleReject = async (row) => {
|
||||
|
||||
onMounted(fetchPending)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.config-info {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
.config-info .label {
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
.config-json {
|
||||
background: #1e1e1e;
|
||||
color: #d4d4d4;
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
.config-json :deep(.key) { color: #9cdcfe; }
|
||||
.config-json :deep(.string) { color: #ce9178; }
|
||||
.config-json :deep(.number) { color: #b5cea8; }
|
||||
.config-json :deep(.boolean) { color: #569cd6; }
|
||||
.config-json :deep(.null) { color: #569cd6; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user