diff --git a/web/src/views/Sites.vue b/web/src/views/Sites.vue
index 430a9a8..a09247d 100644
--- a/web/src/views/Sites.vue
+++ b/web/src/views/Sites.vue
@@ -58,13 +58,30 @@
-
预览
-
- {{ preview.siteId||'-' }}
- {{ (preview.names||[]).join(' / ') }}
- {{ (preview.urls||[]).join(' / ') }}
- {{ preview.siteType }}
- {{ preview.status }}
+
+ 表单编辑(双向同步)
+ JSON解析错误
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -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