refactor: 界面小调整

This commit is contained in:
meilin.huang
2023-11-15 12:28:49 +08:00
parent 0ae99cdaf9
commit 43230267b6
11 changed files with 115 additions and 110 deletions

View File

@@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.1.0", "@element-plus/icons-vue": "^2.1.0",
"asciinema-player": "^3.6.2", "asciinema-player": "^3.6.2",
"axios": "^1.6.0", "axios": "^1.6.2",
"countup.js": "^2.7.0", "countup.js": "^2.7.0",
"cropperjs": "^1.5.11", "cropperjs": "^1.5.11",
"echarts": "^5.4.3", "echarts": "^5.4.3",

View File

@@ -40,6 +40,12 @@ const openSetingsDrawer = () => {
setingsRef.value.openDrawer(); setingsRef.value.openDrawer();
}; };
const prefers = matchMedia('(prefers-color-scheme: dark)');
const switchDarkFollowOS = () => {
// 跟随系统主题
themeConfigStores.switchDark(prefers.matches);
};
// 页面加载时 // 页面加载时
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
@@ -53,9 +59,8 @@ onMounted(() => {
if (tc) { if (tc) {
themeConfigStores.setThemeConfig({ themeConfig: tc }); themeConfigStores.setThemeConfig({ themeConfig: tc });
document.documentElement.style.cssText = getLocal('themeConfigStyle'); document.documentElement.style.cssText = getLocal('themeConfigStyle');
themeConfigStores.switchDark(tc.isDark);
} }
switchDarkFollowOS();
// 是否开启水印 // 是否开启水印
useWatermark().then((res) => { useWatermark().then((res) => {

View File

@@ -1,9 +1,9 @@
import { randomUuid } from './string'; import { randomUuid } from './string';
const TokenKey = 'token'; const TokenKey = 'm-token';
const UserKey = 'user'; const UserKey = 'm-user';
const TagViewsKey = 'tagViews'; const TagViewsKey = 'm-tagViews';
const ClientIdKey = 'clientId'; const ClientIdKey = 'm-clientId';
// 获取请求token // 获取请求token
export function getToken(): string { export function getToken(): string {
@@ -64,13 +64,20 @@ export function getClientId(): string {
// 1. localStorage // 1. localStorage
// 设置永久缓存 // 设置永久缓存
export function setLocal(key: string, val: any) { export function setLocal(key: string, val: any) {
window.localStorage.setItem(key, JSON.stringify(val)); if (typeof val == 'object') {
val = JSON.stringify(val);
}
window.localStorage.setItem(key, val);
} }
// 获取永久缓存 // 获取永久缓存
export function getLocal(key: string) { export function getLocal(key: string) {
let json: any = window.localStorage.getItem(key); let val: any = window.localStorage.getItem(key);
return JSON.parse(json); try {
return JSON.parse(val);
} catch (e) {
return val;
}
} }
// 移除永久缓存 // 移除永久缓存
@@ -86,13 +93,20 @@ export function clearLocal() {
// 2. sessionStorage // 2. sessionStorage
// 设置临时缓存 // 设置临时缓存
export function setSession(key: string, val: any) { export function setSession(key: string, val: any) {
window.sessionStorage.setItem(key, JSON.stringify(val)); if (typeof val == 'object') {
val = JSON.stringify(val);
}
window.sessionStorage.setItem(key, val);
} }
// 获取临时缓存 // 获取临时缓存
export function getSession(key: string) { export function getSession(key: string) {
let json: any = window.sessionStorage.getItem(key); let val: any = window.sessionStorage.getItem(key);
return JSON.parse(json); try {
return JSON.parse(val);
} catch (e) {
return val;
}
} }
// 移除临时缓存 // 移除临时缓存

View File

@@ -1,5 +1,5 @@
declare interface UserInfoState<T = any> { declare interface UserInfoState<T = any> {
userInfo: any; userInfo: T;
} }
declare interface ThemeConfigState { declare interface ThemeConfigState {
@@ -92,7 +92,7 @@ declare interface TagsView {
} }
// TagsView 路由列表 // TagsView 路由列表
declare interface TagsViewsState<T = any> { declare interface TagsViewsState<> {
tagsViews: TagsView[]; tagsViews: TagsView[];
} }

View File

@@ -8,7 +8,7 @@
ref="treeRef" ref="treeRef"
:style="{ maxHeight: state.height, height: state.height, overflow: 'auto' }" :style="{ maxHeight: state.height, height: state.height, overflow: 'auto' }"
:highlight-current="true" :highlight-current="true"
:indent="7" :indent="10"
:load="loadNode" :load="loadNode"
:props="treeProps" :props="treeProps"
lazy lazy
@@ -190,6 +190,7 @@ defineExpose({
overflow: 'auto'; overflow: 'auto';
position: relative; position: relative;
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
border: 1px solid var(--el-border-color-light, #ebeef5); border: 1px solid var(--el-border-color-light, #ebeef5);
.el-tree { .el-tree {

View File

@@ -1,43 +1,8 @@
<template> <template>
<div class="db-sql-exec"> <div class="db-sql-exec">
<el-row class="mb5"> <el-row>
<el-col :span="4"> <el-col :span="5">
<el-button <tag-tree ref="tagTreeRef" :loadTags="loadTags">
:disabled="!state.db || !nowDbInst.id"
type="primary"
icon="plus"
@click="addQueryTab({ id: nowDbInst.id, dbs: nowDbInst.databases?.split(' ') }, state.db)"
size="small"
>新建查询</el-button
>
</el-col>
<el-col :span="20" v-if="state.db">
<el-descriptions :column="4" size="small" border style="height: 10px" class="ml5">
<el-descriptions-item label-align="right" label="tag">{{ nowDbInst.tagPath }}</el-descriptions-item>
<el-descriptions-item label-align="right">
<template #label>
<div>
<SvgIcon :name="DbInst.getIconName(nowDbInst.type)" :size="18" />
实例
</div>
</template>
{{ nowDbInst.id }}
<el-divider direction="vertical" border-style="dashed" />
{{ nowDbInst.name }}
<el-divider direction="vertical" border-style="dashed" />
{{ nowDbInst.host }}
</el-descriptions-item>
<el-descriptions-item label="库名" label-align="right">{{ state.db }}</el-descriptions-item>
</el-descriptions>
</el-col>
</el-row>
<el-row type="flex">
<el-col :span="4">
<tag-tree ref="tagTreeRef" :loadTags="loadTags" :height="state.tagTreeHeight">
<template #prefix="{ data }"> <template #prefix="{ data }">
<span v-if="data.type.value == SqlExecNodeType.DbInst"> <span v-if="data.type.value == SqlExecNodeType.DbInst">
<el-popover :show-after="500" placement="right-start" title="数据库实例信息" trigger="hover" :width="250"> <el-popover :show-after="500" placement="right-start" title="数据库实例信息" trigger="hover" :width="250">
@@ -81,8 +46,43 @@
</tag-tree> </tag-tree>
</el-col> </el-col>
<el-col :span="20"> <el-col :span="19">
<el-container id="data-exec" class="mt5 ml5"> <el-row>
<el-col :span="24" v-if="state.db">
<el-descriptions :column="4" size="small" border class="ml5">
<el-descriptions-item label-align="right" label="操作"
><el-button
:disabled="!state.db || !nowDbInst.id"
type="primary"
icon="Search"
@click="addQueryTab({ id: nowDbInst.id, dbs: nowDbInst.databases?.split(' ') }, state.db)"
size="small"
>新建查询</el-button
></el-descriptions-item
>
<el-descriptions-item label-align="right" label="tag">{{ nowDbInst.tagPath }}</el-descriptions-item>
<el-descriptions-item label-align="right">
<template #label>
<div>
<SvgIcon :name="DbInst.getIconName(nowDbInst.type)" :size="18" />
实例
</div>
</template>
{{ nowDbInst.id }}
<el-divider direction="vertical" border-style="dashed" />
{{ nowDbInst.name }}
<el-divider direction="vertical" border-style="dashed" />
{{ nowDbInst.host }}
</el-descriptions-item>
<el-descriptions-item label="库名" label-align="right">{{ state.db }}</el-descriptions-item>
</el-descriptions>
</el-col>
</el-row>
<div id="data-exec" class="mt5 ml5">
<el-tabs <el-tabs
v-if="state.tabs.size > 0" v-if="state.tabs.size > 0"
type="card" type="card"
@@ -143,7 +143,7 @@
/> />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-container> </div>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@@ -157,7 +157,7 @@ import { DbInst, TabInfo, TabType, registerDbCompletionItemProvider } from './db
import { TagTreeNode, NodeType } from '../component/tag'; import { TagTreeNode, NodeType } from '../component/tag';
import TagTree from '../component/TagTree.vue'; import TagTree from '../component/TagTree.vue';
import { dbApi } from './api'; import { dbApi } from './api';
import { dispposeCompletionItemProvider } from '../../../components/monaco/completionItemProvider'; import { dispposeCompletionItemProvider } from '@/components/monaco/completionItemProvider';
import SvgIcon from '@/components/svgIcon/index.vue'; import SvgIcon from '@/components/svgIcon/index.vue';
import { ContextmenuItem } from '@/components/contextmenu/index'; import { ContextmenuItem } from '@/components/contextmenu/index';
@@ -203,10 +203,12 @@ const SqlIcon = {
// node节点点击时触发改变db事件 // node节点点击时触发改变db事件
const nodeClickChangeDb = (nodeData: TagTreeNode) => { const nodeClickChangeDb = (nodeData: TagTreeNode) => {
const params = nodeData.params; const params = nodeData.params;
changeDb( if (params.db) {
{ id: params.id, host: `${params.host}:${params.port}`, name: params.name, type: params.type, tagPath: params.tagPath, databases: params.database }, changeDb(
params.db { id: params.id, host: `${params.host}`, name: params.name, type: params.type, tagPath: params.tagPath, databases: params.database },
); params.db
);
}
}; };
// tagpath 节点类型 // tagpath 节点类型
@@ -221,25 +223,23 @@ const NodeTypeTagPath = new NodeType(TagTreeNode.TagPath).withLoadNodesFunc(asyn
}); });
// 数据库实例节点类型 // 数据库实例节点类型
const NodeTypeDbInst = new NodeType(SqlExecNodeType.DbInst) const NodeTypeDbInst = new NodeType(SqlExecNodeType.DbInst).withLoadNodesFunc((parentNode: TagTreeNode) => {
.withLoadNodesFunc((parentNode: TagTreeNode) => { const params = parentNode.params;
const params = parentNode.params; const dbs = params.database.split(' ')?.sort();
const dbs = params.database.split(' ')?.sort(); return dbs.map((x: any) => {
return dbs.map((x: any) => { return new TagTreeNode(`${parentNode.key}.${x}`, x, NodeTypeDb)
return new TagTreeNode(`${parentNode.key}.${x}`, x, NodeTypeDb) .withParams({
.withParams({ tagPath: params.tagPath,
tagPath: params.tagPath, id: params.id,
id: params.id, name: params.name,
name: params.name, type: params.type,
type: params.type, host: `${params.host}:${params.port}`,
host: `${params.host}:${params.port}`, dbs: dbs,
dbs: dbs, db: x,
db: x, })
}) .withIcon(DbIcon);
.withIcon(DbIcon); });
}); });
})
.withNodeClickFunc(nodeClickChangeDb);
// 数据库节点 // 数据库节点
const NodeTypeDb = new NodeType(SqlExecNodeType.Db) const NodeTypeDb = new NodeType(SqlExecNodeType.Db)
@@ -369,7 +369,6 @@ const state = reactive({
dataTabsTableHeight: '600', dataTabsTableHeight: '600',
editorHeight: '600', editorHeight: '600',
tablesOpHeight: '600', tablesOpHeight: '600',
tagTreeHeight: window.innerHeight - 178 + 'px',
}); });
const { nowDbInst } = toRefs(state); const { nowDbInst } = toRefs(state);
@@ -389,9 +388,8 @@ onBeforeUnmount(() => {
*/ */
const setHeight = () => { const setHeight = () => {
state.editorHeight = window.innerHeight - 500 + 'px'; state.editorHeight = window.innerHeight - 500 + 'px';
state.dataTabsTableHeight = window.innerHeight - 250 + 'px'; state.dataTabsTableHeight = window.innerHeight - 255 + 'px';
state.tablesOpHeight = window.innerHeight - 220 + 'px'; state.tablesOpHeight = window.innerHeight - 220 + 'px';
state.tagTreeHeight = window.innerHeight - 165 + 'px';
}; };
/** /**
@@ -434,6 +432,7 @@ const loadTableData = async (db: any, dbName: string, tableName: string) => {
if (tableName == '') { if (tableName == '') {
return; return;
} }
changeDb(db, dbName);
const key = `${db.id}:\`${dbName}\`.${tableName}`; const key = `${db.id}:\`${dbName}\`.${tableName}`;
let tab = state.tabs.get(key); let tab = state.tabs.get(key);
@@ -462,6 +461,7 @@ const addQueryTab = async (db: any, dbName: string, sqlName: string = '') => {
ElMessage.warning('请选择数据库实例及对应的schema'); ElMessage.warning('请选择数据库实例及对应的schema');
return; return;
} }
changeDb(db, dbName);
const dbId = db.id; const dbId = db.id;
let label; let label;
@@ -513,6 +513,7 @@ const addTablesOpTab = async (db: any) => {
ElMessage.warning('请选择数据库实例及对应的schema'); ElMessage.warning('请选择数据库实例及对应的schema');
return; return;
} }
changeDb(db, dbName);
const dbId = db.id; const dbId = db.id;
let key = `表操作:${dbId}:${dbName}.tablesOp`; let key = `表操作:${dbId}:${dbName}.tablesOp`;
@@ -642,4 +643,3 @@ const getNowDbInfo = () => {
} }
} }
</style> </style>
../../../components/contextmenu

View File

@@ -31,10 +31,6 @@
<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-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-tooltip>
</div> </div>
<div style="float: right" class="fl"> <div style="float: right" class="fl">
@@ -464,17 +460,6 @@ const replaceSelection = (str: string, selection: any) => {
}); });
}; };
const onLimit = () => {
let position = monacoEditor.getPosition() as monaco.Position;
let newText = ' limit 10';
monacoEditor?.getModel()?.applyEdits([
{
range: new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column),
text: newText,
},
]);
};
/** /**
* 导出当前页数据 * 导出当前页数据
*/ */

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="db-table"> <div class="db-table">
<el-row class="mb10"> <el-row class="mb5">
<el-popover v-model:visible="showDumpInfo" :width="470" placement="right" trigger="click"> <el-popover v-model:visible="showDumpInfo" :width="470" placement="right" trigger="click">
<template #reference> <template #reference>
<el-button class="ml5" type="success" size="small">导出</el-button> <el-button class="ml5" type="success" size="small">导出</el-button>
@@ -64,7 +64,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column property="createTime" label="创建时间" min-width="150"> </el-table-column> <el-table-column property="createTime" label="创建时间" min-width="150"> </el-table-column>
<el-table-column label="更多信息" min-width="140"> <el-table-column label="更多信息" min-width="160">
<template #default="scope"> <template #default="scope">
<el-link @click.prevent="showColumns(scope.row)" type="primary">字段</el-link> <el-link @click.prevent="showColumns(scope.row)" type="primary">字段</el-link>
<el-link class="ml5" @click.prevent="showTableIndex(scope.row)" type="success">索引</el-link> <el-link class="ml5" @click.prevent="showTableIndex(scope.row)" type="success">索引</el-link>

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<el-row> <el-row>
<el-col :span="4"> <el-col :span="5">
<tag-tree :loadTags="loadTags"> <tag-tree :loadTags="loadTags">
<template #prefix="{ data }"> <template #prefix="{ data }">
<span v-if="data.type.value == MongoNodeType.Mongo"> <span v-if="data.type.value == MongoNodeType.Mongo">
@@ -42,7 +42,7 @@
</tag-tree> </tag-tree>
</el-col> </el-col>
<el-col :span="20"> <el-col :span="19">
<div id="mongo-tab" class="ml5" style="border: 1px solid var(--el-border-color-light, #ebeef5); margin-top: 1px"> <div id="mongo-tab" class="ml5" style="border: 1px solid var(--el-border-color-light, #ebeef5); margin-top: 1px">
<el-row v-if="nowColl"> <el-row v-if="nowColl">
<el-descriptions :column="10" size="small" border> <el-descriptions :column="10" size="small" border>

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<el-row> <el-row>
<el-col :span="4"> <el-col :span="5">
<el-row type="flex" justify="space-between"> <el-row type="flex" justify="space-between">
<el-col :span="24" class="flex-auto"> <el-col :span="24" class="flex-auto">
<tag-tree :loadTags="loadTags"> <tag-tree :loadTags="loadTags">
@@ -132,7 +132,7 @@
</div> </div>
</el-col> </el-col>
<el-col :span="13" style="border-left: 1px solid var(--el-card-border-color)"> <el-col :span="12" style="border-left: 1px solid var(--el-card-border-color)">
<div class="ml5"> <div class="ml5">
<el-tabs @tab-remove="removeDataTab" style="width: 100%" v-model="state.activeName"> <el-tabs @tab-remove="removeDataTab" style="width: 100%" v-model="state.activeName">
<el-tab-pane closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label" :name="dt.key"> <el-tab-pane closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label" :name="dt.key">

View File

@@ -628,10 +628,10 @@ asynckit@^0.4.0:
resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz" resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
axios@^1.6.0: axios@^1.6.2:
version "1.6.0" version "1.6.2"
resolved "https://registry.npmmirror.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102" resolved "https://registry.npmmirror.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2"
integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg== integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==
dependencies: dependencies:
follow-redirects "^1.15.0" follow-redirects "^1.15.0"
form-data "^4.0.0" form-data "^4.0.0"