feat: 编辑器增加版本状态(预览版/正式版)和未保存提示
This commit is contained in:
@@ -43,10 +43,19 @@
|
||||
<!-- 编辑模式:全屏双栏 -->
|
||||
<div v-else style="display:flex;flex-direction:column;height:calc(100vh - 80px)">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px">
|
||||
<h2 style="margin:0">编辑: {{ editSiteId }}</h2>
|
||||
<div style="display:flex;align-items:center;gap:10px">
|
||||
<h2 style="margin:0">编辑: {{ editSiteId }}</h2>
|
||||
<!-- 快照状态(仅对非默认模板显示) -->
|
||||
<el-tag v-if="!isDefaultEditor && 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>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px">
|
||||
<el-button size="small" type="primary" @click="savePages" :loading="saving">保存</el-button>
|
||||
<el-button size="small" @click="uploadPages" :loading="uploading">上传</el-button>
|
||||
<el-button v-if="!isDefaultEditor && snapshotStatus" size="small" @click="savePreview" :loading="savingPreview">保存预览版</el-button>
|
||||
<el-button v-if="!isDefaultEditor && snapshotStatus?.draft.exists" size="small" type="success" @click="publishSnapshot" :loading="publishing">发布正式版</el-button>
|
||||
<el-button size="small" type="danger" @click="deletePages" :loading="deleting">删除</el-button>
|
||||
<el-button size="small" @click="editSiteId=''">返回列表</el-button>
|
||||
</div>
|
||||
@@ -113,8 +122,10 @@
|
||||
<script setup>
|
||||
import api from '../api'; import { Refresh } from '@element-plus/icons-vue'
|
||||
|
||||
const loading = ref(false), saving = ref(false), uploading = ref(false), deleting = ref(false), sites = ref([]), pagesMap = ref({}), sitesList = ref([])
|
||||
const editSiteId = ref(''), editorJson = ref('{}')
|
||||
const loading = ref(false), saving = ref(false), uploading = ref(false), deleting = ref(false), savingPreview = ref(false), publishing = ref(false)
|
||||
const sites = ref([]), pagesMap = ref({}), sitesList = ref([])
|
||||
const editSiteId = ref(''), editorJson = ref('{}'), originalJson = ref('')
|
||||
const snapshotStatus = ref(null)
|
||||
const authType = ref('NONE')
|
||||
const defaultTypes = ['nexusphp','mtorrent','gazelle','unit3d']
|
||||
const isDefaultEditor = computed(() => editSiteId.value.startsWith('default:'))
|
||||
@@ -122,6 +133,12 @@ const pageKeys = ref([])
|
||||
const verifying = ref({})
|
||||
const verifyResults = ref({})
|
||||
|
||||
const hasUnsavedChanges = computed(() => {
|
||||
if (!editSiteId.value) return false
|
||||
try { return JSON.stringify(JSON.parse(editorJson.value)) !== JSON.stringify(JSON.parse(originalJson.value || '{}')) }
|
||||
catch { return false }
|
||||
})
|
||||
|
||||
const loadPageKeys = async () => {
|
||||
try { const r = await api.raw.get('/admin/page-keys'); pageKeys.value = r?.data || r || [] }
|
||||
catch {}
|
||||
@@ -207,6 +224,27 @@ const editPage = async (row) => {
|
||||
authType.value = data?.authType || 'NONE'
|
||||
editorJson.value = JSON.stringify({ authType: authType.value, entries: data?.entries || [] }, null, 2)
|
||||
} catch { editorJson.value = JSON.stringify({ authType:'NONE', entries:[] }, null, 2) }
|
||||
originalJson.value = editorJson.value
|
||||
if (!row.siteId.startsWith('default:')) fetchSnapshotStatus()
|
||||
}
|
||||
|
||||
const fetchSnapshotStatus = async () => {
|
||||
try { snapshotStatus.value = (await api.raw.get('/admin/sites/' + editSiteId.value + '/snapshot-status')).data || null }
|
||||
catch { snapshotStatus.value = null }
|
||||
}
|
||||
|
||||
const savePreview = async () => {
|
||||
savingPreview.value = true
|
||||
try { await api.raw.post('/admin/sites/' + editSiteId.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/' + editSiteId.value + '/publish'); ElMessage.success('已发布为正式版'); fetchSnapshotStatus() }
|
||||
catch { ElMessage.error('发布失败') }
|
||||
finally { publishing.value = false }
|
||||
}
|
||||
|
||||
const remove = (idx) => { parsed.value.splice(idx,1); syncToJson() }
|
||||
@@ -240,6 +278,7 @@ const savePages = async () => {
|
||||
? '/admin/default-pages/' + editSiteId.value.replace('default:','')
|
||||
: '/sites/' + editSiteId.value + '/pages'
|
||||
await api.raw.put(url, { entries: parsed.value, authType: authType.value })
|
||||
originalJson.value = editorJson.value
|
||||
ElMessage.success('已保存'); editSiteId.value=''; fetchAll()
|
||||
} catch { ElMessage.error('保存失败') }
|
||||
finally { saving.value = false }
|
||||
|
||||
Reference in New Issue
Block a user