diff --git a/tenant-platform/src/api/system.ts b/tenant-platform/src/api/system.ts index 27c3322..0f62575 100644 --- a/tenant-platform/src/api/system.ts +++ b/tenant-platform/src/api/system.ts @@ -80,3 +80,64 @@ export function streamSystemUpdate(onLine: (line: string) => void, signal?: Abor export function streamSystemReset(onLine: (line: string) => void, signal?: AbortSignal) { return streamOperation('/system/reset', onLine, signal) } + +// ── Database Management (PRIVATE mode only) ────────────────────────────── + +export interface TableInfo { + name: string + comment: string +} + +export interface ColumnInfo { + name: string + type: string + size: number + nullable: boolean + comment: string +} + +export interface TableDataPage { + columns: string[] + rows: Record[] + total: number + totalPages: number + page: number + size: number +} + +async function authFetch(path: string): Promise { + const token = localStorage.getItem('token') ?? '' + const res = await fetch(`${BASE}${path}`, { + headers: { Authorization: `Bearer ${token}` }, + }) + if (!res.ok) { + const json = await res.json().catch(() => null) + throw new Error(json?.message ?? `HTTP ${res.status}`) + } + return res.json() +} + +export async function listDatabaseTables(): Promise { + const json = await authFetch('/system/database/tables') + return json.data as TableInfo[] +} + +export async function getTableColumns(tableName: string): Promise { + const json = await authFetch(`/system/database/tables/${encodeURIComponent(tableName)}/columns`) + return json.data as ColumnInfo[] +} + +export async function getTableData( + tableName: string, + params: { page?: number; size?: number; keyword?: string; sortColumn?: string; sortDirection?: string }, +): Promise { + const query = new URLSearchParams() + if (params.page != null) query.set('page', String(params.page)) + if (params.size != null) query.set('size', String(params.size)) + if (params.keyword) query.set('keyword', params.keyword) + if (params.sortColumn) query.set('sortColumn', params.sortColumn) + if (params.sortDirection) query.set('sortDirection', params.sortDirection) + const qs = query.toString() + const json = await authFetch(`/system/database/tables/${encodeURIComponent(tableName)}/data${qs ? '?' + qs : ''}`) + return json.data as TableDataPage +} diff --git a/tenant-platform/src/router/index.ts b/tenant-platform/src/router/index.ts index 2f0022e..6b62328 100644 --- a/tenant-platform/src/router/index.ts +++ b/tenant-platform/src/router/index.ts @@ -105,6 +105,10 @@ const router = createRouter({ path: 'system-logs', component: () => import('@/views/system/ServerLogsView.vue'), }, + { + path: 'database', + component: () => import('@/views/database/DatabaseView.vue'), + }, { path: 'accounts', component: () => import('@/views/accounts/SubAccountView.vue'), diff --git a/tenant-platform/src/views/database/DatabaseView.vue b/tenant-platform/src/views/database/DatabaseView.vue new file mode 100644 index 0000000..ba4a932 --- /dev/null +++ b/tenant-platform/src/views/database/DatabaseView.vue @@ -0,0 +1,355 @@ + + + + + diff --git a/tenant-platform/src/views/layout/MainLayout.vue b/tenant-platform/src/views/layout/MainLayout.vue index 5067b4a..79c1f52 100644 --- a/tenant-platform/src/views/layout/MainLayout.vue +++ b/tenant-platform/src/views/layout/MainLayout.vue @@ -24,6 +24,7 @@ 安全中心 服务日志 + 数据库管理 操作日志 子账号管理 @@ -60,6 +61,7 @@ 安全中心 服务日志 + 数据库管理 操作日志 子账号管理 @@ -108,7 +110,7 @@ import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue' import { useAuthStore } from '@/stores/auth' import { useRoute, useRouter } from 'vue-router' -import { Bell, ChatDotRound, Document, Grid, Key, List, Lock, Menu, Monitor, Odometer, Upload, User } from '@element-plus/icons-vue' +import { Bell, ChatDotRound, Coin, Document, Grid, Key, List, Lock, Menu, Monitor, Odometer, Upload, User } from '@element-plus/icons-vue' import { getDeploymentStatus } from '@/api/system' const auth = useAuthStore()