feat(system): 添加系统版本查询和数据库迁移功能

- 移除 license-service 中 DeviceEntity 的 device_id 唯一约束注解
- 添加 /api/system/version 接口用于查询当前部署版本
- 实现数据库 schema 版本化迁移机制
- 添加自动执行数据库迁移的功能
- 在前端安全中心界面显示当前版本和迁移状态
- 优化配置文件修复逻辑和代码结构
这个提交包含在:
XuqmGroup 2026-05-22 23:04:36 +08:00
父节点 ee20767d57
当前提交 e999d4d443
共有 2 个文件被更改,包括 35 次插入3 次删除

查看文件

@ -43,6 +43,16 @@ async function streamOperation(
if (buf) onLine(buf)
}
export async function getSystemVersion(): Promise<{ currentVersion: string }> {
const token = localStorage.getItem('token') ?? ''
const res = await fetch(`${BASE}/system/version`, {
headers: { Authorization: `Bearer ${token}` },
})
if (!res.ok) throw new Error(`HTTP ${res.status}`)
const json = await res.json()
return json.data as { currentVersion: string }
}
export function streamSystemUpdate(onLine: (line: string) => void, signal?: AbortSignal) {
return streamOperation('/system/update', onLine, signal)
}

查看文件

@ -213,7 +213,15 @@
<div v-if="!updating && !updateDone && !updateError" style="color:#606266;">
<p v-if="operationType === 'update'">将拉取最新镜像并重建所有运行中的服务容器用于升级到新版本</p>
<p v-else>将用当前本地镜像重建所有运行中的服务容器无需下载新镜像适合修复异常服务</p>
<el-alert type="warning" :closable="false" show-icon style="margin-top:12px">
<el-descriptions v-if="operationType === 'update'" :column="1" border size="small" style="margin-top:12px;margin-bottom:12px">
<el-descriptions-item label="当前版本">
<el-skeleton v-if="versionLoading" :rows="1" animated style="width:160px" />
<el-tag v-else-if="currentVersion" type="info" size="small">{{ currentVersion }}</el-tag>
<span v-else style="color:#c0c4cc"></span>
</el-descriptions-item>
<el-descriptions-item label="数据库迁移">自动执行新版本启动时应用变更</el-descriptions-item>
</el-descriptions>
<el-alert type="warning" :closable="false" show-icon>
<template #title>tenant-service 重启时页面连接会短暂中断 1030 </template>
<template #default>操作完成后请刷新页面</template>
</el-alert>
@ -258,7 +266,7 @@ import { Loading } from '@element-plus/icons-vue'
import { accountApi } from '@/api/account'
import { appApi, type App } from '@/api/app'
import { migrateApi } from '@/api/migrate'
import { getDeploymentStatus, streamSystemUpdate, streamSystemReset } from '@/api/system'
import { getDeploymentStatus, getSystemVersion, streamSystemUpdate, streamSystemReset } from '@/api/system'
import { useAuthStore } from '@/stores/auth'
import { formatTime } from '@/utils/date'
@ -451,10 +459,23 @@ const updateError = ref('')
const selfRestarting = ref(false)
const updateLog = ref<string[]>([])
const logEl = ref<HTMLPreElement | null>(null)
const currentVersion = ref('')
const versionLoading = ref(false)
function openOperationDialog(type: 'update' | 'reset') {
async function openOperationDialog(type: 'update' | 'reset') {
operationType.value = type
showUpdateDialog.value = true
if (type === 'update' && !currentVersion.value) {
versionLoading.value = true
try {
const info = await getSystemVersion()
currentVersion.value = info.currentVersion
} catch {
currentVersion.value = ''
} finally {
versionLoading.value = false
}
}
}
function resetUpdateDialog() {
@ -463,6 +484,7 @@ function resetUpdateDialog() {
updateDone.value = false
updateError.value = ''
selfRestarting.value = false
currentVersion.value = ''
}
async function startOperation() {