feat: 站点编辑右侧表单双向同步JSON编辑器

This commit is contained in:
mediabot-pt
2026-07-05 21:21:55 +08:00
parent 4d928ead51
commit 0c2bffab5c

View File

@@ -58,13 +58,30 @@
</div>
</div>
<div style="flex:1;overflow:auto;min-height:0">
<div style="font-size:13px;font-weight:500;margin-bottom:8px">预览</div>
<el-form label-width="70px" label-position="left" size="small">
<el-form-item label="站点ID"><span style="font-weight:500">{{ preview.siteId||'-' }}</span></el-form-item>
<el-form-item label="名称"><span>{{ (preview.names||[]).join(' / ') }}</span></el-form-item>
<el-form-item label="地址"><span>{{ (preview.urls||[]).join(' / ') }}</span></el-form-item>
<el-form-item label="类型"><el-tag size="small">{{ preview.siteType }}</el-tag></el-form-item>
<el-form-item label="状态"><el-tag size="small" :type="preview.status==='active'?'success':'info'">{{ preview.status }}</el-tag></el-form-item>
<div style="font-size:13px;font-weight:500;margin-bottom:8px;display:flex;gap:8px;align-items:center">
<span>表单编辑(双向同步)</span>
<el-tag v-if="jsonError" type="danger" size="small">JSON解析错误</el-tag>
</div>
<el-form v-if="!jsonError" label-width="80px" label-position="left" size="small">
<el-form-item label="站点ID">
<el-input v-model="form.siteId" @input="formToJson" />
</el-form-item>
<el-form-item label="名称">
<el-input v-model="form.namesStr" type="textarea" :rows="2" @input="formToJson" placeholder="一行一个" />
</el-form-item>
<el-form-item label="地址">
<el-input v-model="form.urlsStr" type="textarea" :rows="2" @input="formToJson" placeholder="一行一个" />
</el-form-item>
<el-form-item label="类型">
<el-select v-model="form.siteType" @change="formToJson" style="width:100%">
<el-option v-for="t in ['nexusphp','mtorrent','gazelle','unit3d','unknown']" :key="t" :label="t" :value="t" />
</el-select>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="form.status" @change="formToJson" style="width:100%">
<el-option label="活跃" value="active" /><el-option label="弃用" value="deprecated" />
</el-select>
</el-form-item>
</el-form>
</div>
</div>
@@ -75,8 +92,30 @@
import api from '../api'
const loading = ref(false), saving = ref(false), pendingCount = ref(0)
const sites = ref([]), editSiteId = ref(''), editorJson = ref('{}')
const preview = computed(() => { try { return JSON.parse(editorJson.value) } catch { return {} } })
const sites = ref([]), editSiteId = ref(''), editorJson = ref('{}'), jsonError = ref(false)
const form = reactive({ siteId:'', namesStr:'', urlsStr:'', siteType:'nexusphp', status:'active' })
let syncing = false
const jsonToForm = () => {
try { const s = JSON.parse(editorJson.value); form.siteId = s.siteId||''; form.namesStr = (s.names||[]).join('\n'); form.urlsStr = (s.urls||[]).join('\n'); form.siteType = s.siteType||'nexusphp'; form.status = s.status||'active'; jsonError.value = false }
catch { jsonError.value = true }
}
const formToJson = () => {
if (syncing) return; syncing = true
jsonError.value = false
editorJson.value = JSON.stringify({
siteId: form.siteId, names: (form.namesStr||'').split('\n').map(s=>s.trim()).filter(Boolean),
urls: (form.urlsStr||'').split('\n').map(s=>s.trim()).filter(Boolean),
siteType: form.siteType, status: form.status,
}, null, 2)
nextTick(() => { syncing = false })
}
const jsonToFormDebounced = null
watch(editorJson, () => { if (!syncing) jsonToForm() })
const refresh = async () => {
const refresh = async () => {
loading.value = true