refactor: tooltip延迟显示等

This commit is contained in:
meilin.huang
2023-10-31 12:36:04 +08:00
parent f2b0f294d8
commit 3155380f16
17 changed files with 134 additions and 110 deletions

View File

@@ -59,15 +59,20 @@ export async function useLoginCaptcha(): Promise<boolean> {
*/ */
export async function useWatermark(): Promise<any> { export async function useWatermark(): Promise<any> {
const value = await getConfigValue(UseWatermarkConfigKey); const value = await getConfigValue(UseWatermarkConfigKey);
if (!value) { const defaultValue = {
return {
isUse: true, isUse: true,
}; };
if (!value) {
return defaultValue;
} }
try {
const jsonValue = JSON.parse(value); const jsonValue = JSON.parse(value);
// 将字符串转为bool // 将字符串转为bool
jsonValue.isUse = convertBool(jsonValue.isUse, true); jsonValue.isUse = convertBool(jsonValue.isUse, true);
return jsonValue; return jsonValue;
} catch (e) {
return defaultValue;
}
} }
function convertBool(value: string, defaultValue: boolean) { function convertBool(value: string, defaultValue: boolean) {

View File

@@ -132,7 +132,7 @@ const languageArr = [
}, },
]; ];
const options = { const defaultOptions = {
language: 'shell', language: 'shell',
theme: 'SolarizedLight', theme: 'SolarizedLight',
automaticLayout: true, //自适应宽高布局 automaticLayout: true, //自适应宽高布局
@@ -223,9 +223,9 @@ const initMonacoEditorIns = () => {
// options参数参考 https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html#language // options参数参考 https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html#language
// 初始化一些主题 // 初始化一些主题
monaco.editor.defineTheme('SolarizedLight', SolarizedLight); monaco.editor.defineTheme('SolarizedLight', SolarizedLight);
options.language = state.languageMode; defaultOptions.language = state.languageMode;
options.theme = themeConfig.value.editorTheme; defaultOptions.theme = themeConfig.value.editorTheme;
monacoEditorIns = monaco.editor.create(monacoTextarea.value, Object.assign(options, props.options as any)); monacoEditorIns = monaco.editor.create(monacoTextarea.value, Object.assign(defaultOptions, props.options as any));
// 监听内容改变,双向绑定 // 监听内容改变,双向绑定
monacoEditorIns.onDidChangeModelContent(() => { monacoEditorIns.onDidChangeModelContent(() => {

View File

@@ -151,7 +151,7 @@ export const useThemeConfig = defineStore('themeConfig', {
this.themeConfig.editorTheme = 'vs-dark'; this.themeConfig.editorTheme = 'vs-dark';
} else { } else {
body.setAttribute('class', ''); body.setAttribute('class', '');
this.themeConfig.editorTheme = 'SolarizedLight'; this.themeConfig.editorTheme = 'vs';
} }
}, },
// 设置水印配置信息 // 设置水印配置信息

View File

@@ -1,6 +1,6 @@
<template> <template>
<div style="display: inline-flex; justify-content: center; align-items: center; cursor: pointer; vertical-align: middle"> <div style="display: inline-flex; justify-content: center; align-items: center; cursor: pointer; vertical-align: middle">
<el-popover @show="showTagInfo" placement="top-start" title="标签信息" :width="300" trigger="hover"> <el-popover :show-after="500" @show="showTagInfo" placement="top-start" title="标签信息" :width="300" trigger="hover">
<template #reference> <template #reference>
<el-icon> <el-icon>
<InfoFilled /> <InfoFilled />

View File

@@ -52,6 +52,10 @@
</span> </span>
</template> </template>
<template #host="{ data }">
{{ `${data.host}:${data.port}` }}
</template>
<template #database="{ data }"> <template #database="{ data }">
<el-popover placement="right" trigger="click" :width="300"> <el-popover placement="right" trigger="click" :width="300">
<template #reference> <template #reference>
@@ -195,6 +199,10 @@ const queryConfig = [TableQuery.slot('tagPath', '标签', 'tagPathSelect'), Tabl
const columns = ref([ const columns = ref([
TableColumn.new('tagPath', '标签路径').isSlot().setAddWidth(20), TableColumn.new('tagPath', '标签路径').isSlot().setAddWidth(20),
TableColumn.new('instanceName', '实例名'),
TableColumn.new('type', '类型'),
TableColumn.new('host', 'ip:port').isSlot().setAddWidth(20),
TableColumn.new('username', 'username'),
TableColumn.new('name', '名称'), TableColumn.new('name', '名称'),
TableColumn.new('database', '数据库').isSlot().setMinWidth(70), TableColumn.new('database', '数据库').isSlot().setMinWidth(70),
TableColumn.new('remark', '备注'), TableColumn.new('remark', '备注'),

View File

@@ -39,7 +39,7 @@
> >
<template #prefix="{ data }"> <template #prefix="{ data }">
<span v-if="data.type == NodeType.DbInst"> <span v-if="data.type == NodeType.DbInst">
<el-popover placement="right-start" title="数据库实例信息" trigger="hover" :width="210"> <el-popover :show-after="500" placement="right-start" title="数据库实例信息" trigger="hover" :width="210">
<template #reference> <template #reference>
<SvgIcon v-if="data.params.type === 'mysql'" name="iconfont icon-op-mysql" :size="18" /> <SvgIcon v-if="data.params.type === 'mysql'" name="iconfont icon-op-mysql" :size="18" />
<SvgIcon v-if="data.params.type === 'postgres'" name="iconfont icon-op-postgres" :size="18" /> <SvgIcon v-if="data.params.type === 'postgres'" name="iconfont icon-op-postgres" :size="18" />
@@ -47,8 +47,10 @@
<SvgIcon name="InfoFilled" v-else /> <SvgIcon name="InfoFilled" v-else />
</template> </template>
<template #default> <template #default>
<el-form class="instances-pop-form" label-width="55px" :size="'small'"> <el-form class="instances-pop-form" label-width="auto" :size="'small'">
<el-form-item label="类型:">{{ data.params.type }}</el-form-item> <el-form-item label="类型:">{{ data.params.type }}</el-form-item>
<el-form-item label="host:">{{ `${data.params.host}:${data.params.port}` }}</el-form-item>
<el-form-item label="user:">{{ data.params.username }}</el-form-item>
<el-form-item label="名称:">{{ data.params.name }}</el-form-item> <el-form-item label="名称:">{{ data.params.name }}</el-form-item>
<el-form-item v-if="data.params.remark" label="备注:">{{ data.params.remark }}</el-form-item> <el-form-item v-if="data.params.remark" label="备注:">{{ data.params.remark }}</el-form-item>
</el-form> </el-form>
@@ -60,7 +62,13 @@
<SvgIcon name="Calendar" v-if="data.type == NodeType.TableMenu" color="#409eff" /> <SvgIcon name="Calendar" v-if="data.type == NodeType.TableMenu" color="#409eff" />
<el-tooltip v-if="data.type == NodeType.Table" effect="customized" :content="data.params.tableComment" placement="top-end"> <el-tooltip
:show-after="500"
v-if="data.type == NodeType.Table"
effect="customized"
:content="data.params.tableComment"
placement="top-end"
>
<SvgIcon name="Calendar" color="#409eff" /> <SvgIcon name="Calendar" color="#409eff" />
</el-tooltip> </el-tooltip>

View File

@@ -30,7 +30,7 @@
:sortable="sortable" :sortable="sortable"
> >
<template #header v-if="showColumnTip"> <template #header v-if="showColumnTip">
<el-tooltip raw-content placement="top" effect="customized"> <el-tooltip :show-after="500" raw-content placement="top" effect="customized">
<template #content> {{ getColumnTip(item) }} </template> <template #content> {{ getColumnTip(item) }} </template>
{{ item.columnName }} {{ item.columnName }}
</el-tooltip> </el-tooltip>
@@ -45,7 +45,7 @@
import { onMounted, watch, reactive, toRefs } from 'vue'; import { onMounted, watch, reactive, toRefs } from 'vue';
import { DbInst, UpdateFieldsMeta, FieldsMeta } from '../db'; import { DbInst, UpdateFieldsMeta, FieldsMeta } from '../db';
const emits = defineEmits(['sortChange', 'deleteData', 'selectionChange', 'changeUpdatedField']) const emits = defineEmits(['sortChange', 'deleteData', 'selectionChange', 'changeUpdatedField']);
const props = defineProps({ const props = defineProps({
dbId: { dbId: {
@@ -54,7 +54,7 @@ const props = defineProps({
}, },
dbType: { dbType: {
type: String, type: String,
default: '' default: '',
}, },
db: { db: {
type: String, type: String,
@@ -88,9 +88,9 @@ const props = defineProps({
}, },
height: { height: {
type: String, type: String,
default: '600' default: '600',
} },
}) });
const state = reactive({ const state = reactive({
dbId: 0, // 当前选中操作的数据库实例 dbId: 0, // 当前选中操作的数据库实例
@@ -108,13 +108,7 @@ const state = reactive({
updatedFields: [] as UpdateFieldsMeta[], // 各个tab表被修改的字段信息 updatedFields: [] as UpdateFieldsMeta[], // 各个tab表被修改的字段信息
}); });
const { const { tableHeight, datas } = toRefs(state);
tableHeight,
datas,
sortable,
loading,
showColumnTip,
} = toRefs(state);
watch(props, (newValue: any) => { watch(props, (newValue: any) => {
setState(newValue); setState(newValue);
@@ -123,7 +117,7 @@ watch(props, (newValue: any) => {
onMounted(async () => { onMounted(async () => {
console.log('in DbTable mounted'); console.log('in DbTable mounted');
setState(props); setState(props);
}) });
const setState = (props: any) => { const setState = (props: any) => {
state.dbId = props.dbId; state.dbId = props.dbId;
@@ -137,7 +131,7 @@ const setState = (props: any) => {
state.columns = props.columns; state.columns = props.columns;
state.showColumnTip = props.showColumnTip; state.showColumnTip = props.showColumnTip;
state.emptyText = props.emptyText; state.emptyText = props.emptyText;
} };
const getColumnTip = (column: any) => { const getColumnTip = (column: any) => {
const comment = column.columnComment; const comment = column.columnComment;
@@ -181,7 +175,7 @@ const cellClick = (row: any, column: any, cell: any) => {
row[property] = input.value; row[property] = input.value;
cell.replaceChildren(div); cell.replaceChildren(div);
if (input.value !== text) { if (input.value !== text) {
let currentUpdatedFields = state.updatedFields let currentUpdatedFields = state.updatedFields;
const dbInst = getNowDbInst(); const dbInst = getNowDbInst();
// 主键 // 主键
const primaryKey = await dbInst.loadTableColumn(state.db, state.table); const primaryKey = await dbInst.loadTableColumn(state.db, state.table);
@@ -189,73 +183,75 @@ const cellClick = (row: any, column: any, cell: any) => {
// 更新字段列信息 // 更新字段列信息
const updateColumn = await dbInst.loadTableColumn(state.db, state.table, property); const updateColumn = await dbInst.loadTableColumn(state.db, state.table, property);
const newField = { const newField = {
div, row, div,
row,
fieldName: property, fieldName: property,
fieldType: updateColumn.columnType, fieldType: updateColumn.columnType,
oldValue: text, oldValue: text,
newValue: input.value newValue: input.value,
} as FieldsMeta; } as FieldsMeta;
// 被修改的字段 // 被修改的字段
const primaryKeyFields = currentUpdatedFields.filter((meta) => meta.primaryKey === primaryKeyValue) const primaryKeyFields = currentUpdatedFields.filter((meta) => meta.primaryKey === primaryKeyValue);
let hasKey = false; let hasKey = false;
if (primaryKeyFields.length <= 0) { if (primaryKeyFields.length <= 0) {
primaryKeyFields[0] = { primaryKeyFields[0] = {
primaryKey: primaryKeyValue, primaryKey: primaryKeyValue,
primaryKeyName: primaryKey.columnName, primaryKeyName: primaryKey.columnName,
primaryKeyType: primaryKey.columnType, primaryKeyType: primaryKey.columnType,
fields: [newField] fields: [newField],
} };
} else { } else {
hasKey = true hasKey = true;
let hasField = primaryKeyFields[0].fields.some(a => { let hasField = primaryKeyFields[0].fields.some((a) => {
if (a.fieldName === newField.fieldName) { if (a.fieldName === newField.fieldName) {
a.newValue = newField.newValue a.newValue = newField.newValue;
} }
return a.fieldName === newField.fieldName return a.fieldName === newField.fieldName;
}) });
if (!hasField) { if (!hasField) {
primaryKeyFields[0].fields.push(newField) primaryKeyFields[0].fields.push(newField);
} }
} }
let fields = primaryKeyFields[0].fields let fields = primaryKeyFields[0].fields;
const fieldsParam = fields.filter((a) => { const fieldsParam = fields.filter((a) => {
if (a.fieldName === column.property) { if (a.fieldName === column.property) {
a.newValue = input.value a.newValue = input.value;
} }
return a.fieldName === column.property return a.fieldName === column.property;
}) });
const field = fieldsParam.length > 0 && fieldsParam[0] || {} as FieldsMeta const field = (fieldsParam.length > 0 && fieldsParam[0]) || ({} as FieldsMeta);
if (field.oldValue === input.value) { // 新值=旧值 if (field.oldValue === input.value) {
// 新值=旧值
// 删除数据 // 删除数据
div.classList.remove('update_field_active') div.classList.remove('update_field_active');
let delIndex: number[] = []; let delIndex: number[] = [];
currentUpdatedFields.forEach((a, i) => { currentUpdatedFields.forEach((a, i) => {
if (a.primaryKey === primaryKeyValue) { if (a.primaryKey === primaryKeyValue) {
a.fields = a.fields && a.fields.length > 0 ? a.fields.filter(f => f.fieldName !== column.property) : []; a.fields = a.fields && a.fields.length > 0 ? a.fields.filter((f) => f.fieldName !== column.property) : [];
a.fields.length <= 0 && delIndex.push(i) a.fields.length <= 0 && delIndex.push(i);
} }
}); });
delIndex.forEach(i => delete currentUpdatedFields[i]) delIndex.forEach((i) => delete currentUpdatedFields[i]);
currentUpdatedFields = currentUpdatedFields.filter(a => a) currentUpdatedFields = currentUpdatedFields.filter((a) => a);
} else { } else {
// 新增数据 // 新增数据
div.classList.add('update_field_active') div.classList.add('update_field_active');
if (hasKey) { if (hasKey) {
currentUpdatedFields.forEach((value, index, array) => { currentUpdatedFields.forEach((value, index, array) => {
if (value.primaryKey === primaryKeyValue) { if (value.primaryKey === primaryKeyValue) {
array[index].fields = fields array[index].fields = fields;
} }
}) });
} else { } else {
currentUpdatedFields.push({ currentUpdatedFields.push({
primaryKey: primaryKeyValue, primaryKey: primaryKeyValue,
primaryKeyName: primaryKey.columnName, primaryKeyName: primaryKey.columnName,
primaryKeyType: primaryKey.columnType, primaryKeyType: primaryKey.columnType,
fields fields,
}) });
} }
} }
state.updatedFields = currentUpdatedFields; state.updatedFields = currentUpdatedFields;
@@ -266,7 +262,7 @@ const cellClick = (row: any, column: any, cell: any) => {
}; };
const submitUpdateFields = () => { const submitUpdateFields = () => {
const dbInst = DbInst.getInst(state.dbId) const dbInst = DbInst.getInst(state.dbId);
let currentUpdatedFields = state.updatedFields; let currentUpdatedFields = state.updatedFields;
if (currentUpdatedFields.length <= 0) { if (currentUpdatedFields.length <= 0) {
return; return;
@@ -274,58 +270,62 @@ const submitUpdateFields = () => {
const db = state.db; const db = state.db;
let res = ''; let res = '';
let divs: HTMLElement[] = []; let divs: HTMLElement[] = [];
currentUpdatedFields.forEach(a => { currentUpdatedFields.forEach((a) => {
let sql = `UPDATE ${dbInst.wrapName(state.table)} SET `; let sql = `UPDATE ${dbInst.wrapName(state.table)} SET `;
let primaryKey = a.primaryKey; let primaryKey = a.primaryKey;
let primaryKeyType = a.primaryKeyType; let primaryKeyType = a.primaryKeyType;
let primaryKeyName = a.primaryKeyName; let primaryKeyName = a.primaryKeyName;
a.fields.forEach(f => { a.fields.forEach((f) => {
sql += ` ${dbInst.wrapName(f.fieldName)} = ${DbInst.wrapColumnValue(f.fieldType, f.newValue)},` sql += ` ${dbInst.wrapName(f.fieldName)} = ${DbInst.wrapColumnValue(f.fieldType, f.newValue)},`;
// 如果修改的字段是主键 // 如果修改的字段是主键
if (f.fieldName === primaryKeyName) { if (f.fieldName === primaryKeyName) {
primaryKey = f.oldValue primaryKey = f.oldValue;
} }
divs.push(f.div) divs.push(f.div);
}) });
sql = sql.substring(0, sql.length - 1) sql = sql.substring(0, sql.length - 1);
sql += ` WHERE ${dbInst.wrapName(primaryKeyName)} = ${DbInst.wrapColumnValue(primaryKeyType, primaryKey)} ;` sql += ` WHERE ${dbInst.wrapName(primaryKeyName)} = ${DbInst.wrapColumnValue(primaryKeyType, primaryKey)} ;`;
res += sql; res += sql;
}) });
dbInst.promptExeSql(db, res, () => { }, () => { dbInst.promptExeSql(
db,
res,
() => {},
() => {
currentUpdatedFields = []; currentUpdatedFields = [];
divs.forEach(a => { divs.forEach((a) => {
a.classList.remove('update_field_active'); a.classList.remove('update_field_active');
}) });
state.updatedFields = []; state.updatedFields = [];
changeUpdatedField(); changeUpdatedField();
});
} }
);
};
const cancelUpdateFields = () => { const cancelUpdateFields = () => {
state.updatedFields.forEach((a: any) => { state.updatedFields.forEach((a: any) => {
a.fields.forEach((b: any) => { a.fields.forEach((b: any) => {
b.div.classList.remove('update_field_active') b.div.classList.remove('update_field_active');
b.row[b.fieldName] = b.oldValue b.row[b.fieldName] = b.oldValue;
}) });
}) });
state.updatedFields = []; state.updatedFields = [];
changeUpdatedField(); changeUpdatedField();
} };
const changeUpdatedField = () => { const changeUpdatedField = () => {
emits('changeUpdatedField', state.updatedFields); emits('changeUpdatedField', state.updatedFields);
} };
const getNowDbInst = () => { const getNowDbInst = () => {
return DbInst.getInst(state.dbId); return DbInst.getInst(state.dbId);
} };
defineExpose({ defineExpose({
submitUpdateFields, submitUpdateFields,
cancelUpdateFields cancelUpdateFields,
}) });
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@@ -6,12 +6,12 @@
<el-link @click="onRunSql()" :underline="false" class="ml15" icon="VideoPlay"> </el-link> <el-link @click="onRunSql()" :underline="false" class="ml15" icon="VideoPlay"> </el-link>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-tooltip class="box-item" effect="dark" content="format sql" placement="top"> <el-tooltip :show-after="1000" class="box-item" effect="dark" content="format sql" placement="top">
<el-link @click="formatSql()" type="primary" :underline="false" icon="MagicStick"> </el-link> <el-link @click="formatSql()" type="primary" :underline="false" icon="MagicStick"> </el-link>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-tooltip class="box-item" effect="dark" content="commit" placement="top"> <el-tooltip :show-after="1000" class="box-item" effect="dark" content="commit" placement="top">
<el-link @click="onCommit()" type="success" :underline="false" icon="CircleCheck"> </el-link> <el-link @click="onCommit()" type="success" :underline="false" icon="CircleCheck"> </el-link>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
@@ -27,12 +27,12 @@
multiple multiple
:limit="100" :limit="100"
> >
<el-tooltip class="box-item" effect="dark" content="SQL脚本执行" placement="top"> <el-tooltip :show-after="1000" class="box-item" effect="dark" content="SQL脚本执行" placement="top">
<el-link type="success" :underline="false" icon="Document"></el-link> <el-link type="success" :underline="false" icon="Document"></el-link>
</el-tooltip> </el-tooltip>
</el-upload> </el-upload>
<el-divider direction="vertical" border-style="dashed" /> <el-divider direction="vertical" border-style="dashed" />
<el-tooltip class="box-item" effect="dark" content="limit" placement="top"> <el-tooltip :show-after="1000" class="box-item" effect="dark" content="limit" placement="top">
<el-link @click="onLimit()" type="success" :underline="false" icon="Operation"> </el-link> <el-link @click="onLimit()" type="success" :underline="false" icon="Operation"> </el-link>
</el-tooltip> </el-tooltip>
</div> </div>
@@ -153,7 +153,7 @@ const state = reactive({
hasUpdatedFileds: false, hasUpdatedFileds: false,
}); });
const { tableDataHeight, editorHeight, ti, execRes, table, sqlName, loading, hasUpdatedFileds } = toRefs(state); const { tableDataHeight, ti, execRes, table, loading, hasUpdatedFileds } = toRefs(state);
watch( watch(
() => props.editorHeight, () => props.editorHeight,

View File

@@ -74,7 +74,8 @@
:data="columns" :data="columns"
max-height="500" max-height="500"
size="small" size="small"
@row-click="(...event: any) => { @row-click="
(...event: any) => {
onConditionRowClick(event); onConditionRowClick(event);
} }
" "
@@ -153,6 +154,7 @@
<el-form ref="dataForm" :model="addDataDialog.data" label-width="auto" size="small"> <el-form ref="dataForm" :model="addDataDialog.data" label-width="auto" size="small">
<el-form-item <el-form-item
v-for="column in columns" v-for="column in columns"
:key="column.columnName"
class="w100" class="w100"
:prop="column.columnName" :prop="column.columnName"
:label="column.columnName" :label="column.columnName"

View File

@@ -54,7 +54,7 @@
<template #action="{ data }"> <template #action="{ data }">
<span v-auth="'machine:terminal'"> <span v-auth="'machine:terminal'">
<el-tooltip effect="customized" content="按住ctrl则为新标签打开" placement="top"> <el-tooltip :show-after="500" effect="customized" content="按住ctrl则为新标签打开" placement="top">
<el-button :disabled="data.status == -1" type="primary" @click="showTerminal(data, $event)" link>终端</el-button> <el-button :disabled="data.status == -1" type="primary" @click="showTerminal(data, $event)" link>终端</el-button>
</el-tooltip> </el-tooltip>

View File

@@ -5,7 +5,7 @@
<tag-tree @node-click="nodeClick" :load="loadNode"> <tag-tree @node-click="nodeClick" :load="loadNode">
<template #prefix="{ data }"> <template #prefix="{ data }">
<span v-if="data.type == NodeType.Mongo"> <span v-if="data.type == NodeType.Mongo">
<el-popover placement="right-start" title="mongo实例信息" trigger="hover" :width="210"> <el-popover :show-after="500" placement="right-start" title="mongo实例信息" trigger="hover" :width="210">
<template #reference> <template #reference>
<SvgIcon name="iconfont icon-op-mongo" :size="18" /> <SvgIcon name="iconfont icon-op-mongo" :size="18" />
</template> </template>

View File

@@ -7,7 +7,7 @@
<tag-tree @node-click="nodeClick" :load="loadNode"> <tag-tree @node-click="nodeClick" :load="loadNode">
<template #prefix="{ data }"> <template #prefix="{ data }">
<span v-if="data.type == NodeType.Redis"> <span v-if="data.type == NodeType.Redis">
<el-popover placement="right-start" title="redis实例信息" trigger="hover" :width="210"> <el-popover :show-after="500" placement="right-start" title="redis实例信息" trigger="hover" :width="210">
<template #reference> <template #reference>
<SvgIcon name="iconfont icon-op-redis" :size="18" /> <SvgIcon name="iconfont icon-op-redis" :size="18" />
</template> </template>
@@ -471,7 +471,7 @@ const removeDataTab = (targetName: string) => {
delete state.dataTabs[targetName]; delete state.dataTabs[targetName];
}; };
const keyTreeNodeExpand = (data: any, node: any, component: any) => { const keyTreeNodeExpand = (data: any, node: any) => {
state.keyTreeExpanded.add(data.key); state.keyTreeExpanded.add(data.key);
// async sort nodes // async sort nodes
if (!node.customSorted) { if (!node.customSorted) {
@@ -480,7 +480,7 @@ const keyTreeNodeExpand = (data: any, node: any, component: any) => {
} }
}; };
const keyTreeNodeCollapse = (data: any, node: any, component: any) => { const keyTreeNodeCollapse = (data: any) => {
state.keyTreeExpanded.delete(data.key); state.keyTreeExpanded.delete(data.key);
}; };

View File

@@ -49,7 +49,7 @@ func (d *Db) Dbs(rc *req.Ctx) {
} }
queryCond.TagIds = tagIds queryCond.TagIds = tagIds
res, err := d.DbApp.GetPageList(queryCond, page, new([]vo.SelectDataDbVO)) res, err := d.DbApp.GetPageList(queryCond, page, new([]vo.DbListVO))
biz.ErrIsNil(err) biz.ErrIsNil(err)
rc.ResData = res rc.ResData = res
} }

View File

@@ -24,7 +24,7 @@ type Instance struct {
// @router /api/instances [get] // @router /api/instances [get]
func (d *Instance) Instances(rc *req.Ctx) { func (d *Instance) Instances(rc *req.Ctx) {
queryCond, page := ginx.BindQueryAndPage[*entity.InstanceQuery](rc.GinCtx, new(entity.InstanceQuery)) queryCond, page := ginx.BindQueryAndPage[*entity.InstanceQuery](rc.GinCtx, new(entity.InstanceQuery))
res, err := d.InstanceApp.GetPageList(queryCond, page, new([]vo.SelectDataInstanceVO)) res, err := d.InstanceApp.GetPageList(queryCond, page, new([]vo.InstanceListVO))
biz.ErrIsNil(err) biz.ErrIsNil(err)
rc.ResData = res rc.ResData = res
} }

View File

@@ -2,8 +2,7 @@ package vo
import "time" import "time"
type SelectDataDbVO struct { type DbListVO struct {
//models.BaseModel
Id *int64 `json:"id"` Id *int64 `json:"id"`
Name *string `json:"name"` Name *string `json:"name"`
Database *string `json:"database"` Database *string `json:"database"`
@@ -14,6 +13,9 @@ type SelectDataDbVO struct {
InstanceId *int64 `json:"instanceId"` InstanceId *int64 `json:"instanceId"`
InstanceName *string `json:"instanceName"` InstanceName *string `json:"instanceName"`
InstanceType *string `json:"type"` InstanceType *string `json:"type"`
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`
CreateTime *time.Time `json:"createTime"` CreateTime *time.Time `json:"createTime"`
Creator *string `json:"creator"` Creator *string `json:"creator"`

View File

@@ -2,8 +2,7 @@ package vo
import "time" import "time"
type SelectDataInstanceVO struct { type InstanceListVO struct {
//models.BaseModel
Id *int64 `json:"id"` Id *int64 `json:"id"`
Name *string `json:"name"` Name *string `json:"name"`
Host *string `json:"host"` Host *string `json:"host"`

View File

@@ -19,7 +19,7 @@ func newDbRepo() repository.Db {
// 分页获取数据库信息列表 // 分页获取数据库信息列表
func (d *dbRepoImpl) GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) { func (d *dbRepoImpl) GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQueryWithTableName("t_db db"). qd := gormx.NewQueryWithTableName("t_db db").
Select("db.*, inst.name instance_name, inst.type instance_type"). Select("db.*, inst.name instance_name, inst.type instance_type, inst.host, inst.port, inst.username ").
Joins("JOIN t_db_instance inst ON db.instance_id = inst.id"). Joins("JOIN t_db_instance inst ON db.instance_id = inst.id").
Eq("db.instance_id", condition.InstanceId). Eq("db.instance_id", condition.InstanceId).
Like("db.database", condition.Database). Like("db.database", condition.Database).