diff --git a/mayfly_go_web/src/views/ops/db/DbEdit.vue b/mayfly_go_web/src/views/ops/db/DbEdit.vue index aa67b2bc..95a56889 100644 --- a/mayfly_go_web/src/views/ops/db/DbEdit.vue +++ b/mayfly_go_web/src/views/ops/db/DbEdit.vue @@ -292,10 +292,7 @@ export default defineComponent({ emit('cancel'); setTimeout(() => { resetInputDb(); - dbForm.value.resetFields(); - // 重置对象属性为null - state.form = {} as any; - }, 200); + }, 500); }; return { diff --git a/mayfly_go_web/src/views/ops/db/DbList.vue b/mayfly_go_web/src/views/ops/db/DbList.vue index 5fb7b658..9871f270 100644 --- a/mayfly_go_web/src/views/ops/db/DbList.vue +++ b/mayfly_go_web/src/views/ops/db/DbList.vue @@ -59,8 +59,11 @@ - + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ @@ -195,7 +246,18 @@ export default defineComponent({ }, datas: [], total: 0, - + // sql执行记录弹框 + sqlExecLogDialog: { + title: '', + visible: false, + data: [], + total: 0, + query: { + dbId: 0, + pageNum: 1, + pageSize: 12, + }, + }, chooseTableName: '', tableInfoDialog: { visible: false, @@ -284,6 +346,32 @@ export default defineComponent({ } catch (err) {} }; + const onShowSqlExec = async (row: any) => { + state.sqlExecLogDialog.title = `${row.name}[${row.host}:${row.port}]`; + state.sqlExecLogDialog.query.dbId = row.id; + searchSqlExecLog(); + state.sqlExecLogDialog.visible = true; + }; + + const onBeforeCloseSqlExecDialog = () => { + state.sqlExecLogDialog.visible = false; + state.sqlExecLogDialog.data = []; + state.sqlExecLogDialog.total = 0; + state.sqlExecLogDialog.query.dbId = 0; + state.sqlExecLogDialog.query.pageNum = 1; + }; + + const searchSqlExecLog = async () => { + const res = await dbApi.getSqlExecs.request(state.sqlExecLogDialog.query); + state.sqlExecLogDialog.data = res.list; + state.sqlExecLogDialog.total = res.total; + }; + + const handleSqlExecPageChange = (curPage: number) => { + state.sqlExecLogDialog.query.pageNum = curPage; + searchSqlExecLog(); + }; + const showTableInfo = async (row: any, db: string) => { state.tableInfoDialog.infos = await dbApi.tableInfos.request({ id: row.id, db }); state.dbId = row.id; @@ -360,6 +448,10 @@ export default defineComponent({ editDb, valChange, deleteDb, + onShowSqlExec, + onBeforeCloseSqlExecDialog, + handleSqlExecPageChange, + searchSqlExecLog, showTableInfo, closeTableInfo, showColumns, diff --git a/mayfly_go_web/src/views/ops/db/SqlExec.vue b/mayfly_go_web/src/views/ops/db/SqlExec.vue index eee6c4a8..a7a18595 100644 --- a/mayfly_go_web/src/views/ops/db/SqlExec.vue +++ b/mayfly_go_web/src/views/ops/db/SqlExec.vue @@ -239,7 +239,6 @@ import 'codemirror/theme/base16-light.css'; import 'codemirror/addon/selection/active-line'; import _CodeMirror from 'codemirror'; -// import 'codemirror/mode/sql/sql.js'; import 'codemirror/addon/hint/show-hint.js'; import 'codemirror/addon/hint/sql-hint.js'; @@ -390,7 +389,44 @@ export default defineComponent({ let sql = getSql(); isTrue(sql && sql.trim(), '请选中需要执行的sql'); - state.queryTab.loading = true; + // 去除字符串前的空格、换行等 + sql = sql.replace(/(^\s*)/g, ''); + let execRemark = ''; + let canRun = true; + if ( + sql.startsWith('update') || + sql.startsWith('UPDATE') || + sql.startsWith('INSERT') || + sql.startsWith('insert') || + sql.startsWith('DELETE') || + sql.startsWith('delete') + ) { + const res: any = await ElMessageBox.prompt('请输入备注', 'Tip', { + confirmButtonText: '确定', + cancelButtonText: '取消', + inputPattern: /^[\s\S]*.*[^\s][\s\S]*$/, + inputErrorMessage: '请输入执行该sql的备注信息', + }); + execRemark = res.value; + if (!execRemark) { + canRun = false; + } + } + if (!canRun) { + return; + } + + try { + state.queryTab.loading = true; + const colAndData: any = await runSql(sql, execRemark); + state.queryTab.execRes.data = colAndData.res; + state.queryTab.execRes.tableColumn = colAndData.colNames; + state.queryTab.loading = false; + } catch (e: any) { + state.queryTab.loading = false; + } + closeExecBtns(); + // 即只有以该字符串开头的sql才可修改表数据内容 if (sql.startsWith('SELECT *') || sql.startsWith('select *') || sql.startsWith('SELECT\n *')) { state.queryTab.selectionDatas = []; @@ -407,16 +443,6 @@ export default defineComponent({ state.queryTab.nowTableName = ''; state.nowTableName = ''; } - - try { - const colAndData: any = await runSql(sql); - state.queryTab.execRes.data = colAndData.res; - state.queryTab.execRes.tableColumn = colAndData.colNames; - state.queryTab.loading = false; - } catch (e: any) { - state.queryTab.loading = false; - } - closeExecBtns(); }; /** @@ -424,12 +450,40 @@ export default defineComponent({ * * @param sql 执行的sql */ - const runSql = (sql: string) => { - return dbApi.sqlExec.request({ + const runSql = async (sql: string, remark: string = '') => { + return await dbApi.sqlExec.request({ id: state.dbId, db: state.db, sql: sql.trim(), + remark, }); + // const sqlTrim = sql.trim(); + // let remark = ''; + // let canRun = true; + // const needRemark = ['update', 'UPDATE', 'delete', 'DELETE', 'INSERT', 'insert'].indexOf(sqlTrim.split(' ')[0]); + // if (needRemark) { + // const res: any = await ElMessageBox.prompt('请输入备注', 'Tip', { + // confirmButtonText: '确定', + // cancelButtonText: '取消', + // }); + // remark = res.value; + // if (!remark) { + // canRun = false; + // } + // } + + // if (!canRun) { + // return; + // } + // try { + // state.queryTab.loading = true; + // return await dbApi.sqlExec.request({ + // id: state.dbId, + // db: state.db, + // sql: sqlTrim, + // remark, + // }); + // } catch (e: any) {} }; const removeDataTab = (targetName: string) => { @@ -497,8 +551,9 @@ export default defineComponent({ if (flag === 'equal') { // 获取该列中第一个不为空的数据(内容) for (let i = 0; i < tableData.length; i++) { - if (tableData[i][str].length > 0) { - columnContent = tableData[i][str]; + // 转为字符串后比较 + if ((tableData[i][str] + '').length > 0) { + columnContent = tableData[i][str] + ''; break; } } @@ -515,7 +570,7 @@ export default defineComponent({ index = i; } } - columnContent = tableData[index][str]; + columnContent = tableData[index][str] + ''; } const contentWidth: number = getContentWidth(columnContent); // 获取列名称的长度 加上排序图标长度 @@ -899,7 +954,8 @@ export default defineComponent({ if (!state.nowTableName || !property) { return; } - let text = row[property]; + // 转为字符串比较,可能存在数字等 + let text = row[property] + ''; let div = cell.children[0]; if (div) { let input = document.createElement('input'); diff --git a/mayfly_go_web/src/views/ops/db/api.ts b/mayfly_go_web/src/views/ops/db/api.ts index 3c7173a3..ffe31bc7 100644 --- a/mayfly_go_web/src/views/ops/db/api.ts +++ b/mayfly_go_web/src/views/ops/db/api.ts @@ -12,7 +12,7 @@ export const dbApi = { columnMetadata: Api.create("/dbs/{id}/c-metadata", 'get'), // 获取表即列提示 hintTables: Api.create("/dbs/{id}/hint-tables", 'get'), - sqlExec: Api.create("/dbs/{id}/exec-sql", 'get'), + sqlExec: Api.create("/dbs/{id}/exec-sql", 'post'), // 保存sql saveSql: Api.create("/dbs/{id}/sql", 'post'), // 获取保存的sql @@ -20,4 +20,6 @@ export const dbApi = { // 获取保存的sql names getSqlNames: Api.create("/dbs/{id}/sql-names", 'get'), deleteDbSql: Api.create("/dbs/{id}/sql", 'delete'), + // 获取数据库sql执行记录 + getSqlExecs: Api.create("/dbs/{id}/sql-execs", 'get'), } \ No newline at end of file diff --git a/mayfly_go_web/src/views/ops/db/component/SqlExecDialog.vue b/mayfly_go_web/src/views/ops/db/component/SqlExecDialog.vue index 0bb39e91..c00b3ea2 100644 --- a/mayfly_go_web/src/views/ops/db/component/SqlExecDialog.vue +++ b/mayfly_go_web/src/views/ops/db/component/SqlExecDialog.vue @@ -1,6 +1,7 @@