diff --git a/.gitignore b/.gitignore index fe77c27..d108ac1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules +docs/ .worktrees/ out/ logs/ diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 78db95a..e837947 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -18,6 +18,7 @@ import { EventSourcePolyfill } from 'event-source-polyfill' export interface CustomAxiosRequestConfig extends InternalAxiosRequestConfig { loading?: boolean + silentStatusError?: boolean } const config = { @@ -109,6 +110,10 @@ class RequestHttp { } // 全局错误信息拦截(防止下载文件的时候返回数据流,没有 code 直接报错) if (data.code && data.code !== ResultEnum.SUCCESS) { + if ((response.config as CustomAxiosRequestConfig).silentStatusError) { + return Promise.reject(data) + } + if (data.message.includes('&')) { let formattedMessage = data.message.split('&').join('
') if (data.message.includes(':')) { @@ -147,7 +152,9 @@ class RequestHttp { if (error.message.indexOf('timeout') !== -1) ElMessage.error('请求超时!请您稍后重试') if (error.message.indexOf('Network Error') !== -1) ElMessage.error('网络错误!请您稍后重试') // 根据服务器响应的错误状态码,做不同的处理 - if (response) checkStatus(response.status) + if (response && !(error.config as CustomAxiosRequestConfig | undefined)?.silentStatusError) { + checkStatus(response.status) + } // 服务器结果都没有返回(可能服务器错误可能客户端断网),断网处理:可以跳转到断网页面 if (!window.navigator.onLine) router.replace('/500') return Promise.reject(error) diff --git a/frontend/src/api/system/dbms/index.ts b/frontend/src/api/system/dbms/index.ts index 2551180..6e1953f 100644 --- a/frontend/src/api/system/dbms/index.ts +++ b/frontend/src/api/system/dbms/index.ts @@ -1,12 +1,13 @@ import http from '@/api' +import type { CustomAxiosRequestConfig } from '@/api' import type { Dbms } from '@/api/system/dbms/interface' export const getDbmsOverview = () => { return http.get('/database/overview', {}, { loading: false }) } -export const getDbmsConnectionList = (params: Dbms.ConnectionListParams) => { - return http.post('/database/connections/list', params, { loading: false }) +export const getDbmsConnectionList = (params: Dbms.ConnectionListParams, config: Partial = {}) => { + return http.post('/database/connections/list', params, { loading: false, ...config }) } export const addDbmsConnection = (params: Dbms.ConnectionPayload) => { @@ -25,24 +26,32 @@ export const testDbmsConnection = (params: Dbms.TestConnectionParams) => { return http.post('/database/connections/test', params) } -export const getDbmsTableList = (params: Dbms.TableListParams) => { - return http.post('/database/connections/tables', params) +export const getDbmsTableList = (params: Dbms.TableListParams, config: Partial = {}) => { + return http.post('/database/connections/tables', params, config) } export const createDbmsBackupTask = (params: Dbms.CreateBackupParams) => { return http.post('/database/backups/create', params) } -export const getDbmsBackupTaskList = (params: Dbms.TaskListParams) => { - return http.post('/database/backups/tasks/list', params, { loading: false }) +export const getDbmsBackupTaskList = (params: Dbms.TaskListParams, config: Partial = {}) => { + return http.post('/database/backups/tasks/list', params, { loading: false, ...config }) } export const getDbmsBackupTaskStatus = (taskId: string) => { return http.get('/database/backups/tasks/status', { taskId }, { loading: false }) } -export const getDbmsBackupFileList = (params: Dbms.FileListParams) => { - return http.post('/database/backups/files/list', params, { loading: false }) +export const stopDbmsBackupTask = (params: Dbms.StopBackupTaskParams) => { + return http.post('/database/backups/tasks/stop', params) +} + +export const restartDbmsBackupTask = (params: Dbms.RestartBackupTaskParams) => { + return http.post('/database/backups/tasks/restart', params) +} + +export const getDbmsBackupFileList = (params: Dbms.FileListParams, config: Partial = {}) => { + return http.post('/database/backups/files/list', params, { loading: false, ...config }) } export const createDbmsRestoreTask = (params: Dbms.CreateRestoreParams) => { @@ -53,6 +62,10 @@ export const getDbmsRestoreTaskStatus = (taskId: string) => { return http.get('/database/restores/tasks/status', { taskId }, { loading: false }) } +export const getDbmsRestoreTaskList = (params: Dbms.TaskListParams, config: Partial = {}) => { + return http.post('/database/restores/tasks/list', params, { loading: false, ...config }) +} + export const deleteDbmsBackupFile = (params: Dbms.DeleteBackupFileParams) => { return http.post('/database/delete/backup-file', params) } diff --git a/frontend/src/api/system/dbms/interface/index.ts b/frontend/src/api/system/dbms/interface/index.ts index 22cd20c..5de7d2e 100644 --- a/frontend/src/api/system/dbms/interface/index.ts +++ b/frontend/src/api/system/dbms/interface/index.ts @@ -29,9 +29,10 @@ export namespace Dbms { dbType: DbType host: string port: number - connectType: ConnectType + connectType?: ConnectType | null serviceName?: string | null sid?: string | null + databaseName?: string | null schemaName?: string | null username: string savePassword: 0 | 1 @@ -53,9 +54,10 @@ export namespace Dbms { dbType: DbType host: string port: number - connectType: ConnectType + connectType?: ConnectType | null serviceName?: string | null sid?: string | null + databaseName?: string | null schemaName?: string | null username: string password?: string | null @@ -90,6 +92,11 @@ export namespace Dbms { export interface TableRecord { owner: string tableName: string + autoIncrement?: number | string | null + updateTime?: string | null + dataLength?: number | string | null + engine?: string | null + tableRows?: number | string | null comments?: string | null } @@ -122,6 +129,15 @@ export namespace Dbms { taskStatus: TaskStatus } + export interface StopBackupTaskParams { + taskId: string + } + + export interface RestartBackupTaskParams { + taskId: string + temporaryPassword?: string + } + export interface TaskListParams extends ReqPage { connectionId?: string taskStatus?: TaskStatus | '' @@ -134,6 +150,7 @@ export namespace Dbms { dbType: DbType operationType: OperationType backupStrategy?: BackupStrategy | null + restoreMode?: RestoreMode | null taskStatus: TaskStatus schemaName?: string | null targetNamesJson?: string | null @@ -163,6 +180,7 @@ export namespace Dbms { backupMode?: BackupMode | null fileName: string filePath?: string | null + metadataFilePath?: string | null logFileName?: string | null logFilePath?: string | null fileSize?: number | null diff --git a/frontend/src/components/echarts/line/index.vue b/frontend/src/components/echarts/line/index.vue index 53b5bd0..3fda57b 100644 --- a/frontend/src/components/echarts/line/index.vue +++ b/frontend/src/components/echarts/line/index.vue @@ -138,7 +138,7 @@ const getSeriesTimeRange = () => { let maxTime = Number.NEGATIVE_INFINITY seriesList.forEach((series: { data?: unknown[] }) => { - ;(series.data || []).forEach(point => { + (series.data || []).forEach(point => { const timestamp = resolveTimeValue(point) if (timestamp === undefined) return diff --git a/frontend/src/routers/modules/check-dbms-route-contract.mjs b/frontend/src/routers/modules/check-dbms-route-contract.mjs index b98c05c..cdf5e19 100644 --- a/frontend/src/routers/modules/check-dbms-route-contract.mjs +++ b/frontend/src/routers/modules/check-dbms-route-contract.mjs @@ -15,6 +15,7 @@ const expectedPaths = [ '/systemMonitor/databaseMonitor/index', '/systemMonitor/database-monitor', '/systemMonitor/database-monitor/index', + '/system-ops/dbms/index', '/system-ops/database-monitor', '/system-ops/database-monitor/index' ] diff --git a/frontend/src/routers/modules/staticRouter.ts b/frontend/src/routers/modules/staticRouter.ts index 16783fd..e6cd8f4 100644 --- a/frontend/src/routers/modules/staticRouter.ts +++ b/frontend/src/routers/modules/staticRouter.ts @@ -208,6 +208,7 @@ export const staticRouter: RouteRecordRaw[] = [ '/systemMonitor/databaseMonitor/index', '/systemMonitor/database-monitor', '/systemMonitor/database-monitor/index', + '/system-ops/dbms/index', '/system-ops/database-monitor', '/system-ops/database-monitor/index' ], diff --git a/frontend/src/views/system-ops/dbms/components/DbmsConnectionDialog.vue b/frontend/src/views/system-ops/dbms/components/DbmsConnectionDialog.vue index 56befc7..b761520 100644 --- a/frontend/src/views/system-ops/dbms/components/DbmsConnectionDialog.vue +++ b/frontend/src/views/system-ops/dbms/components/DbmsConnectionDialog.vue @@ -25,7 +25,7 @@ - + @@ -39,20 +39,28 @@ - - - + - - - + @@ -114,9 +122,54 @@ const formRules: FormRules = { connectionName: [{ required: true, message: '请输入连接名称', trigger: 'blur' }], host: [{ required: true, message: '请输入主机地址', trigger: 'blur' }], port: [{ required: true, message: '请输入端口', trigger: 'blur' }], - connectType: [{ required: true, message: '请选择连接类型', trigger: 'change' }], - serviceName: [{ required: true, message: '请输入服务名', trigger: 'blur' }], - sid: [{ required: true, message: '请输入 SID', trigger: 'blur' }], + connectType: [ + { + validator: (_rule, value, callback) => { + if (selectedDbType.value === 'ORACLE' && !value) { + callback(new Error('请选择连接类型')) + return + } + callback() + }, + trigger: 'change' + } + ], + serviceName: [ + { + validator: (_rule, value, callback) => { + if (selectedDbType.value === 'ORACLE' && form.connectType === 'SERVICE_NAME' && !String(value || '').trim()) { + callback(new Error('请输入服务名')) + return + } + callback() + }, + trigger: 'blur' + } + ], + sid: [ + { + validator: (_rule, value, callback) => { + if (selectedDbType.value === 'ORACLE' && form.connectType === 'SID' && !String(value || '').trim()) { + callback(new Error('请输入 SID')) + return + } + callback() + }, + trigger: 'blur' + } + ], + databaseName: [ + { + validator: (_rule, value, callback) => { + if (selectedDbType.value === 'MYSQL' && !String(value || '').trim()) { + callback(new Error('请输入数据库名')) + return + } + callback() + }, + trigger: 'blur' + } + ], username: [{ required: true, message: '请输入用户名', trigger: 'blur' }] } @@ -133,7 +186,7 @@ const resetForm = () => { const open = (nextMode: 'add' | 'edit', record?: Dbms.ConnectionRecord, dbType: Dbms.DbType = 'ORACLE') => { mode.value = nextMode selectedDbType.value = record?.dbType || dbType - applyForm(createConnectionForm(record)) + applyForm(createConnectionForm(record, selectedDbType.value)) visible.value = true } diff --git a/frontend/src/views/system-ops/dbms/components/DbmsConnectionTree.vue b/frontend/src/views/system-ops/dbms/components/DbmsConnectionTree.vue index d705cf0..6026395 100644 --- a/frontend/src/views/system-ops/dbms/components/DbmsConnectionTree.vue +++ b/frontend/src/views/system-ops/dbms/components/DbmsConnectionTree.vue @@ -15,7 +15,7 @@
- +
@@ -31,7 +31,7 @@ @node-click="handleNodeClick" >