diff --git a/web/src/api/index.js b/web/src/api/index.js index 8b7dcaf..5155377 100644 --- a/web/src/api/index.js +++ b/web/src/api/index.js @@ -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 } }) }, diff --git a/web/src/views/Configs.vue b/web/src/views/Configs.vue index a563439..c50ef35 100644 --- a/web/src/views/Configs.vue +++ b/web/src/views/Configs.vue @@ -11,14 +11,29 @@ - + + + +
+ 站点: {{ viewing.siteId }}   + 版本: {{ viewing.version }}   + 提交者: {{ viewing.submitterId || '-' }} +
+
+

+      
+ +
@@ -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 `${match}` + } + ) +} + +const escapeHtml = (str) => { + return str.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) + +