diff --git a/mayfly_go_web/package.json b/mayfly_go_web/package.json
index 6eb7901b..2ccd21ec 100644
--- a/mayfly_go_web/package.json
+++ b/mayfly_go_web/package.json
@@ -19,6 +19,9 @@
"jsoneditor": "^9.9.2",
"lodash": "^4.17.21",
"mitt": "^3.0.0",
+ "monaco-editor": "^0.34.1",
+ "monaco-sql-languages": "^0.9.5",
+ "monaco-themes": "^0.4.2",
"nprogress": "^0.2.0",
"screenfull": "^6.0.2",
"sortablejs": "^1.13.0",
diff --git a/mayfly_go_web/public/config.js b/mayfly_go_web/public/config.js
index 8fbf95dc..5518e7e4 100644
--- a/mayfly_go_web/public/config.js
+++ b/mayfly_go_web/public/config.js
@@ -2,4 +2,23 @@ window.globalConfig = {
// 默认为空,以访问根目录为api请求地址。若前后端分离部署可单独配置该后端api请求地址
"BaseApiUrl": "",
"BaseWsUrl": ""
-}
\ No newline at end of file
+}
+
+// index.html添加百秒级时间戳,防止被浏览器缓存
+!function(){
+ let t = "t=" + new Date().getTime().toString().substring(0, 8)
+ let search = location.search;
+ let m = search && search.match(/t=\d*/g)
+
+ if (m[0]){
+ if( m[0] !== t){
+ location.search = search.replace(m[0], t)
+ }
+ } else {
+ if(search.indexOf('?') > -1){
+ location.search = search + '&'+t
+ }else{
+ location.search = t
+ }
+ }
+}()
diff --git a/mayfly_go_web/src/views/ops/db/DbList.vue b/mayfly_go_web/src/views/ops/db/DbList.vue
index 64bf9342..9823e3ec 100644
--- a/mayfly_go_web/src/views/ops/db/DbList.vue
+++ b/mayfly_go_web/src/views/ops/db/DbList.vue
@@ -353,8 +353,6 @@ const state = reactive({
tableCreateDialog: {
title: '创建表',
visible: false,
- columns: [],
- indexs: [],
activeName: '1',
type: '',
enableEditTypes:['mysql'], // 支持"编辑表"的数据库类型
@@ -693,8 +691,8 @@ const openEditTable = async (row: any) => {
state.tableCreateDialog.visible = true
state.tableCreateDialog.activeName = '1'
- if(row === false){
- state.tableCreateDialog.data = {edit: false, row: {}, indexs: [], columns: [] }
+ if (row === false) {
+ state.tableCreateDialog.data = { edit: false, row: {}, indexs: [], columns: [] }
state.tableCreateDialog.title = '创建表'
}
diff --git a/mayfly_go_web/src/views/ops/db/SqlExec.vue b/mayfly_go_web/src/views/ops/db/SqlExec.vue
index 6ace9594..040e6a04 100644
--- a/mayfly_go_web/src/views/ops/db/SqlExec.vue
+++ b/mayfly_go_web/src/views/ops/db/SqlExec.vue
@@ -87,6 +87,13 @@
+
+
+ {{ item }}
+
+
+
+
-
@@ -130,6 +139,7 @@
+
@@ -244,65 +254,56 @@
import { onMounted, toRefs, reactive, ref, watch } from 'vue';
import { dbApi } from './api';
-import 'codemirror/addon/hint/show-hint.css';
-// import base style
-import 'codemirror/lib/codemirror.css';
-// 引入主题后还需要在 options 中指定主题才会生效
-import 'codemirror/theme/base16-light.css';
-
-import 'codemirror/addon/selection/active-line';
-import _CodeMirror from 'codemirror';
-import 'codemirror/addon/hint/show-hint.js';
-import 'codemirror/addon/hint/sql-hint.js';
-
-import { format as sqlFormatter } from 'sql-formatter';
-import { notBlank, notEmpty, isTrue } from '@/common/assert';
-import { ElMessage, ElMessageBox } from 'element-plus';
+import {format as sqlFormatter} from 'sql-formatter';
+import {isTrue, notBlank, notEmpty} from '@/common/assert';
+import {ElMessage, ElMessageBox} from 'element-plus';
import config from '@/common/config';
-import { getSession } from '@/common/utils/storage';
+import {getSession} from '@/common/utils/storage';
import SqlExecBox from './component/SqlExecBox';
-import { dateStrFormat } from '@/common/utils/date.ts';
-import { useStore } from '@/store/index.ts';
-import { tagApi } from '../tag/api.ts';
+import {dateStrFormat} from '@/common/utils/date.ts';
+import {useStore} from '@/store/index.ts';
+import {tagApi} from '../tag/api.ts';
+
+import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker';
+import {language as sqlLanguage} from 'monaco-editor/esm/vs/basic-languages/mysql/mysql.js';
+import * as monaco from 'monaco-editor';
+import {editor, languages, Position} from 'monaco-editor';
+
+// 主题仓库 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'
+import ahe from 'monaco-themes/themes/All Hallows Eve.json'
+import bop from 'monaco-themes/themes/Birds of Paradise.json'
+import krTheme from 'monaco-themes/themes/krTheme.json'
+import Dracula from 'monaco-themes/themes/Dracula.json'
+import TextmateMac from 'monaco-themes/themes/Textmate (Mac Classic).json'
+import { Minus } from '@element-plus/icons-vue';
const store = useStore();
-const codeTextarea: any = ref(null);
+const monacoTextarea: any = ref(null);
const token = getSession('token');
-let codemirror = null as any;
const tableMap = new Map();
const defalutLimit = 20
-const cmOptions = {
- tabSize: 4,
- mode: 'text/x-sql',
- lineNumbers: true,
- line: true,
- indentWithTabs: true,
- smartIndent: true,
- matchBrackets: true,
- theme: 'base16-light',
- autofocus: true,
- extraKeys: { Tab: 'autocomplete' }, // 自定义快捷键
- hintOptions: {
- completeSingle: false,
- // 自定义提示选项
- tables: {},
- },
- // more CodeMirror options...
+export type TableMeta = {
+ // 表名
+ tableName:string,
+ // 表注释
+ tableComment:string
}
-
const state = reactive({
token: token,
tags: [],
dbs: [] as any, // 数据库实例列表
- databaseList: [], // 数据库实例拥有的数据库列表,1数据库实例 -> 多数据库
+ databaseList: [] as string[], // 数据库实例拥有的数据库列表,1数据库实例 -> 多数据库
db: '', // 当前操作的数据库
dbType: '',
tables: [] as any,
dbId: null, // 当前选中操作的数据库实例
tableName: '',
- tableMetadata: [],
+ tableMetadata: [] as TableMeta[],
sqlName: '', // 当前sql模板名
sqlNames: [], // 所有sql模板名
activeName: 'Query',
@@ -316,16 +317,16 @@ const state = reactive({
// 点击执行按钮执行结果信息
execRes: {
data: [],
- tableColumn: [],
+ tableColumn: []
},
loading: false,
nowTableName: '', //当前表格数据操作的数据库表名,用于双击编辑表内容使用
- selectionDatas: [],
+ selectionDatas: []
},
params: {
pageNum: 1,
pageSize: 100,
- tagPath: null,
+ tagPath: null
},
conditionDialog: {
title: '',
@@ -334,14 +335,21 @@ const state = reactive({
dataTab: null,
visible: false,
condition: '=',
- value: null,
+ value: null
},
genSqlDialog: {
visible: false,
sql: '',
},
+ monacoOptions: {
+ editor: {} as editor.IStandaloneCodeEditor,
+ height: '',
+ tableMaxHeight:250,
+ dbTables:{},
+ theme:'',
+ defaultThemes:[ 'vs' ,'vs-dark', 'hc-black', 'hc-light', 'Monokai', 'Active4D', 'ahe', 'bop', 'krTheme', 'Dracula', 'TextmateMac'],
+ }
});
-
const {
tags,
dbs,
@@ -360,27 +368,288 @@ const {
params,
conditionDialog,
genSqlDialog,
+ monacoOptions
} = toRefs(state)
-const initCodemirror = () => {
- // 初始化编辑器实例,传入需要被实例化的文本域对象和默认配置
- codemirror = _CodeMirror.fromTextArea(codeTextarea.value, cmOptions);
- codemirror.on('inputRead', (instance: any, changeObj: any) => {
- if (/^[a-zA-Z]/.test(changeObj.text[0])) {
- instance.showHint();
- }
- });
+let monacoEditor = {} as editor.IStandaloneCodeEditor;
- codemirror.on('beforeChange', (instance: any, changeObj: any) => {
- var text = changeObj.text[0];
- // 将sql提示去除
- changeObj.text[0] = text.split(' ')[0];
- });
+self.MonacoEnvironment = {
+ getWorker() {
+ return new EditorWorker();
+ }
};
+const initMonacoEditor = () => {
+ console.log('初始化编辑器')
+ // options参数参考 https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html#language
+
+ let defVal = `-- monaco editor
+select * from database.Outvisit l
+left join patient p on l.patid=p.patientid
+join patstatic c on l.patid=c.patid inner join patphone ph on l.patid=ph.patid
+where l.name='kevin' and exsits(select 1 from pharmacywestpas pw where p.outvisitid=l.outvisitid)
+unit all
+select * from invisit v where`;
+
+ monacoEditor = monaco.editor.create(monacoTextarea.value, {
+ value: defVal,
+ language: 'sql',
+ theme: 'vs',
+ automaticLayout: true, //自适应宽高布局
+ foldingStrategy: 'indentation',//代码可分小段折叠
+ roundedSelection: false, // 禁用选择文本背景的圆角
+ matchBrackets: 'near',
+ linkedEditing:true,
+ cursorBlinking: 'smooth',// 光标闪烁样式
+ mouseWheelZoom: true, // 在按住Ctrl键的同时使用鼠标滚轮时,在编辑器中缩放字体
+ overviewRulerBorder: false, // 不要滚动条的边框
+ tabSize: 2, // tab 缩进长度
+ // fontFamily:'consolas', // 字体 暂时不要设置,否则光标容易错位
+ // letterSpacing: 1, 字符间距
+ // quickSuggestions:false, // 禁用代码提示
+ minimap: {
+ enabled: false, // 不要小地图
+ },
+ });
+
+ // 初始化一些主题
+ monaco.editor.defineTheme('Monokai', Monokai);
+ monaco.editor.defineTheme('Active4D', Active4D);
+ monaco.editor.defineTheme('ahe', ahe);
+ monaco.editor.defineTheme('bop', bop);
+ monaco.editor.defineTheme('krTheme', krTheme);
+ monaco.editor.defineTheme('Dracula', Dracula);
+ monaco.editor.defineTheme('TextmateMac', TextmateMac);
+
+ // 动态设置主题
+ // monaco.editor.setTheme('hc-black');
+
+ // 参考 https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-completion-provider-example
+ monaco.languages.registerCompletionItemProvider('sql', {
+ triggerCharacters:['.'],
+ provideCompletionItems: async (model: editor.ITextModel, position: Position): Promise => {
+
+ let word = model.getWordUntilPosition(position);
+ const {lineNumber, column} = position
+ const {startColumn, endColumn} = word
+
+ // 当前行文本
+ let lineContent = model.getLineContent(lineNumber);
+ // 注释行不需要代码提示
+ if(lineContent.startsWith('--')){
+ return {suggestions: []}
+ }
+
+ let range = {
+ startLineNumber: lineNumber,
+ endLineNumber: lineNumber,
+ startColumn,
+ endColumn,
+ };
+
+ // 光标前文本
+ const textBeforePointer = model.getValueInRange({
+ startLineNumber: lineNumber,
+ startColumn: 0,
+ endLineNumber: lineNumber,
+ endColumn: column
+ })
+ const textBeforePointerMulti = model.getValueInRange({
+ startLineNumber: 1,
+ startColumn: 0,
+ endLineNumber: lineNumber,
+ endColumn: column
+ })
+ // 光标后文本
+ const textAfterPointerMulti = model.getValueInRange({
+ startLineNumber: lineNumber,
+ startColumn: column,
+ endLineNumber: model.getLineCount(),
+ endColumn: model.getLineMaxColumn(model.getLineCount())
+ })
+ // // const nextTokens = textAfterPointer.trim().split(/\s+/)
+ // // const nextToken = nextTokens[0].toLowerCase()
+ const tokens = textBeforePointer.trim().split(/\s+/)
+ const lastToken = tokens[tokens.length - 1].toLowerCase()
+
+ console.log("光标前文本:=>" + textBeforePointerMulti)
+
+ console.log("最后输入的:=>" + lastToken)
+ if (lastToken.endsWith('.')) {
+ // 如果是.触发代码提示,则进行【 库.表名联想 】 或 【 表别名.表字段联想 】
+ let str = lastToken.substring(0, lastToken.lastIndexOf('.'))
+ // 库.表名联想
+ if (state.databaseList.indexOf(str) > -1) {
+ let tables = await loadTableMetadata(str)
+ let suggestions: languages.CompletionItem[] = []
+ for(let item of tables){
+ const {tableName, tableComment} = item
+ suggestions.push({
+ label: tableName + ( tableComment?' - ' + tableComment :'' ),
+ kind: monaco.languages.CompletionItemKind.File,
+ insertText: tableName,
+ range
+});
+ }
+ return { suggestions }
+ }
+
+ let sql = textBeforePointerMulti.split(';')[textBeforePointerMulti.split(';').length - 1] + textAfterPointerMulti.split(';')[0];
+ // 表别名.表字段联想
+ let tableInfo = getTableByAlias(sql,state.db, str)
+ if(tableInfo.tableName){
+ let table = tableInfo.tableName
+ let db = tableInfo.dbName
+ // 取出表名并提示
+ let dbs = state.monacoOptions.dbTables[db]
+ let tables = dbs ? (dbs[table] || []) : [];
+ if((!tables || tables.length === 0) && db){
+ state.monacoOptions.dbTables[db] = await loadHintTables(db)
+ dbs = state.monacoOptions.dbTables[db]
+ tables = dbs ? (dbs[table] || []) : [];
+ }
+ tables.sort()
+ let suggestions: languages.CompletionItem[] = []
+ tables.forEach((a:string)=>{
+ // 字段数据格式 字段名 字段注释, 如: create_time [datetime][创建时间]
+ let fieldName = a.substring(0,a.indexOf(" "))
+ let comment = a.replace(eval(`/${fieldName}\\s+/`), '')
+ let detail = fieldName + ( comment?' - ' + comment :'' )
+ suggestions.push({
+ label: detail,
+ kind: monaco.languages.CompletionItemKind.Property,
+ detail: detail,
+ insertText: fieldName,
+ range
+ });
+ })
+ return { suggestions }
+ //
+ }
+ return { suggestions:[] }
+ }
+
+ // 库名联想
+
+ let suggestions: languages.CompletionItem[] = []
+ // mysql关键字
+ sqlLanguage.keywords.forEach((item: any) => {
+ suggestions.push({
+ label: item,
+ kind: monaco.languages.CompletionItemKind.Keyword,
+ insertText: item,
+ range
+ });
+ })
+ // 操作符
+ sqlLanguage.operators.forEach((item: any) => {
+ suggestions.push({
+ label: item,
+ kind: monaco.languages.CompletionItemKind.Operator,
+ insertText: item,
+ range
+ });
+ })
+ // 内置函数
+ sqlLanguage.builtinFunctions.forEach((item: any) => {
+ suggestions.push({
+ label: item,
+ kind: monaco.languages.CompletionItemKind.Function,
+ insertText: item,
+ range
+ });
+ })
+ // 内置变量
+ sqlLanguage.builtinVariables.forEach((item: string) => {
+ suggestions.push({
+ label: item,
+ kind: monaco.languages.CompletionItemKind.Variable,
+ insertText: item,
+ range
+ });
+ })
+
+ // 库名提示
+ state.databaseList.forEach(a => {
+ suggestions.push({
+ label: a + ' - schema',
+ kind: monaco.languages.CompletionItemKind.Folder,
+ insertText: a,
+ range
+ });
+ })
+
+ // 表名联想
+ state.tableMetadata.forEach((tableMeta: TableMeta) => {
+ const {tableName, tableComment} = tableMeta
+ suggestions.push({
+ label: tableName + ' - ' + tableComment,
+ kind: monaco.languages.CompletionItemKind.File,
+ detail: tableComment,
+ insertText: tableName,
+ range
+ });
+ })
+
+ // 默认提示
+ return {
+ suggestions: suggestions
+};
+ },
+ });
+
+};
+
+/**
+ * 根据别名获取sql里的表名
+ * @param sql sql
+ * @param db 默认数据库
+ * @param alias 别名
+ */
+const getTableByAlias = (sql: string, db: string, alias: string):{dbName: string, tableName: string} => {
+
+ // 表别名:表名
+ let result = {};
+ let defName = '';
+ let defResult = {};
+ // 正则匹配取出表名和表别名
+ // 测试sql
+ /*
+
+ `select * from database.Outvisit l
+left join patient p on l.patid=p.patientid
+join patstatic c on l.patid=c.patid inner join patphone ph on l.patid=ph.patid
+where l.name='kevin' and exsits(select 1 from pharmacywestpas pw where p.outvisitid=l.outvisitid)
+unit all
+select * from invisit v where`.match(/(join|from)\s+(\w*-?\w*\.?\w+)\s*(as)?\s*(\w*)/gi)
+ */
+
+ let match = sql.match(/(join|from)\s+(\w*-?\w*\.?\w+)\s*(as)?\s*(\w*)/gi)
+ if(match && match.length>0){
+ match.forEach(a=>{
+ // 去掉前缀,取出
+ let t = a.substring(5, a.length)
+ .replaceAll(/\s+as\s+/g, ' ')
+ .split(/\s+/);
+ let withDb = t[0].split('.');
+ // 表名是 db名.表名
+ let tName = withDb.length > 1 ? withDb[1] : withDb[0]
+ let dbName = withDb.length > 1 ? withDb[0] :(db||'')
+ if(t.length == 2){
+ // 表别名:表名
+ result[t[1]]= {tableName: tName, dbName}
+ }else{
+ // 只有表名无别名 取第一个无别名的表为默认表
+ !defName && (defResult = { tableName: tName, dbName: db })
+ }
+ })
+ }
+ return result[alias] || defResult
+}
+
onMounted(() => {
- initCodemirror();
setHeight();
+ initMonacoEditor();
// 监听浏览器窗口大小变化,更新对应组件高度
window.onresize = () =>
(() => {
@@ -393,10 +662,25 @@ onMounted(() => {
*/
const setHeight = () => {
// 默认300px
- codemirror.setSize('auto', `${window.innerHeight - 538}px`);
- state.dataTabsTableHeight = window.innerHeight - 274;
+ state.monacoOptions.height = window.innerHeight - 550 + 'px'
+ state.dataTabsTableHeight = window.innerHeight - 274 ;
};
+/**
+ * 拖拽改变sql编辑区和查询结果区高度
+ */
+const onDragSetHeight = (e: any) => {
+ document.onmousemove = (e) => {
+ e.preventDefault();
+ //得到鼠标拖动的宽高距离:取绝对值
+ state.monacoOptions.height = `${monacoTextarea.value.offsetHeight + e.movementY}px`
+ state.monacoOptions.tableMaxHeight -= e.movementY
+ }
+ document.onmouseup = () => {
+ document.onmousemove = null;
+ }
+}
+
/**
* 标签更改后的回调事件
*/
@@ -425,9 +709,8 @@ const getTags = async () => {
const onRunSql = async () => {
notBlank(state.dbId, '请先选择数据库');
// 没有选中的文本,则为全部文本
- let sql = getSql();
- isTrue(sql && sql.trim(), '请选中需要执行的sql');
-
+ let sql = getSql() as string;
+ notBlank(sql && sql.trim(), '请选中需要执行的sql');
// 去除字符串前的空格、换行等
sql = sql.replace(/(^\s*)/g, '');
let execRemark = '';
@@ -669,12 +952,21 @@ const getColumnTip = (tableName: string, columnName: string) => {
* 获取sql,如果有鼠标选中,则返回选中内容,否则返回输入框内所有内容
*/
const getSql = () => {
- // 没有选中的文本,则为全部文本
- let selectSql = codemirror.getSelection();
- if (!selectSql) {
- selectSql = getCodermirrorValue();
+ let res = '' as string | undefined;
+ // 编辑器还没初始化
+ if(!monacoEditor.getModel){
+ return res;
}
- return selectSql;
+ // 选择选中的sql
+ let selection = monacoEditor.getSelection()
+ if (selection){
+ res = monacoEditor.getModel()?.getValueInRange(selection)
+ }
+ // 整个编辑器的sql
+ if(!res){
+ return monacoEditor.getModel()?.getValue()
+ }
+ return res
};
/**
@@ -691,26 +983,29 @@ const changeDbInstance = (dbId: any) => {
/**
* 更改数据库事件
*/
-const changeDb = (db: string) => {
+const changeDb = async (db: string) => {
if (!db) {
return;
}
clearDb();
- dbApi.tableMetadata.request({ id: state.dbId, db }).then((res) => {
- state.tableMetadata = res;
- });
+
+ // 加载数据库下所有表
+ state.tableMetadata = await loadTableMetadata(db)
+
+ // 加载数据库下所有表字段信息
+ state.monacoOptions.dbTables[db] = await loadHintTables(db)
- dbApi.hintTables
- .request({
- id: state.dbId,
- db,
- })
- .then((res) => {
- cmOptions.hintOptions.tables = res;
- });
getSqlNames();
};
+const loadTableMetadata = async (db: string) =>{
+ return await dbApi.tableMetadata.request({id: state.dbId, db})
+}
+
+const loadHintTables = async (db: string) =>{
+ return await dbApi.hintTables.request({id: state.dbId, db,})
+}
+
// 选择表事件
const changeTable = async (tableName: string, execSelectSql: boolean = true) => {
if (tableName == '') {
@@ -906,6 +1201,9 @@ const onTableSortChange = async (sort: any) => {
const changeSqlTemplate = () => {
getUserSql();
};
+const changeEditorTheme = () => {
+ monaco.editor.setTheme(state.monacoOptions.theme);
+};
/**
* 获取用户保存的sql模板内容
@@ -914,15 +1212,15 @@ const getUserSql = () => {
notBlank(state.dbId, '请先选择数据库');
dbApi.getSql.request({ id: state.dbId, type: 1, name: state.sqlName, db: state.db }).then((res) => {
if (res) {
- setCodermirrorValue(res.sql);
+ setSqlEditorValue(res.sql);
} else {
- setCodermirrorValue('');
+ setSqlEditorValue('');
}
});
};
-const setCodermirrorValue = (value: string) => {
- codemirror.setValue(value);
+const setSqlEditorValue = (value: string) => {
+ monacoEditor.getModel()?.setValue(value);
};
const getCodermirrorValue = () => {
@@ -952,8 +1250,8 @@ const getSqlNames = () => {
};
const saveSql = async () => {
- const sql = codemirror.getValue();
- notEmpty(sql, 'sql内容不能为空');
+ const sql = monacoEditor.getModel()?.getValue();
+ notBlank(sql, 'sql内容不能为空');
notBlank(state.dbId, '请先选择数据库实例');
await dbApi.saveSql.request({ id: state.dbId, db: state.db, sql: sql, type: 1, name: state.sqlName });
ElMessage.success('保存成功');
@@ -990,7 +1288,7 @@ const clearDb = () => {
state.nowTableName = '';
state.tableMetadata = [];
state.dataTabs = {};
- setCodermirrorValue('');
+ setSqlEditorValue('');
state.sqlNames = [];
state.sqlName = '';
state.activeName = state.queryTab.name;
@@ -1079,19 +1377,21 @@ const cellClick = (row: any, column: any, cell: any) => {
return;
}
// 转为字符串比较,可能存在数字等
- let text = (row[property] ? row[property] : '') + '';
+ let text = (row[property] || row[property]==0 ? row[property] : '') + '';
let div = cell.children[0];
if (div) {
let input = document.createElement('input');
input.setAttribute('value', text);
// 将表格width也赋值于输入框,避免输入框长度超过表格长度
- input.setAttribute('style', 'height:30px;' + div.getAttribute('style'));
+ input.setAttribute('style', 'height:23px;text-align:center;border:none;' + div.getAttribute('style'));
cell.replaceChildren(input);
input.focus();
input.addEventListener('blur', async () => {
row[property] = input.value;
cell.replaceChildren(div);
if (input.value !== text) {
+ // 设置修改了的字段 背景色
+ // div.setAttribute('style', (div.getAttribute('style')||'')+';background-color:var(--el-color-success)')
const primaryKey = await getColumn(state.nowTableName);
const primaryKeyColumnName = primaryKey.columnName;
// 更新字段列信息
@@ -1099,7 +1399,10 @@ const cellClick = (row: any, column: any, cell: any) => {
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')
});
}
});
@@ -1170,9 +1473,11 @@ const addRow = async () => {
* 格式化sql
*/
const formatSql = () => {
- let selectSql = codemirror.getSelection();
- isTrue(selectSql, '请选中需要格式化的sql');
- codemirror.replaceSelection(sqlFormatter(selectSql));
+ let selectSql = getSql();
+ if(selectSql){
+ monacoEditor.getModel()?.setValue(sqlFormatter(selectSql))
+ }
+
};
const search = async () => {
@@ -1183,7 +1488,7 @@ const search = async () => {
// 加载选中的db
const setSelects = async (sqlExecInfo: any) => {
// 保存sql
- let sql = codemirror?.getValue();
+ let sql = getSql();
if (sql && sql.length > 0 && state.dbId) {
await saveSql();
}
@@ -1197,7 +1502,7 @@ const setSelects = async (sqlExecInfo: any) => {
state.dbId = dbId;
state.db = db;
// 加载schema下所有表
- changeDb(db);
+ await changeDb(db);
};
// 判断如果有数据则加载下拉选项
@@ -1230,6 +1535,12 @@ watch(store.state.sqlExecInfo, async (newValue) => {
}
}
+.editor-move-resize {
+ cursor: n-resize;
+ height: 3px;
+ text-align: center;
+}
+
.el-tabs__header {
padding: 0 10px;
background-color: #fff;
diff --git a/mayfly_go_web/src/views/ops/db/component/SqlExecBox.ts b/mayfly_go_web/src/views/ops/db/component/SqlExecBox.ts
index 1925bdbc..93d200af 100644
--- a/mayfly_go_web/src/views/ops/db/component/SqlExecBox.ts
+++ b/mayfly_go_web/src/views/ops/db/component/SqlExecBox.ts
@@ -41,4 +41,4 @@ const SqlExecBox = (props: SqlExecProps): void => {
}
}
-export default SqlExecBox;
\ No newline at end of file
+export default SqlExecBox;
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 6f91e23e..4663c254 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,6 @@
-
+
@@ -70,7 +70,7 @@ const {
dialogVisible,
sqlValue,
remark,
- btnLoading,
+ btnLoading
} = toRefs(state)
state.sqlValue = props.sql as any;
@@ -148,7 +148,6 @@ const open = (props: SqlExecProps) => {
};
defineExpose({ open })
-