Files
par/web/src/views/Sites.vue

122 lines
5.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div style="display:flex;flex-direction:column;height:calc(100vh - 80px)">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px">
<div style="display:flex;align-items:center;gap:12px">
<h2 style="margin:0">站点列表</h2>
<el-badge v-if="pendingCount" :value="pendingCount" type="warning">
<el-button size="small" @click="$router.push('/sites/review')">变更审核</el-button>
</el-badge>
</div>
<div style="display:flex;gap:8px">
<el-button size="small" @click="refresh" :loading="loading">刷新</el-button>
<el-button size="small" @click="newSite">新建</el-button>
<el-button size="small" type="primary" @click="saveSite" :loading="saving" v-if="editSiteId">保存</el-button>
</div>
</div>
<div style="display:flex;gap:12px;flex:1;min-height:0">
<!-- 左侧:编辑器(当前选中站点) -->
<div style="flex:0 0 420px;display:flex;flex-direction:column;min-height:0">
<div style="font-size:13px;font-weight:500;margin-bottom:4px;display:flex;justify-content:space-between;align-items:center">
<span>{{ editSiteId ? '编辑: '+editSiteId : '选择站点编辑' }}</span>
</div>
<div style="flex:1;min-height:0;border-radius:4px;overflow:hidden">
<CodeEditor v-model="editorJson" language="json" />
</div>
</div>
<!-- 右侧:所有站点可视化 -->
<div style="flex:1;overflow:auto;min-height:0">
<el-table :data="sites" stripe v-loading="loading" border empty-text="暂无站点"
style="font-size:13px" :row-style="{height:'44px'}" @row-click="editSite" highlight-current-row
:row-class-name="rowClass">
<el-table-column prop="siteId" label="站点ID" width="110" />
<el-table-column label="名称" min-width="130">
<template #default="s">{{ (s.row.names||[]).join(' / ') || '-' }}</template>
</el-table-column>
<el-table-column label="地址" min-width="180" show-overflow-tooltip>
<template #default="s">{{ (s.row.urls||[]).join(' / ') }}</template>
</el-table-column>
<el-table-column prop="siteType" label="类型" width="100" />
<el-table-column label="状态" width="80">
<template #default="s">
<el-tag size="small" :type="s.row.status==='active'?'success':'info'">{{ s.row.status||'active' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="适配" width="90">
<template #default="s">
<el-tag v-if="s.row.latestVersion" size="small" type="primary">v{{ s.row.latestVersion }}</el-tag>
<span v-else style="color:#909399">-</span>
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template #default="s">
<el-button size="small" @click.stop="editSite(s.row)">编辑</el-button>
<el-button size="small" type="danger" text @click.stop="deleteSite(s.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script setup>
import api from '../api'
const loading = ref(false), saving = ref(false), pendingCount = ref(0)
const sites = ref([]), editSiteId = ref(''), editorJson = ref('{}')
const rowClass = ({row}) => row.siteId === editSiteId.value ? 'current-row' : ''
const refresh = async () => {
loading.value = true
try {
const r = await api.raw.get('/admin/sites')
sites.value = Array.isArray(r?.data) ? r.data : r || []
try { pendingCount.value = ((await api.sites.pendingChanges()).data || []).length } catch { pendingCount.value = 0 }
} catch { ElMessage.error('加载失败') }
finally { loading.value = false }
}
const editSite = (row) => {
editSiteId.value = row.siteId
editorJson.value = JSON.stringify({siteId: row.siteId, names: row.names, urls: row.urls, siteType: row.siteType, status: row.status||'active'}, null, 2)
}
const newSite = () => {
editSiteId.value = ''
editorJson.value = JSON.stringify({siteId:'',names:[''],urls:[''],siteType:'nexusphp',status:'active'}, null, 2)
}
const deleteSite = async (row) => {
try { await ElMessageBox.confirm('确认删除 '+row.siteId+' ?','删除',{type:'warning'}) } catch { return }
try {
await api.raw.put('/admin/sites/'+row.siteId, {siteId:row.siteId,names:row.names,urls:row.urls,siteType:row.siteType,status:'deprecated'})
ElMessage.success('已弃用')
refresh()
if (editSiteId.value === row.siteId) editSiteId.value = ''
} catch { ElMessage.error('操作失败') }
}
const saveSite = async () => {
saving.value = true
try {
const site = JSON.parse(editorJson.value)
if (!site.siteId) { ElMessage.warning('siteId不能为空'); return }
await api.raw.put('/admin/sites/'+site.siteId, {
names: site.names||[], urls: site.urls||[], siteType: site.siteType||'unknown', status: site.status||'active',
})
ElMessage.success('已保存')
refresh()
} catch { ElMessage.error('保存失败') }
finally { saving.value = false }
}
onMounted(refresh)
</script>
<style scoped>
:deep(.current-row) { background-color: #ecf5ff !important }
</style>