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": {
"@element-plus/icons-vue": "^2.1.0",
"asciinema-player": "^3.6.2",
"axios": "^1.6.0",
"axios": "^1.6.2",
"countup.js": "^2.7.0",
"cropperjs": "^1.5.11",
"echarts": "^5.4.3",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,10 +31,6 @@
<el-link type="success" :underline="false" icon="Document"></el-link>
</el-tooltip>
</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 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>
<div class="db-table">
<el-row class="mb10">
<el-row class="mb5">
<el-popover v-model:visible="showDumpInfo" :width="470" placement="right" trigger="click">
<template #reference>
<el-button class="ml5" type="success" size="small">导出</el-button>
@@ -64,7 +64,7 @@
</template>
</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">
<el-link @click.prevent="showColumns(scope.row)" type="primary">字段</el-link>
<el-link class="ml5" @click.prevent="showTableIndex(scope.row)" type="success">索引</el-link>

View File

@@ -1,7 +1,7 @@
<template>
<div>
<el-row>
<el-col :span="4">
<el-col :span="5">
<tag-tree :loadTags="loadTags">
<template #prefix="{ data }">
<span v-if="data.type.value == MongoNodeType.Mongo">
@@ -42,7 +42,7 @@
</tag-tree>
</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">
<el-row v-if="nowColl">
<el-descriptions :column="10" size="small" border>

View File

@@ -1,7 +1,7 @@
<template>
<div>
<el-row>
<el-col :span="4">
<el-col :span="5">
<el-row type="flex" justify="space-between">
<el-col :span="24" class="flex-auto">
<tag-tree :loadTags="loadTags">
@@ -132,7 +132,7 @@
</div>
</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">
<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">

View File

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