From 4afd5bbd5ebfe45ae306b981c5858a0f40819bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=97=E6=B4=8B?= Date: Tue, 22 Nov 2022 00:34:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9F=A5=E8=AF=A2=E7=BB=93=E6=9E=9C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=89=B9=E9=87=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- .../src/components/monaco/MonacoEditor.vue | 6 +- mayfly_go_web/src/views/ops/db/DbEdit.vue | 4 +- mayfly_go_web/src/views/ops/db/SqlExec.vue | 214 +++++++++++++++--- 4 files changed, 193 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 3b2b2a10..6f365d5c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ *.sum */node_modules/ -**/vendor/ \ No newline at end of file +**/vendor/ +.idea +out diff --git a/mayfly_go_web/src/components/monaco/MonacoEditor.vue b/mayfly_go_web/src/components/monaco/MonacoEditor.vue index 58c04c07..76c6828b 100644 --- a/mayfly_go_web/src/components/monaco/MonacoEditor.vue +++ b/mayfly_go_web/src/components/monaco/MonacoEditor.vue @@ -13,7 +13,7 @@ import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker'; import * as monaco from 'monaco-editor'; import { editor } from 'monaco-editor'; import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker' -// 主题仓库 https://github.com/brijeshb42/monaco-themes +// 主题仓库 https://github.com/brijeshb42/monaco-themes // 主题例子 https://editor.bitwiser.in/ // import Monokai from 'monaco-themes/themes/Monokai.json' // import Active4D from 'monaco-themes/themes/Active4D.json' @@ -117,7 +117,7 @@ const options = { mouseWheelZoom: true, // 在按住Ctrl键的同时使用鼠标滚轮时,在编辑器中缩放字体 overviewRulerBorder: false, // 不要滚动条的边框 tabSize: 4, // tab 缩进长度 - fontFamily: 'JetBrainsMono', // 字体 暂时不要设置,否则光标容易错位 + // fontFamily: 'JetBrainsMono', // 字体 暂时不要设置,否则光标容易错位 fontWeight: 'bold', // fontSize: 12, // letterSpacing: 1, 字符间距 @@ -264,4 +264,4 @@ const registeShell = () => { max-width: 130px; } } - \ No newline at end of file + diff --git a/mayfly_go_web/src/views/ops/db/DbEdit.vue b/mayfly_go_web/src/views/ops/db/DbEdit.vue index 95f51481..6222c821 100644 --- a/mayfly_go_web/src/views/ops/db/DbEdit.vue +++ b/mayfly_go_web/src/views/ops/db/DbEdit.vue @@ -45,8 +45,8 @@ - diff --git a/mayfly_go_web/src/views/ops/db/SqlExec.vue b/mayfly_go_web/src/views/ops/db/SqlExec.vue index b42169e0..2f67310c 100644 --- a/mayfly_go_web/src/views/ops/db/SqlExec.vue +++ b/mayfly_go_web/src/views/ops/db/SqlExec.vue @@ -75,7 +75,7 @@ - 导出 + + + 提交 + gi + + + + 提交 + { 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; - } + await doRunSql(sql, execRemark) // 即只有以该字符串开头的sql才可修改表数据内容 if (sql.startsWith('SELECT *') || sql.startsWith('select *') || sql.startsWith('SELECT\n *')) { @@ -812,6 +840,21 @@ const onRunSql = async () => { } }; +const doRunSql = async (sql:string, execRemark?:string) => { + try { + state.queryTab.sql = sql; + state.queryTab.loading = true; + const colAndData: any = await runSql(sql, execRemark); + state.queryTab.updatedFields = []; + state.queryTab.execRes.data = colAndData.res; + state.queryTab.execRes.tableColumn = colAndData.colNames; + state.queryTab.loading = false; + } catch (e: any) { + state.queryTab.loading = false; + } +} + + const exportData = () => { const dataList = state.queryTab.execRes.data; isTrue(dataList.length > 0, '没有数据可导出'); @@ -846,6 +889,7 @@ const exportData = () => { * 执行sql str * * @param sql 执行的sql + * @param remark sql备注 */ const runSql = async (sql: string, remark: string = '') => { return await dbApi.sqlExec.request({ @@ -1134,7 +1178,7 @@ const onConfirmCondition = () => { } const row = conditionDialog.columnRow as any; condition += `${row.columnName} ${conditionDialog.condition} `; - dataTab.condition = condition + wrapColumnValue(row, conditionDialog.value); + dataTab.condition = condition + wrapColumnValue(row.columnType, conditionDialog.value); onCancelCondition(); }; @@ -1353,7 +1397,7 @@ const onDeleteData = async () => { isTrue(deleteDatas && deleteDatas.length > 0, '请先选择要删除的数据'); const primaryKey = await getColumn(state.nowTableName); const primaryKeyColumnName = primaryKey.columnName; - const ids = deleteDatas.map((d: any) => `${wrapColumnValue(primaryKey, d[primaryKeyColumnName])}`).join(','); + const ids = deleteDatas.map((d: any) => `${wrapColumnValue(primaryKey.columnType, d[primaryKeyColumnName])}`).join(','); const sql = `DELETE FROM ${state.nowTableName} WHERE ${primaryKeyColumnName} IN (${ids})`; promptExeSql(sql, null, () => { @@ -1416,7 +1460,7 @@ const cellClick = (row: any, column: any, cell: any) => { } // 转为字符串比较,可能存在数字等 let text = (row[property] || row[property] == 0 ? row[property] : '') + ''; - let div = cell.children[0]; + let div:HTMLElement = cell.children[0]; if (div) { let input = document.createElement('input'); input.setAttribute('value', text); @@ -1428,25 +1472,125 @@ const cellClick = (row: any, column: any, cell: any) => { row[property] = input.value; cell.replaceChildren(div); if (input.value !== text) { - // 设置修改了的字段 背景色 - // div.setAttribute('style', (div.getAttribute('style')||'')+';background-color:var(--el-color-success)') + let currentUpdatedFields: UpdateFieldsMeta[] + if (state.activeName === 'Query'){ + currentUpdatedFields = state.queryTab.updatedFields + } else { + currentUpdatedFields = state.updatedFields; + } + // 主键 const primaryKey = await getColumn(state.nowTableName); - const primaryKeyColumnName = primaryKey.columnName; + const primaryKeyValue = row[primaryKey.columnName]; // 更新字段列信息 - const updateColumn = await getColumn(state.nowTableName, column.rawColumnKey); - const sql = `UPDATE ${state.nowTableName} SET ${column.rawColumnKey} = ${wrapColumnValue(updateColumn, input.value)} - WHERE ${primaryKeyColumnName} = ${wrapColumnValue(primaryKey, row[primaryKeyColumnName])}`; - promptExeSql(sql, () => { - // 还原值 - row[property] = text; - // 还原背景色 - // div.setAttribute('style', (div.getAttribute('style')||'')+';background-color:inherit') - }); + const updateColumn = await getColumn(state.nowTableName, property); + const newField = {div, fieldName: column.rawColumnKey, fieldType: updateColumn.columnType, oldValue: text, newValue: input.value} as FieldsMeta; + + // 被修改的字段 + const primaryKeyFields = currentUpdatedFields.filter((meta)=>meta.primaryKey === primaryKeyValue) + let hasKey = false; + if (primaryKeyFields.length<=0){ + primaryKeyFields[0] = {primaryKey: primaryKeyValue, primaryKeyName: primaryKey.columnName, primaryKeyType: primaryKey.columnType, fields:[newField]} + }else { + hasKey = true + let hasField = primaryKeyFields[0].fields.some(a=>{ + if(a.fieldName === newField.fieldName){ + a.newValue = newField.newValue + } + return a.fieldName === newField.fieldName + }) + if(!hasField){ + primaryKeyFields[0].fields.push(newField) + } + } + let fields = primaryKeyFields[0].fields + + const fieldsParam = fields.filter((a)=> { + if(a.fieldName === column.rawColumnKey){ + a.newValue = input.value + } + return a.fieldName === column.rawColumnKey + }) + + const field = fieldsParam.length > 0 && fieldsParam[0] || {} as FieldsMeta + if (field.oldValue === input.value){ // 新值=旧值 + // 删除数据 + div.classList.remove('update_field_active') + let delIndex: number[] = []; + currentUpdatedFields.forEach((a,i) => { + if(a.primaryKey === primaryKeyValue) { + a.fields = a.fields && a.fields.length > 0 ? a.fields.filter(f => f.fieldName !== column.rawColumnKey) : []; + a.fields.length <= 0 && delIndex.push(i) + } + }); + delIndex.forEach(i=>delete currentUpdatedFields[i]) + currentUpdatedFields = currentUpdatedFields.filter(a=>a) + }else { + // 新增数据 + div.classList.add('update_field_active') + if (hasKey){ + currentUpdatedFields.forEach((value, index, array) =>{ + if(value.primaryKey === primaryKeyValue) { + array[index].fields = fields + } + }) + }else { + currentUpdatedFields.push({primaryKey: primaryKeyValue, primaryKeyName: primaryKey.columnName, primaryKeyType: primaryKey.columnType, fields}) + } + } + if (state.activeName === 'Query'){ + state.queryTab.updatedFields = currentUpdatedFields + } else { + state.updatedFields = currentUpdatedFields + } } }); } }; +const submitUpdateFields = () =>{ + let currentUpdatedFields:UpdateFieldsMeta[]; + let isQuery = false; + if (state.activeName === 'Query'){ + isQuery = true; + currentUpdatedFields = state.queryTab.updatedFields + } else { + currentUpdatedFields = state.updatedFields + } + if(currentUpdatedFields.length <= 0){ + return; + } + let res=''; + let divs:HTMLElement[] = []; + currentUpdatedFields.forEach(a=>{ + let sql = `UPDATE ${state.nowTableName} SET `; + let primaryKey = a.primaryKey; + let primaryKeyType = a.primaryKeyType; + let primaryKeyName = a.primaryKeyName; + a.fields.forEach(f => { + sql += ` ${f.fieldName} = ${wrapColumnValue(f.fieldType, f.newValue)},` + divs.push(f.div) + }) + sql = sql.substring(0, sql.length - 1) + sql += ` WHERE ${primaryKeyName} = ${wrapColumnValue(primaryKeyType, primaryKey)} ;` + res += sql; + }) + + promptExeSql(res, ()=>{}, ()=>{ + currentUpdatedFields = []; + divs.forEach(a=>{ + a.classList.remove('update_field_active') + }) + if(isQuery){ + state.queryTab.updatedFields = [] + doRunSql(state.queryTab.sql) + }else{ + state.updatedFields = [] + onRefresh(state.nowTableName) + } + }); + +} + /** * 根据字段列名获取字段列信息。 * 若字段列名为空,则返回主键列,若无主键列返回第一个字段列信息(用于获取主键等) @@ -1463,8 +1607,8 @@ const getColumn = async (tableName: string, columnName: string = '') => { /** * 根据字段信息包装字段值,如为字符串等则添加‘’ */ -const wrapColumnValue = (column: any, value: any) => { - if (isNumber(column.columnType)) { +const wrapColumnValue = (columnType: string, value: any) => { + if (isNumber(columnType)) { return value; } return `'${value}'`; @@ -1599,6 +1743,15 @@ watch(store.state.sqlExecInfo, async (newValue) => {