mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 23:40:24 +08:00
feat: dbms表数据列表新增排序
This commit is contained in:
@@ -18,7 +18,6 @@
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="success"
|
||||
size="mini"
|
||||
@click="
|
||||
newQueryShow = true;
|
||||
activeName = 'second';
|
||||
@@ -32,9 +31,9 @@
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<el-container style="border: 1px solid #eee; margin-top: 1px; height: 600px">
|
||||
<el-container style="border: 1px solid #eee; margin-top: 1px; height: 630px">
|
||||
<el-container style="margin-left: 2px">
|
||||
<el-header style="text-align: left; height: 45px; font-size: 12px; padding: 0px">
|
||||
<el-header style="text-align: left; height: 35px; font-size: 12px; padding: 0px">
|
||||
<el-select v-model="tableName" placeholder="请选择表" @change="changeTable" filterable style="width: 99%">
|
||||
<el-option
|
||||
v-for="item in tableMetadata"
|
||||
@@ -47,21 +46,22 @@
|
||||
</el-header>
|
||||
|
||||
<el-main style="padding: 0px; overflow: hidden">
|
||||
<el-table :data="columnMetadata" height="100%" size="mini">
|
||||
<el-table :data="columnMetadata" height="100%" size="small">
|
||||
<el-table-column prop="columnName" label="名称" show-overflow-tooltip> </el-table-column>
|
||||
<el-table-column prop="columnComment" label="备注" show-overflow-tooltip> </el-table-column>
|
||||
<el-table-column width="120" prop="columnType" label="类型" show-overflow-tooltip> </el-table-column>
|
||||
</el-table>
|
||||
</el-main>
|
||||
</el-container>
|
||||
<el-tabs style="width: 70%; margin-left: 20px" v-model="activeName" @tab-click="handleClick">
|
||||
<el-tabs style="width: 70%; margin-left: 10px" v-model="activeName">
|
||||
<el-tab-pane label="数据信息" name="first">
|
||||
<el-table
|
||||
@cell-dblclick="cellClick"
|
||||
@sort-change="tableSortChange"
|
||||
style="margin-top: 1px"
|
||||
:data="execRes.data"
|
||||
size="mini"
|
||||
max-height="500"
|
||||
size="small"
|
||||
max-height="580"
|
||||
:empty-text="execRes.emptyResText"
|
||||
stripe
|
||||
border
|
||||
@@ -75,19 +75,16 @@
|
||||
:prop="item"
|
||||
:label="item"
|
||||
show-overflow-tooltip
|
||||
:sortable="nowTableName != '' ? 'custom' : false"
|
||||
>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="新建查询" v-if="newQueryShow" name="second">
|
||||
<el-aside id="sqlcontent" width="75%" style="background-color: rgb(238, 241, 246)">
|
||||
<el-aside id="sqlcontent" width="100%" style="background-color: rgb(238, 241, 246)">
|
||||
<div class="toolbar">
|
||||
<div class="fl">
|
||||
<!-- <el-button v-waves @click="runSql" type="success" icon="video-play" plain>执行</el-button>
|
||||
|
||||
<el-button v-waves @click="formatSql" type="primary" icon="magic-stick" plain>格式化</el-button> -->
|
||||
|
||||
<el-upload
|
||||
style="display: inline-block; margin-left: 10px"
|
||||
:before-upload="beforeUpload"
|
||||
@@ -102,7 +99,7 @@
|
||||
multiple
|
||||
:limit="100"
|
||||
>
|
||||
<el-button v-waves type="success" icon="video-play" plain>sql脚本执行</el-button>
|
||||
<el-button type="success" icon="video-play" plain size="small">sql脚本执行</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
|
||||
@@ -121,8 +118,8 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
<el-button v-waves @click="saveSql" type="primary" icon="document-add" plain>保存</el-button>
|
||||
<el-button v-waves @click="deleteSql" type="danger" icon="delete" plain>删除</el-button>
|
||||
<el-button @click="saveSql" type="primary" icon="document-add" plain size="small">保存</el-button>
|
||||
<el-button @click="deleteSql" type="danger" icon="delete" plain size="small">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<codemirror
|
||||
@@ -135,8 +132,8 @@
|
||||
:options="cmOptions"
|
||||
/>
|
||||
<el-button-group :style="btnStyle">
|
||||
<el-button v-waves @click="runSql" type="success" icon="video-play" size="small" plain>执行</el-button>
|
||||
<el-button v-waves @click="formatSql" type="primary" icon="magic-stick" size="small" plain>格式化</el-button>
|
||||
<el-button @click="runSql" type="success" icon="video-play" size="small" plain>执行</el-button>
|
||||
<el-button @click="formatSql" type="primary" icon="magic-stick" size="small" plain>格式化</el-button>
|
||||
</el-button-group>
|
||||
</el-aside>
|
||||
</el-tab-pane>
|
||||
@@ -150,7 +147,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, computed, defineComponent, ref } from 'vue';
|
||||
import { h, toRefs, reactive, computed, defineComponent, ref } from 'vue';
|
||||
import { dbApi } from './api';
|
||||
import _ from 'lodash';
|
||||
|
||||
@@ -166,7 +163,7 @@ import { codemirror } from '@/components/codemirror';
|
||||
import 'codemirror/addon/hint/show-hint.js';
|
||||
import 'codemirror/addon/hint/sql-hint.js';
|
||||
|
||||
import sqlFormatter from 'sql-formatter';
|
||||
import { format as sqlFormatter } from 'sql-formatter';
|
||||
import { notNull, notEmpty } from '@/common/assert';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import ProjectEnvSelect from '../component/ProjectEnvSelect.vue';
|
||||
@@ -185,10 +182,12 @@ export default defineComponent({
|
||||
|
||||
const state = reactive({
|
||||
token: token,
|
||||
defalutLimit: 25, // 默认查询数量
|
||||
dbs: [],
|
||||
tables: [],
|
||||
dbId: null,
|
||||
tableName: '',
|
||||
nowTableName: '', // 当前表格数据操作的数据库表名,用于双击编辑表内容使用
|
||||
tableMetadata: [],
|
||||
columnMetadata: [],
|
||||
sqlName: '',
|
||||
@@ -283,20 +282,39 @@ export default defineComponent({
|
||||
|
||||
/**
|
||||
* 执行sql str
|
||||
*
|
||||
* @param sql 执行的sql
|
||||
* @param replaceColumn 是否替换列名,如点击排序时,不需要替换表头,否则排序icon无法回显
|
||||
*/
|
||||
const runSqlStr = async (sql: string) => {
|
||||
state.execRes.tableColumn = [];
|
||||
const runSqlStr = async (sql: string, replaceColumn: boolean = true) => {
|
||||
state.activeName = 'first';
|
||||
sql = sql.trim();
|
||||
if (replaceColumn) {
|
||||
state.execRes.tableColumn = [];
|
||||
}
|
||||
state.execRes.data = [];
|
||||
state.execRes.emptyResText = '查询中...';
|
||||
console.log(sql);
|
||||
const res = await dbApi.sqlExec.request({
|
||||
id: state.dbId,
|
||||
sql: sql,
|
||||
});
|
||||
state.execRes.emptyResText = '没有数据';
|
||||
state.execRes.tableColumn = res.colNames;
|
||||
if (replaceColumn) {
|
||||
state.execRes.tableColumn = res.colNames;
|
||||
}
|
||||
state.execRes.data = res.res;
|
||||
state.activeName = 'first';
|
||||
|
||||
// 设置当前可双击修改表数据内容的表名,即只有以该字符串开头的sql才可修改表数据内容
|
||||
if (sql.startsWith('SELECT *') || sql.startsWith('select *')) {
|
||||
const tableName = sql.split(/from/i)[1];
|
||||
if (tableName) {
|
||||
state.nowTableName = tableName.trim().split(' ')[0];
|
||||
} else {
|
||||
state.nowTableName = '';
|
||||
}
|
||||
} else {
|
||||
state.nowTableName = '';
|
||||
}
|
||||
};
|
||||
|
||||
const beforeUpload = (file: File) => {
|
||||
@@ -423,6 +441,9 @@ export default defineComponent({
|
||||
getUserSql();
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取用户保存的sql模板内容
|
||||
*/
|
||||
const getUserSql = () => {
|
||||
notNull(state.dbId, '请先选择数据库');
|
||||
dbApi.getSql.request({ id: state.dbId, type: 1, name: state.sqlName }).then((res) => {
|
||||
@@ -434,6 +455,9 @@ export default defineComponent({
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取用户保存的sql模板名称
|
||||
*/
|
||||
const getSqlNames = () => {
|
||||
dbApi.getSqlNames
|
||||
.request({
|
||||
@@ -508,34 +532,108 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
if (execSelectSql) {
|
||||
runSqlStr(`SELECT * FROM ${tableName} ORDER BY create_time DESC LIMIT 25`);
|
||||
runSqlStr(`SELECT * FROM ${tableName} LIMIT ${state.defalutLimit}`);
|
||||
}
|
||||
};
|
||||
|
||||
// 监听单元格点击事件
|
||||
const cellClick = (row: any, column: any, cell: any, event: any) => {
|
||||
console.log(cell.children[0].tagName);
|
||||
// 如果当前操作的表名不存在,则不允许修改表格内容
|
||||
if (!state.nowTableName) {
|
||||
return;
|
||||
}
|
||||
let isDiv = cell.children[0].tagName === 'DIV';
|
||||
let text = cell.children[0].innerText;
|
||||
let div = cell.children[0];
|
||||
if (isDiv) {
|
||||
let input = document.createElement('input');
|
||||
input.setAttribute('value', text);
|
||||
input.setAttribute('style', 'height:30px');
|
||||
// 将表格width也赋值于输入框,避免输入框长度超过表格长度
|
||||
input.setAttribute('style', 'height:30px;' + div.getAttribute('style'));
|
||||
cell.replaceChildren(input);
|
||||
input.focus();
|
||||
input.addEventListener('blur', () => {
|
||||
div.innerText = input.value;
|
||||
cell.replaceChildren(div);
|
||||
console.log(input.value, column.rawColumnKey, text, 42242);
|
||||
if (input.value !== text) {
|
||||
dbApi.sqlExec.request({
|
||||
id: state.dbId,
|
||||
sql: `UPDATE ${state.tableName} SET ${column.rawColumnKey} = '${input.value}' WHERE ${column.rawColumnKey} = '${text}'`,
|
||||
const primaryKey = getTablePrimaryKeyColume(state.nowTableName);
|
||||
const sql = `UPDATE ${state.nowTableName} SET ${column.rawColumnKey} = '${input.value}' WHERE ${primaryKey} = '${row[primaryKey]}'`;
|
||||
promptExeSql(sql, () => {
|
||||
div.innerText = text;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取表主键列名,目前先以默认表字段第一个字段
|
||||
*/
|
||||
const getTablePrimaryKeyColume = (tableName: string) => {
|
||||
// 'id [bigint(20) unsigned]'
|
||||
return state.cmOptions.hintOptions.tables[tableName][0].split(' ')[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* 弹框提示是否执行sql
|
||||
*/
|
||||
const promptExeSql = (sql: string, cancelFunc: any = null) => {
|
||||
ElMessageBox({
|
||||
title: '执行SQL',
|
||||
message: h(
|
||||
'div',
|
||||
{
|
||||
attrs: {
|
||||
class: 'el-textarea',
|
||||
},
|
||||
},
|
||||
[
|
||||
h('textarea', {
|
||||
attrs: {
|
||||
class: 'el-textarea__inner',
|
||||
autocomplete: 'off',
|
||||
rows: 8,
|
||||
},
|
||||
style: {
|
||||
height: '150px',
|
||||
width: '100%',
|
||||
fontWeight: '600',
|
||||
},
|
||||
value: sqlFormatter(sql),
|
||||
}),
|
||||
]
|
||||
),
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '执行',
|
||||
cancelButtonText: '取消',
|
||||
beforeClose: (action, instance, done) => {
|
||||
if (action === 'confirm') {
|
||||
instance.confirmButtonLoading = true;
|
||||
instance.confirmButtonText = '执行中...';
|
||||
setTimeout(() => {
|
||||
done();
|
||||
setTimeout(() => {
|
||||
instance.confirmButtonLoading = false;
|
||||
}, 200);
|
||||
}, 200);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
},
|
||||
})
|
||||
.then((action) => {
|
||||
dbApi.sqlExec.request({
|
||||
id: state.dbId,
|
||||
sql: sql,
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
if (cancelFunc) {
|
||||
cancelFunc();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 添加新数据行
|
||||
// const addRow = () => {
|
||||
// let obj: any = {};
|
||||
@@ -564,10 +662,10 @@ export default defineComponent({
|
||||
let selectSql = codemirror.value.getSelection();
|
||||
// 有选中sql则只格式化选中部分,否则格式化全部
|
||||
if (selectSql != '') {
|
||||
codemirror.value.replaceSelection(sqlFormatter.format(selectSql));
|
||||
codemirror.value.replaceSelection(sqlFormatter(selectSql));
|
||||
} else {
|
||||
/* 将sql内容进行格式后放入编辑器中*/
|
||||
state.sql = sqlFormatter.format(sqlFormatter.format(state.sql));
|
||||
state.sql = sqlFormatter(state.sql);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -575,10 +673,11 @@ export default defineComponent({
|
||||
const res = await dbApi.dbs.request(state.params);
|
||||
state.dbs = res.list;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取选择文字,显示隐藏按钮,防抖
|
||||
*/
|
||||
const getSelection = _.debounce((e) => {
|
||||
const getSelection = _.debounce((e: any) => {
|
||||
let temp = codemirror.value.getSelection();
|
||||
if (temp) {
|
||||
state.btnStyle.display = 'block';
|
||||
@@ -592,9 +691,22 @@ export default defineComponent({
|
||||
state.btnStyle.top = '';
|
||||
}
|
||||
}, 100);
|
||||
|
||||
const listenMouse = (e: any) => {
|
||||
getSelection(e);
|
||||
};
|
||||
|
||||
/**
|
||||
* 表排序字段变更
|
||||
*/
|
||||
const tableSortChange = (sort: any) => {
|
||||
if (!state.nowTableName) {
|
||||
return;
|
||||
}
|
||||
const sortType = sort.order == 'descending' ? 'DESC' : 'ASC';
|
||||
runSqlStr(`SELECT * FROM ${state.nowTableName} ORDER BY ${sort.prop} ${sortType} LIMIT ${state.defalutLimit}`, false);
|
||||
};
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
cmEditor,
|
||||
@@ -615,6 +727,7 @@ export default defineComponent({
|
||||
formatSql,
|
||||
onBeforeChange,
|
||||
listenMouse,
|
||||
tableSortChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user