添加数据库管理工具,修改部分问题
This commit is contained in:
parent
37b2ad396f
commit
3c9a1651ea
|
|
@ -14,6 +14,8 @@ declare module '@vue/runtime-core' {
|
||||||
ElCard: typeof import('element-plus/es')['ElCard']
|
ElCard: typeof import('element-plus/es')['ElCard']
|
||||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
|
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
||||||
|
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
||||||
ElContainer: typeof import('element-plus/es')['ElContainer']
|
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||||
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
||||||
|
|
@ -35,15 +37,19 @@ declare module '@vue/runtime-core' {
|
||||||
ElOption: typeof import('element-plus/es')['ElOption']
|
ElOption: typeof import('element-plus/es')['ElOption']
|
||||||
ElPagination: typeof import('element-plus/es')['ElPagination']
|
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||||
ElProgress: typeof import('element-plus/es')['ElProgress']
|
ElProgress: typeof import('element-plus/es')['ElProgress']
|
||||||
|
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||||
|
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||||
ElRow: typeof import('element-plus/es')['ElRow']
|
ElRow: typeof import('element-plus/es')['ElRow']
|
||||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
||||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||||
|
ElStatistic: typeof import('element-plus/es')['ElStatistic']
|
||||||
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
||||||
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
||||||
ElTable: typeof import('element-plus/es')['ElTable']
|
ElTable: typeof import('element-plus/es')['ElTable']
|
||||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||||
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
||||||
ElTabs: typeof import('element-plus/es')['ElTabs']
|
ElTabs: typeof import('element-plus/es')['ElTabs']
|
||||||
|
ElTag: typeof import('element-plus/es')['ElTag']
|
||||||
ElTimeline: typeof import('element-plus/es')['ElTimeline']
|
ElTimeline: typeof import('element-plus/es')['ElTimeline']
|
||||||
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
|
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
|
||||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<title>大学生学业作品AI生成工具</title>
|
<title>集成AI工具</title>
|
||||||
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_830376_92o68tc95je.css">
|
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_830376_92o68tc95je.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@agoose77/markdown-it-mermaid": "^1.1.0",
|
"@agoose77/markdown-it-mermaid": "^1.1.0",
|
||||||
|
"@codemirror/basic-setup": "^0.20.0",
|
||||||
|
"@codemirror/lang-sql": "^6.9.1",
|
||||||
|
"@codemirror/state": "^6.5.2",
|
||||||
|
"@codemirror/theme-one-dark": "^6.1.3",
|
||||||
|
"@codemirror/view": "^6.38.1",
|
||||||
"@element-plus/icons-vue": "*",
|
"@element-plus/icons-vue": "*",
|
||||||
"@wangeditor/editor": "^5.1.23",
|
"@wangeditor/editor": "^5.1.23",
|
||||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||||
|
|
@ -264,6 +269,112 @@
|
||||||
"@lezer/common": "^1.0.0"
|
"@lezer/common": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup": {
|
||||||
|
"version": "0.20.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/basic-setup/-/basic-setup-0.20.0.tgz",
|
||||||
|
"integrity": "sha512-W/ERKMLErWkrVLyP5I8Yh8PXl4r+WFNkdYVSzkXYPQv2RMPSkWpr2BgggiSJ8AHF/q3GuApncDD8I4BZz65fyg==",
|
||||||
|
"deprecated": "In version 6.0, this package has been renamed to just 'codemirror'",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/autocomplete": "^0.20.0",
|
||||||
|
"@codemirror/commands": "^0.20.0",
|
||||||
|
"@codemirror/language": "^0.20.0",
|
||||||
|
"@codemirror/lint": "^0.20.0",
|
||||||
|
"@codemirror/search": "^0.20.0",
|
||||||
|
"@codemirror/state": "^0.20.0",
|
||||||
|
"@codemirror/view": "^0.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup/node_modules/@codemirror/autocomplete": {
|
||||||
|
"version": "0.20.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-0.20.3.tgz",
|
||||||
|
"integrity": "sha512-lYB+NPGP+LEzAudkWhLfMxhTrxtLILGl938w+RcFrGdrIc54A+UgmCoz+McE3IYRFp4xyQcL4uFJwo+93YdgHw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/language": "^0.20.0",
|
||||||
|
"@codemirror/state": "^0.20.0",
|
||||||
|
"@codemirror/view": "^0.20.0",
|
||||||
|
"@lezer/common": "^0.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup/node_modules/@codemirror/commands": {
|
||||||
|
"version": "0.20.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-0.20.0.tgz",
|
||||||
|
"integrity": "sha512-v9L5NNVA+A9R6zaFvaTbxs30kc69F6BkOoiEbeFw4m4I0exmDEKBILN6mK+GksJtvTzGBxvhAPlVFTdQW8GB7Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/language": "^0.20.0",
|
||||||
|
"@codemirror/state": "^0.20.0",
|
||||||
|
"@codemirror/view": "^0.20.0",
|
||||||
|
"@lezer/common": "^0.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup/node_modules/@codemirror/language": {
|
||||||
|
"version": "0.20.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.20.2.tgz",
|
||||||
|
"integrity": "sha512-WB3Bnuusw0xhVvhBocieYKwJm04SOk5bPoOEYksVHKHcGHFOaYaw+eZVxR4gIqMMcGzOIUil0FsCmFk8yrhHpw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/state": "^0.20.0",
|
||||||
|
"@codemirror/view": "^0.20.0",
|
||||||
|
"@lezer/common": "^0.16.0",
|
||||||
|
"@lezer/highlight": "^0.16.0",
|
||||||
|
"@lezer/lr": "^0.16.0",
|
||||||
|
"style-mod": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup/node_modules/@codemirror/lint": {
|
||||||
|
"version": "0.20.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-0.20.3.tgz",
|
||||||
|
"integrity": "sha512-06xUScbbspZ8mKoODQCEx6hz1bjaq9m8W8DxdycWARMiiX1wMtfCh/MoHpaL7ws/KUMwlsFFfp2qhm32oaCvVA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/state": "^0.20.0",
|
||||||
|
"@codemirror/view": "^0.20.2",
|
||||||
|
"crelt": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup/node_modules/@codemirror/search": {
|
||||||
|
"version": "0.20.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-0.20.1.tgz",
|
||||||
|
"integrity": "sha512-ROe6gRboQU5E4z6GAkNa2kxhXqsGNbeLEisbvzbOeB7nuDYXUZ70vGIgmqPu0tB+1M3F9yWk6W8k2vrFpJaD4Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/state": "^0.20.0",
|
||||||
|
"@codemirror/view": "^0.20.0",
|
||||||
|
"crelt": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup/node_modules/@codemirror/state": {
|
||||||
|
"version": "0.20.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.20.1.tgz",
|
||||||
|
"integrity": "sha512-ms0tlV5A02OK0pFvTtSUGMLkoarzh1F8mr6jy1cD7ucSC2X/VLHtQCxfhdSEGqTYlQF2hoZtmLv+amqhdgbwjQ=="
|
||||||
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup/node_modules/@codemirror/view": {
|
||||||
|
"version": "0.20.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.20.7.tgz",
|
||||||
|
"integrity": "sha512-pqEPCb9QFTOtHgAH5XU/oVy9UR/Anj6r+tG5CRmkNVcqSKEPmBU05WtN/jxJCFZBXf6HumzWC9ydE4qstO3TxQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/state": "^0.20.0",
|
||||||
|
"style-mod": "^4.0.0",
|
||||||
|
"w3c-keyname": "^2.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup/node_modules/@lezer/common": {
|
||||||
|
"version": "0.16.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.16.1.tgz",
|
||||||
|
"integrity": "sha512-qPmG7YTZ6lATyTOAWf8vXE+iRrt1NJd4cm2nJHK+v7X9TsOF6+HtuU/ctaZy2RCrluxDb89hI6KWQ5LfQGQWuA=="
|
||||||
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup/node_modules/@lezer/highlight": {
|
||||||
|
"version": "0.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-0.16.0.tgz",
|
||||||
|
"integrity": "sha512-iE5f4flHlJ1g1clOStvXNLbORJoiW4Kytso6ubfYzHnaNo/eo5SKhxs4wv/rtvwZQeZrK3we8S9SyA7OGOoRKQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@lezer/common": "^0.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@codemirror/basic-setup/node_modules/@lezer/lr": {
|
||||||
|
"version": "0.16.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.16.3.tgz",
|
||||||
|
"integrity": "sha512-pau7um4eAw94BEuuShUIeQDTf3k4Wt6oIUOYxMmkZgDHdqtIcxWND4LRxi8nI9KuT4I1bXQv67BCapkxt7Ywqw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@lezer/common": "^0.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@codemirror/commands": {
|
"node_modules/@codemirror/commands": {
|
||||||
"version": "6.8.1",
|
"version": "6.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz",
|
||||||
|
|
@ -275,6 +386,19 @@
|
||||||
"@lezer/common": "^1.1.0"
|
"@lezer/common": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@codemirror/lang-sql": {
|
||||||
|
"version": "6.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.9.1.tgz",
|
||||||
|
"integrity": "sha512-ecSk3gm/mlINcURMcvkCZmXgdzPSq8r/yfCtTB4vgqGGIbBC2IJIAy7GqYTy5pgBEooTVmHP2GZK6Z7h63CDGg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/autocomplete": "^6.0.0",
|
||||||
|
"@codemirror/language": "^6.0.0",
|
||||||
|
"@codemirror/state": "^6.0.0",
|
||||||
|
"@lezer/common": "^1.2.0",
|
||||||
|
"@lezer/highlight": "^1.0.0",
|
||||||
|
"@lezer/lr": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@codemirror/language": {
|
"node_modules/@codemirror/language": {
|
||||||
"version": "6.11.0",
|
"version": "6.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.0.tgz",
|
||||||
|
|
@ -316,12 +440,24 @@
|
||||||
"@marijn/find-cluster-break": "^1.0.0"
|
"@marijn/find-cluster-break": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@codemirror/theme-one-dark": {
|
||||||
|
"version": "6.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz",
|
||||||
|
"integrity": "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/language": "^6.0.0",
|
||||||
|
"@codemirror/state": "^6.0.0",
|
||||||
|
"@codemirror/view": "^6.0.0",
|
||||||
|
"@lezer/highlight": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@codemirror/view": {
|
"node_modules/@codemirror/view": {
|
||||||
"version": "6.36.8",
|
"version": "6.38.1",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.8.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.1.tgz",
|
||||||
"integrity": "sha512-yoRo4f+FdnD01fFt4XpfpMCcCAo9QvZOtbrXExn4SqzH32YC6LgzqxfLZw/r6Ge65xyY03mK/UfUqrVw1gFiFg==",
|
"integrity": "sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.5.0",
|
"@codemirror/state": "^6.5.0",
|
||||||
|
"crelt": "^1.0.6",
|
||||||
"style-mod": "^4.1.0",
|
"style-mod": "^4.1.0",
|
||||||
"w3c-keyname": "^2.2.4"
|
"w3c-keyname": "^2.2.4"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@agoose77/markdown-it-mermaid": "^1.1.0",
|
"@agoose77/markdown-it-mermaid": "^1.1.0",
|
||||||
|
"@codemirror/basic-setup": "^0.20.0",
|
||||||
|
"@codemirror/lang-sql": "^6.9.1",
|
||||||
|
"@codemirror/state": "^6.5.2",
|
||||||
|
"@codemirror/theme-one-dark": "^6.1.3",
|
||||||
|
"@codemirror/view": "^6.38.1",
|
||||||
"@element-plus/icons-vue": "*",
|
"@element-plus/icons-vue": "*",
|
||||||
"@wangeditor/editor": "^5.1.23",
|
"@wangeditor/editor": "^5.1.23",
|
||||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ export const menuData: Menus[] = [
|
||||||
'id': '71',
|
'id': '71',
|
||||||
'title': '用户功能管理',
|
'title': '用户功能管理',
|
||||||
'index': '71',
|
'index': '71',
|
||||||
'icon': 'HomeFilled',
|
'icon': 'UserFilled',
|
||||||
'children': [
|
'children': [
|
||||||
{
|
{
|
||||||
id: '51',
|
id: '51',
|
||||||
|
|
@ -234,13 +234,13 @@ export const menuData: Menus[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '59',
|
id: '59',
|
||||||
icon: 'ChatDotSquare',
|
icon: 'Select',
|
||||||
index: '/project-select',
|
index: '/project-select',
|
||||||
title: '项目选择',
|
title: '项目选择',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '72',
|
id: '72',
|
||||||
icon: 'ChatDotSquare',
|
icon: 'Edit',
|
||||||
index: '/db-manage',
|
index: '/db-manage',
|
||||||
title: '数据库管理工具',
|
title: '数据库管理工具',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="content-title">支持拖拽</div>
|
<div class="content-title">支持拖拽</div>
|
||||||
<el-upload class="upload-demo" drag
|
<el-upload class="upload-demo" drag
|
||||||
action="http://127.0.0.1:41000/file/upload" multiple
|
action="https://pm.ljsea.top/file/upload" multiple
|
||||||
:data="uploadData"
|
:data="uploadData"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
:on-success="handleSuccess"
|
:on-success="handleSuccess"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ export interface DatabaseConfig {
|
||||||
ID: number;
|
ID: number;
|
||||||
CreatedAt: string;
|
CreatedAt: string;
|
||||||
UpdatedAt: string;
|
UpdatedAt: string;
|
||||||
DeletedAt: null;
|
DeletedAt: string | null;
|
||||||
UserID: number;
|
UserID: number;
|
||||||
DB_IP: string;
|
DB_IP: string;
|
||||||
DB_Port: number;
|
DB_Port: number;
|
||||||
|
|
@ -15,3 +15,29 @@ export interface DatabaseConfig {
|
||||||
DB_STATUS: number;
|
DB_STATUS: number;
|
||||||
Name: string;
|
Name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ISQLOperation {
|
||||||
|
/** 记录ID */
|
||||||
|
ID: number;
|
||||||
|
|
||||||
|
/** 创建时间 */
|
||||||
|
CreatedAt: string;
|
||||||
|
|
||||||
|
/** 更新时间 */
|
||||||
|
UpdatedAt: string;
|
||||||
|
|
||||||
|
/** 删除时间,null表示未删除 */
|
||||||
|
DeletedAt: string | null;
|
||||||
|
|
||||||
|
/** 操作用户ID */
|
||||||
|
UserID: number;
|
||||||
|
|
||||||
|
/** 执行的SQL语句 */
|
||||||
|
SQL: string;
|
||||||
|
|
||||||
|
/** 数据库ID */
|
||||||
|
DB_ID: number;
|
||||||
|
|
||||||
|
/** 执行状态,0可能表示成功或初始状态 */
|
||||||
|
Status: number;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,525 @@
|
||||||
|
<template>
|
||||||
|
<div class="db-manage-container">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<!-- 左侧数据库表列表 -->
|
||||||
|
<el-col :span="4">
|
||||||
|
<div class="table-list">
|
||||||
|
<h3>数据库表</h3>
|
||||||
|
<el-scrollbar height="400px">
|
||||||
|
<el-tree
|
||||||
|
:data="tables"
|
||||||
|
node-key="name"
|
||||||
|
:props="defaultProps"
|
||||||
|
@node-click="handleTableClick"
|
||||||
|
/>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<!-- 右侧主内容区 -->
|
||||||
|
<el-col :span="20">
|
||||||
|
<!-- 顶部下拉选择框 -->
|
||||||
|
<el-row :gutter="20" class="mb-20">
|
||||||
|
<el-col :span="10">
|
||||||
|
<el-select
|
||||||
|
v-model="selectedDatabase"
|
||||||
|
filterable
|
||||||
|
placeholder="请选择数据库"
|
||||||
|
class="w-100"
|
||||||
|
@change="getRunSQLHistory"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<el-icon><search /></el-icon>
|
||||||
|
</template>
|
||||||
|
<el-option
|
||||||
|
v-for="item in databases"
|
||||||
|
:key="item.ID"
|
||||||
|
:label="item.Name"
|
||||||
|
:value="item.ID"
|
||||||
|
>
|
||||||
|
<span>{{ item.Name }}</span>
|
||||||
|
<span class="option-actions">
|
||||||
|
<el-icon @click.stop="editDatabase(item)"><edit /></el-icon>
|
||||||
|
<el-icon @click.stop="deleteDatabase(item)"
|
||||||
|
><delete
|
||||||
|
/></el-icon>
|
||||||
|
</span>
|
||||||
|
</el-option>
|
||||||
|
<template #append>
|
||||||
|
<el-button icon="plus" @click="showAddDatabaseDialog" />
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1">
|
||||||
|
<el-icon @click="showAddDatabaseDialog"><FolderAdd /></el-icon>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-select
|
||||||
|
v-model="selectedConnection"
|
||||||
|
filterable
|
||||||
|
placeholder="请选择服务器"
|
||||||
|
class="w-100"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<el-icon><search /></el-icon>
|
||||||
|
</template>
|
||||||
|
<el-option
|
||||||
|
v-for="item in connections"
|
||||||
|
:key="item.domain"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.domain"
|
||||||
|
>
|
||||||
|
<span>{{ item.name }}</span>
|
||||||
|
</el-option>
|
||||||
|
<template #append>
|
||||||
|
<el-button circle @click="showAddDatabaseDialog" />
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="3">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="showSQLHistoryDialog"
|
||||||
|
class="w-100"
|
||||||
|
:loading="executing"
|
||||||
|
>执行历史SQL</el-button
|
||||||
|
>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- SQL输入框和执行按钮 -->
|
||||||
|
<el-row class="mb-20">
|
||||||
|
<el-col :span="20">
|
||||||
|
<SqlEditor v-model="sqlQuery" />
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="4">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="executeSql"
|
||||||
|
class="w-100"
|
||||||
|
:loading="executing"
|
||||||
|
>
|
||||||
|
执行
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 结果表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
style="width: 100%"
|
||||||
|
height="400px"
|
||||||
|
v-horizontal-scroll="'always'"
|
||||||
|
v-loading="loading"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
:key="column.prop"
|
||||||
|
:prop="column.prop"
|
||||||
|
:label="column.label"
|
||||||
|
/>
|
||||||
|
</el-table>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 添加/编辑数据库对话框 -->
|
||||||
|
<el-dialog
|
||||||
|
v-model="databaseDialogVisible"
|
||||||
|
:title="isEditDatabase ? '编辑数据库' : '添加数据库'"
|
||||||
|
width="50%"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="数据库名称" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_NAME"
|
||||||
|
placeholder="请输入数据库名称"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据库密码" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_Password"
|
||||||
|
type="password"
|
||||||
|
placeholder="请输入数据库密码"
|
||||||
|
show-password
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户名" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_User"
|
||||||
|
placeholder="请输入用户名称"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="IP或域名" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_IP"
|
||||||
|
placeholder="请输入数据库ip或域名"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据库端口" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_Port"
|
||||||
|
placeholder="请输入数据库端口"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据库类型" required>
|
||||||
|
<el-select
|
||||||
|
v-model="databaseForm.DB_Type"
|
||||||
|
placeholder="请选择数据库类型"
|
||||||
|
>
|
||||||
|
<el-option label="MySQL" value="0" />
|
||||||
|
<el-option label="PostgreSQL" value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="描述信息">
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_Desc"
|
||||||
|
placeholder="请输入备注信息"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="databaseDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="saveDatabase">保存</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="sqlHistoryDialogVisible"
|
||||||
|
title="SQL执行历史"
|
||||||
|
width="50%"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-table :data="sqlHistory" stripe width="100%" height="600px" fit>
|
||||||
|
<el-table-column prop="ID" label="SQLID" width="150"></el-table-column>
|
||||||
|
<el-table-column prop="SQL" label="SQL" width="500"> </el-table-column>
|
||||||
|
<el-table-column label="操作" width="270">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="mini"
|
||||||
|
@click.prevent="useCurrSql(scope.$index)"
|
||||||
|
>引用</el-button
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="mini"
|
||||||
|
@click.prevent="DelSqlHistory(scope.$index)"
|
||||||
|
>删除</el-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="sqlHistoryDialogVisible = false">取消</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, reactive } from "vue";
|
||||||
|
import {
|
||||||
|
FindDBManageListService,
|
||||||
|
AddDBManageService,
|
||||||
|
UpdateDBManageService,
|
||||||
|
RunSQLService,
|
||||||
|
GetSQLRunHistoryService,
|
||||||
|
} from "@/api/dbm";
|
||||||
|
import { DatabaseConfig, ISQLOperation } from "@/types/dbm";
|
||||||
|
|
||||||
|
import horizontalScroll from "el-table-horizontal-scroll";
|
||||||
|
import { Search, Edit, Delete, Plus } from "@element-plus/icons-vue";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import SqlEditor from './sqlEditor.vue';
|
||||||
|
|
||||||
|
// 数据库下拉框数据
|
||||||
|
const databases = ref<DatabaseConfig[]>([]);
|
||||||
|
const selectedDatabase = ref("");
|
||||||
|
|
||||||
|
// 连接下拉框数据
|
||||||
|
const connections = ref([
|
||||||
|
{ name: "腾讯服务器", domain: "tx.ljsea.top" },
|
||||||
|
{ name: "阿里云服务器", domain: "al.ljsea.top" },
|
||||||
|
{ name: "家里服务器", domain: "gep.ljsea.top" },
|
||||||
|
]);
|
||||||
|
const supportdedDBTypes = ref({ 0: "mysql", 1: "postgresql" });
|
||||||
|
const selectedConnection = ref("");
|
||||||
|
|
||||||
|
// SQL查询相关
|
||||||
|
const sqlQuery = ref("");
|
||||||
|
const executing = ref(false);
|
||||||
|
const tableData = ref([]);
|
||||||
|
const tableColumns = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
// 数据库表列表
|
||||||
|
const tables = ref([
|
||||||
|
{
|
||||||
|
name: "users",
|
||||||
|
children: [{ name: "id" }, { name: "username" }, { name: "email" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "products",
|
||||||
|
children: [{ name: "id" }, { name: "name" }, { name: "price" }],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const defaultProps = {
|
||||||
|
children: "children",
|
||||||
|
label: "name",
|
||||||
|
};
|
||||||
|
|
||||||
|
// 数据库对话框相关
|
||||||
|
const databaseDialogVisible = ref(false);
|
||||||
|
const sqlHistoryDialogVisible = ref(false);
|
||||||
|
const isEditDatabase = ref(false);
|
||||||
|
const databaseForm = ref<DatabaseConfig>();
|
||||||
|
const sqlHistory = ref<ISQLOperation[]>([]);
|
||||||
|
|
||||||
|
// 连接对话框相关
|
||||||
|
const connectionDialogVisible = ref(false);
|
||||||
|
const isEditConnection = ref(false);
|
||||||
|
const connectionForm = reactive({
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
host: "",
|
||||||
|
port: "",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const showSQLHistoryDialog = async () => {
|
||||||
|
sqlHistoryDialogVisible.value = true;
|
||||||
|
await getRunSQLHistory();
|
||||||
|
};
|
||||||
|
|
||||||
|
const showAddDatabaseDialog = () => {
|
||||||
|
isEditDatabase.value = false;
|
||||||
|
databaseForm.value = {
|
||||||
|
ID: 0,
|
||||||
|
DB_IP: "",
|
||||||
|
DB_Port: 3306,
|
||||||
|
DB_NAME: "",
|
||||||
|
DB_User: "",
|
||||||
|
DB_Password: "",
|
||||||
|
DB_Type: 0,
|
||||||
|
CreatedAt: "",
|
||||||
|
UpdatedAt: "",
|
||||||
|
};
|
||||||
|
databaseDialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const editDatabase = (item) => {
|
||||||
|
isEditDatabase.value = true;
|
||||||
|
databaseForm.value = item;
|
||||||
|
databaseDialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const GetDBManageList = async () => {
|
||||||
|
let req = {
|
||||||
|
get_type: 0,
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
id: localStorage.getItem("userId"),
|
||||||
|
};
|
||||||
|
await FindDBManageListService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
databases.value = res.data;
|
||||||
|
for (let i = 0; i < databases.value.length; i++) {
|
||||||
|
let type = supportdedDBTypes.value[databases.value[i].DB_Type];
|
||||||
|
databases.value[i].Name =
|
||||||
|
type +
|
||||||
|
" - " +
|
||||||
|
databases.value[i].DB_IP +
|
||||||
|
":" +
|
||||||
|
databases.value[i].DB_Port +
|
||||||
|
" - " +
|
||||||
|
databases.value[i].DB_NAME;
|
||||||
|
}
|
||||||
|
ElMessage.success("获取数据库列表成功");
|
||||||
|
} else {
|
||||||
|
console.error("获取数据库列表失败:", res.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
GetDBManageList();
|
||||||
|
|
||||||
|
const useCurrSql = (index) => {
|
||||||
|
sqlQuery.value = sqlHistory.value[index].SQL;
|
||||||
|
sqlHistoryDialogVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DelSqlHistory = (index) => {
|
||||||
|
sqlHistory.value.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteDatabase = (item) => {
|
||||||
|
databases.value = databases.value.filter((db) => db.ID !== item.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveDatabase = () => {
|
||||||
|
let req = {};
|
||||||
|
if (isEditDatabase.value) {
|
||||||
|
req = {
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
db_id: databaseForm.value.ID,
|
||||||
|
db_name: databaseForm.value.DB_NAME,
|
||||||
|
db_type: databaseForm.value.DB_Type,
|
||||||
|
db_ip: databaseForm.value.DB_IP,
|
||||||
|
db_port: databaseForm.value.DB_Port,
|
||||||
|
db_user: databaseForm.value.DB_User,
|
||||||
|
db_password: databaseForm.value.DB_Password,
|
||||||
|
db_desc: databaseForm.value.DB_Desc,
|
||||||
|
};
|
||||||
|
UpdateDBManageService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success("更新成功");
|
||||||
|
GetDBManageList();
|
||||||
|
} else {
|
||||||
|
ElMessage.error("更新失败");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
req = {
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
db_id: databaseForm.value.ID,
|
||||||
|
db_name: databaseForm.value.DB_NAME,
|
||||||
|
db_type: databaseForm.value.DB_Type,
|
||||||
|
db_ip: databaseForm.value.DB_IP,
|
||||||
|
db_port: databaseForm.value.DB_Port,
|
||||||
|
db_user: databaseForm.value.DB_User,
|
||||||
|
db_password: databaseForm.value.DB_Password,
|
||||||
|
db_desc: databaseForm.value.DB_Desc,
|
||||||
|
};
|
||||||
|
AddDBManageService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success("添加成功");
|
||||||
|
GetDBManageList();
|
||||||
|
} else {
|
||||||
|
ElMessage.error("添加失败");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
databaseDialogVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRunSQLHistory = async () => {
|
||||||
|
if (!selectedDatabase.value) {
|
||||||
|
ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "请选择数据库",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let req = {
|
||||||
|
db_id: selectedDatabase.value,
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
get_type: 0,
|
||||||
|
};
|
||||||
|
await GetSQLRunHistoryService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
sqlHistory.value = res.data;
|
||||||
|
ElMessage({
|
||||||
|
type: "success",
|
||||||
|
message: "获取SQL执行历史成功",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error("获取SQL执行历史失败:", res.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const executeSql = () => {
|
||||||
|
if (!selectedDatabase.value) {
|
||||||
|
ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "请选择数据库",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
executing.value = true;
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
let req = {
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
id: localStorage.getItem("userId"),
|
||||||
|
sql: sqlQuery.value,
|
||||||
|
db_id: selectedDatabase.value,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
RunSQLService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
tableData.value = res.data.Rows;
|
||||||
|
tableColumns.value = res.data.Columns;
|
||||||
|
} else {
|
||||||
|
console.error("执行SQL失败:", res.message);
|
||||||
|
ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: res.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
executing.value = false;
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTableClick = (data) => {
|
||||||
|
if (!data.children) {
|
||||||
|
sqlQuery.value = `SELECT * FROM ${data.name}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.db-manage-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-list {
|
||||||
|
background: #fff;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-20 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-100 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-actions {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-actions .el-icon {
|
||||||
|
margin-left: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,31 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="db-manage-container">
|
<div class="db-manage-container">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<!-- 左侧数据库表列表 -->
|
|
||||||
<el-col :span="4">
|
|
||||||
<div class="table-list">
|
|
||||||
<h3>数据库表</h3>
|
|
||||||
<el-scrollbar height="400px">
|
|
||||||
<el-tree
|
|
||||||
:data="tables"
|
|
||||||
node-key="name"
|
|
||||||
:props="defaultProps"
|
|
||||||
@node-click="handleTableClick"
|
|
||||||
/>
|
|
||||||
</el-scrollbar>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
|
|
||||||
<!-- 右侧主内容区 -->
|
<!-- 右侧主内容区 -->
|
||||||
<el-col :span="20">
|
<el-col :span="24">
|
||||||
<!-- 顶部下拉选择框 -->
|
<!-- 顶部下拉选择框 -->
|
||||||
<el-row :gutter="20" class="mb-20">
|
<el-row :gutter="20" class="mb-20">
|
||||||
<el-col :span="12">
|
<el-col :span="10">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="selectedDatabase"
|
v-model="selectedDatabase"
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择数据库"
|
placeholder="请选择数据库"
|
||||||
class="w-100"
|
class="w-100"
|
||||||
|
@change="getRunSQLHistory"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<el-icon><search /></el-icon>
|
<el-icon><search /></el-icon>
|
||||||
|
|
@ -39,7 +27,9 @@
|
||||||
<span>{{ item.Name }}</span>
|
<span>{{ item.Name }}</span>
|
||||||
<span class="option-actions">
|
<span class="option-actions">
|
||||||
<el-icon @click.stop="editDatabase(item)"><edit /></el-icon>
|
<el-icon @click.stop="editDatabase(item)"><edit /></el-icon>
|
||||||
<el-icon @click.stop="deleteDatabase(item)"><delete /></el-icon>
|
<el-icon @click.stop="deleteDatabase(item)"
|
||||||
|
><delete
|
||||||
|
/></el-icon>
|
||||||
</span>
|
</span>
|
||||||
</el-option>
|
</el-option>
|
||||||
<template #append>
|
<template #append>
|
||||||
|
|
@ -47,11 +37,14 @@
|
||||||
</template>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="1">
|
||||||
|
<el-icon @click="showAddDatabaseDialog"><FolderAdd /></el-icon>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="selectedConnection"
|
v-model="selectedConnection"
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择连接"
|
placeholder="请选择服务器"
|
||||||
class="w-100"
|
class="w-100"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
|
|
@ -59,21 +52,26 @@
|
||||||
</template>
|
</template>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in connections"
|
v-for="item in connections"
|
||||||
:key="item.id"
|
:key="item.domain"
|
||||||
:label="item.name"
|
:label="item.name"
|
||||||
:value="item.id"
|
:value="item.domain"
|
||||||
>
|
>
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ item.name }}</span>
|
||||||
<span class="option-actions">
|
|
||||||
<el-icon @click.stop="editConnection(item)"><edit /></el-icon>
|
|
||||||
<el-icon @click.stop="deleteConnection(item)"><delete /></el-icon>
|
|
||||||
</span>
|
|
||||||
</el-option>
|
</el-option>
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-button icon="plus" @click="showAddConnectionDialog" />
|
<el-button circle @click="showAddDatabaseDialog" />
|
||||||
</template>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="3">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="showSQLHistoryDialog"
|
||||||
|
class="w-100"
|
||||||
|
:loading="executing"
|
||||||
|
>执行历史SQL</el-button
|
||||||
|
>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<!-- SQL输入框和执行按钮 -->
|
<!-- SQL输入框和执行按钮 -->
|
||||||
|
|
@ -85,9 +83,16 @@
|
||||||
:rows="3"
|
:rows="3"
|
||||||
placeholder="请输入SQL语句"
|
placeholder="请输入SQL语句"
|
||||||
/>
|
/>
|
||||||
|
<!-- <SqlEditor v-model="sqlQuery" /> -->
|
||||||
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="4">
|
<el-col :span="4">
|
||||||
<el-button type="primary" @click="executeSql" class="w-100" :loading="executing">
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="executeSql"
|
||||||
|
class="w-100"
|
||||||
|
:loading="executing"
|
||||||
|
>
|
||||||
执行
|
执行
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
@ -96,7 +101,6 @@
|
||||||
<!-- 结果表格 -->
|
<!-- 结果表格 -->
|
||||||
<el-table
|
<el-table
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
border
|
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
height="400px"
|
height="400px"
|
||||||
v-horizontal-scroll="'always'"
|
v-horizontal-scroll="'always'"
|
||||||
|
|
@ -121,7 +125,63 @@
|
||||||
>
|
>
|
||||||
<el-form :model="databaseForm" label-width="100px">
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
<el-form-item label="数据库名称" required>
|
<el-form-item label="数据库名称" required>
|
||||||
<el-input v-model="databaseForm.name" placeholder="请输入数据库名称" />
|
<el-input
|
||||||
|
v-model="databaseForm.DB_NAME"
|
||||||
|
placeholder="请输入数据库名称"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="数据库密码" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_Password"
|
||||||
|
type="password"
|
||||||
|
placeholder="请输入数据库密码"
|
||||||
|
show-password
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="用户名" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_User"
|
||||||
|
placeholder="请输入用户名称"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="IP或域名" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_IP"
|
||||||
|
placeholder="请输入数据库ip或域名"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="数据库端口" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_Port"
|
||||||
|
placeholder="请输入数据库端口"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="数据库类型" required>
|
||||||
|
<el-select
|
||||||
|
v-model="databaseForm.DB_Type"
|
||||||
|
placeholder="请选择数据库类型"
|
||||||
|
>
|
||||||
|
<el-option label="MySQL" value="0" />
|
||||||
|
<el-option label="PostgreSQL" value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="描述信息">
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_Desc"
|
||||||
|
placeholder="请输入备注信息"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
@ -130,236 +190,315 @@
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 添加/编辑连接对话框 -->
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="connectionDialogVisible"
|
v-model="sqlHistoryDialogVisible"
|
||||||
:title="isEditConnection ? '编辑连接' : '添加连接'"
|
title="SQL执行历史"
|
||||||
width="50%"
|
width="50%"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<el-form :model="connectionForm" label-width="100px">
|
<el-table :data="sqlHistory" stripe width="100%" height="600px" fit>
|
||||||
<el-form-item label="连接名称" required>
|
<el-table-column prop="ID" label="SQLID" width="150"></el-table-column>
|
||||||
<el-input v-model="connectionForm.name" placeholder="请输入连接名称" />
|
<el-table-column prop="SQL" label="SQL" width="500"> </el-table-column>
|
||||||
</el-form-item>
|
<el-table-column label="操作" width="270">
|
||||||
<el-form-item label="连接地址" required>
|
<template #default="scope">
|
||||||
<el-input v-model="connectionForm.host" placeholder="请输入连接地址" />
|
<el-button
|
||||||
</el-form-item>
|
type="primary"
|
||||||
<el-form-item label="端口" required>
|
size="mini"
|
||||||
<el-input v-model="connectionForm.port" placeholder="请输入端口" />
|
@click.prevent="useCurrSql(scope.$index)"
|
||||||
</el-form-item>
|
>引用</el-button
|
||||||
<el-form-item label="用户名" required>
|
>
|
||||||
<el-input v-model="connectionForm.username" placeholder="请输入用户名" />
|
<el-button
|
||||||
</el-form-item>
|
type="primary"
|
||||||
<el-form-item label="密码" required>
|
size="mini"
|
||||||
<el-input v-model="connectionForm.password" type="password" placeholder="请输入密码" />
|
@click.prevent="DelSqlHistory(scope.$index)"
|
||||||
</el-form-item>
|
>删除</el-button
|
||||||
</el-form>
|
>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="connectionDialogVisible = false">取消</el-button>
|
<el-button @click="sqlHistoryDialogVisible = false">取消</el-button>
|
||||||
<el-button type="primary" @click="saveConnection">保存</el-button>
|
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineComponent, ref, reactive } from 'vue';
|
import { ref, reactive } from "vue";
|
||||||
import {FindDBManageListService,AddDBManageService,UpdateDBManageService,RunSQLService,GetSQLRunHistoryService } from '@/api/dbm';
|
|
||||||
import {DatabaseConfig} from '@/types/dbm';
|
|
||||||
|
|
||||||
import horizontalScroll from 'el-table-horizontal-scroll'
|
|
||||||
import {
|
import {
|
||||||
Search, Edit, Delete, Plus
|
FindDBManageListService,
|
||||||
} from '@element-plus/icons-vue';
|
AddDBManageService,
|
||||||
|
UpdateDBManageService,
|
||||||
|
RunSQLService,
|
||||||
|
GetSQLRunHistoryService,
|
||||||
|
} from "@/api/dbm";
|
||||||
|
import { DatabaseConfig, ISQLOperation } from "@/types/dbm";
|
||||||
|
import { Search, Edit, Delete, Plus } from "@element-plus/icons-vue";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import SqlEditor from './sqlEditor.vue';
|
||||||
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'DbManage',
|
|
||||||
components: {
|
|
||||||
Search, Edit, Delete, Plus,horizontalScroll
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
// 数据库下拉框数据
|
// 数据库下拉框数据
|
||||||
const databases = ref<DatabaseConfig[]>([]);
|
const databases = ref<DatabaseConfig[]>([]);
|
||||||
const selectedDatabase = ref('');
|
const selectedDatabase = ref("");
|
||||||
|
|
||||||
// 连接下拉框数据
|
// 连接下拉框数据
|
||||||
const connections = ref([
|
const connections = ref([
|
||||||
{ id: 1, name: '本地开发环境' },
|
{ name: "腾讯服务器", domain: "tx.ljsea.top" },
|
||||||
{ id: 2, name: '测试环境' },
|
{ name: "阿里云服务器", domain: "al.ljsea.top" },
|
||||||
{ id: 3, name: '生产环境' },
|
{ name: "家里服务器", domain: "gep.ljsea.top" },
|
||||||
]);
|
]);
|
||||||
const selectedConnection = ref('');
|
const supportdedDBTypes = ref({ 0: "mysql", 1: "postgresql" });
|
||||||
|
const selectedConnection = ref("");
|
||||||
|
|
||||||
// SQL查询相关
|
// SQL查询相关
|
||||||
const sqlQuery = ref('');
|
const sqlQuery = ref("");
|
||||||
const executing = ref(false);
|
const executing = ref(false);
|
||||||
const tableData = ref([]);
|
const tableData = ref([]);
|
||||||
const tableColumns = ref([]);
|
const tableColumns = ref([]);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
// 数据库表列表
|
// 数据库表列表
|
||||||
const tables = ref([
|
|
||||||
{ name: 'users', children: [{ name: 'id' }, { name: 'username' }, { name: 'email' }] },
|
|
||||||
{ name: 'products', children: [{ name: 'id' }, { name: 'name' }, { name: 'price' }] },
|
|
||||||
]);
|
|
||||||
const defaultProps = {
|
|
||||||
children: 'children',
|
|
||||||
label: 'name',
|
|
||||||
};
|
|
||||||
|
|
||||||
// 数据库对话框相关
|
// 数据库对话框相关
|
||||||
const databaseDialogVisible = ref(false);
|
const databaseDialogVisible = ref(false);
|
||||||
|
const sqlHistoryDialogVisible = ref(false);
|
||||||
const isEditDatabase = ref(false);
|
const isEditDatabase = ref(false);
|
||||||
const databaseForm = reactive({
|
const databaseForm = ref<DatabaseConfig>();
|
||||||
id: 0,
|
const sqlHistory = ref<ISQLOperation[]>([]);
|
||||||
name: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
// 连接对话框相关
|
// 连接对话框相关
|
||||||
const connectionDialogVisible = ref(false);
|
const connectionDialogVisible = ref(false);
|
||||||
const isEditConnection = ref(false);
|
const isEditConnection = ref(false);
|
||||||
const connectionForm = reactive({
|
const connectionForm = reactive({
|
||||||
id: 0,
|
id: 0,
|
||||||
name: '',
|
name: "",
|
||||||
host: '',
|
host: "",
|
||||||
port: '',
|
port: "",
|
||||||
username: '',
|
username: "",
|
||||||
password: '',
|
password: "",
|
||||||
});
|
});
|
||||||
|
const showSQLHistoryDialog = async () => {
|
||||||
|
sqlHistoryDialogVisible.value = true;
|
||||||
|
console.log('SQL history dialog opened:', sqlHistoryDialogVisible.value);
|
||||||
|
await getRunSQLHistory();
|
||||||
|
};
|
||||||
|
|
||||||
// 方法定义
|
// 方法定义
|
||||||
const showAddDatabaseDialog = () => {
|
const showAddDatabaseDialog = () => {
|
||||||
isEditDatabase.value = false;
|
isEditDatabase.value = false;
|
||||||
databaseForm.id = 0;
|
databaseForm.value = {
|
||||||
databaseForm.name = '';
|
ID: 0,
|
||||||
|
DB_IP: "",
|
||||||
|
DB_Port: 3306,
|
||||||
|
DB_NAME: "",
|
||||||
|
DB_User: "",
|
||||||
|
DB_Password: "",
|
||||||
|
DB_Type: 0,
|
||||||
|
CreatedAt: "",
|
||||||
|
UpdatedAt: "",
|
||||||
|
UserID: 0,
|
||||||
|
DB_Desc: "",
|
||||||
|
DB_STATUS: 0,
|
||||||
|
Name: "",
|
||||||
|
DeletedAt: null,
|
||||||
|
};
|
||||||
databaseDialogVisible.value = true;
|
databaseDialogVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const editDatabase = (item) => {
|
const editDatabase = (item) => {
|
||||||
isEditDatabase.value = true;
|
isEditDatabase.value = true;
|
||||||
databaseForm.id = item.id;
|
console.log("editDatabase:", item);
|
||||||
databaseForm.name = item.name;
|
databaseForm.value = item;
|
||||||
databaseDialogVisible.value = true;
|
databaseDialogVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const GetDBManageList = async () => {
|
const GetDBManageList = async () => {
|
||||||
let req = {"get_type":0, "token":localStorage.getItem("token"), "id":localStorage.getItem("userId")}
|
let req = {
|
||||||
await FindDBManageListService(req).then((res: any) => {
|
get_type: 0,
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
id: localStorage.getItem("userId"),
|
||||||
|
};
|
||||||
|
await FindDBManageListService(req)
|
||||||
|
.then((res: any) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
databases.value = res.data;
|
databases.value = res.data;
|
||||||
for (let i = 0; i < databases.value.length; i++) {
|
for (let i = 0; i < databases.value.length; i++) {
|
||||||
let type = "MySQL";
|
let type = supportdedDBTypes.value[databases.value[i].DB_Type];
|
||||||
switch(databases.value[i].DB_Type) {
|
databases.value[i].Name =
|
||||||
case 0:
|
type +
|
||||||
type = "MySQL";
|
" - " +
|
||||||
break;
|
databases.value[i].DB_IP +
|
||||||
case 1:
|
":" +
|
||||||
type = "PostgreSQL";
|
databases.value[i].DB_Port +
|
||||||
break;
|
" - " +
|
||||||
}
|
databases.value[i].DB_NAME;
|
||||||
databases.value[i].Name = type + " - "+ databases.value[i].DB_IP + ":" + databases.value[i].DB_Port + " - " + databases.value[i].DB_NAME;
|
|
||||||
}
|
}
|
||||||
|
ElMessage.success("获取数据库列表成功");
|
||||||
|
console.log("获取数据库列表成功:", databases.value);
|
||||||
|
|
||||||
|
|
||||||
|
// console.log("获取数据库列表成功:", res.data);
|
||||||
|
|
||||||
|
// console.log("获取数据库列表成功:", res.data);
|
||||||
|
// console.log("获取数据库列表成功:", res.data);
|
||||||
} else {
|
} else {
|
||||||
console.error('获取数据库列表失败:', res.message);
|
console.error("获取数据库列表失败:", res.message);
|
||||||
}
|
}
|
||||||
}).catch((error: any) => {
|
})
|
||||||
console.error('请求错误:', error);
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
GetDBManageList();
|
GetDBManageList();
|
||||||
|
|
||||||
|
const useCurrSql = (index) => {
|
||||||
|
sqlQuery.value = sqlHistory.value[index].SQL;
|
||||||
|
sqlHistoryDialogVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DelSqlHistory = (index) => {
|
||||||
|
sqlHistory.value.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
const deleteDatabase = (item) => {
|
const deleteDatabase = (item) => {
|
||||||
// 实际项目中这里应该调用API删除
|
// 实际项目中这里应该调用API删除
|
||||||
databases.value = databases.value.filter(db => db.ID !== item.id);
|
databases.value = databases.value.filter((db) => db.ID !== item.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveDatabase = () => {
|
const saveDatabase = () => {
|
||||||
|
let req = {};
|
||||||
if (isEditDatabase.value) {
|
if (isEditDatabase.value) {
|
||||||
// 更新
|
// 更新
|
||||||
const index = databases.value.findIndex(db => db.ID === databaseForm.id);
|
// const index = databases.value.findIndex(db => db.ID === databaseForm.id);
|
||||||
if (index !== -1) {
|
// if (index !== -1) {
|
||||||
databases.value[index].Name = databaseForm.name;
|
// databases.value[index].Name = databaseForm.name;
|
||||||
|
// }]
|
||||||
|
req = {
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
db_id: databaseForm.value.ID,
|
||||||
|
db_name: databaseForm.value.DB_NAME,
|
||||||
|
db_type: databaseForm.value.DB_Type,
|
||||||
|
db_ip: databaseForm.value.DB_IP,
|
||||||
|
db_port: databaseForm.value.DB_Port,
|
||||||
|
db_user: databaseForm.value.DB_User,
|
||||||
|
db_password: databaseForm.value.DB_Password,
|
||||||
|
db_desc: databaseForm.value.DB_Desc,
|
||||||
|
};
|
||||||
|
UpdateDBManageService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success("更新成功");
|
||||||
|
GetDBManageList();
|
||||||
|
} else {
|
||||||
|
ElMessage.error("更新失败");
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// 新增
|
// 新增
|
||||||
// databases.value.push({
|
// databases.value.push({
|
||||||
// id: databases.value.length + 1,
|
// id: databases.value.length + 1,
|
||||||
// name: databaseForm.name,
|
// name: databaseForm.name,
|
||||||
// });
|
// });
|
||||||
|
req = {
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
db_id: databaseForm.value.ID,
|
||||||
|
db_name: databaseForm.value.DB_NAME,
|
||||||
|
db_type: databaseForm.value.DB_Type,
|
||||||
|
db_ip: databaseForm.value.DB_IP,
|
||||||
|
db_port: databaseForm.value.DB_Port,
|
||||||
|
db_user: databaseForm.value.DB_User,
|
||||||
|
db_password: databaseForm.value.DB_Password,
|
||||||
|
db_desc: databaseForm.value.DB_Desc,
|
||||||
|
};
|
||||||
|
AddDBManageService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success("添加成功");
|
||||||
|
GetDBManageList();
|
||||||
|
} else {
|
||||||
|
ElMessage.error("添加失败");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
databaseDialogVisible.value = false;
|
databaseDialogVisible.value = false;
|
||||||
};
|
};
|
||||||
|
const getRunSQLHistory = async () => {
|
||||||
const showAddConnectionDialog = () => {
|
if (!selectedDatabase.value) {
|
||||||
isEditConnection.value = false;
|
ElMessage({
|
||||||
connectionForm.id = 0;
|
type: "error",
|
||||||
connectionForm.name = '';
|
message: "请选择数据库",
|
||||||
connectionForm.host = '';
|
|
||||||
connectionForm.port = '';
|
|
||||||
connectionForm.username = '';
|
|
||||||
connectionForm.password = '';
|
|
||||||
connectionDialogVisible.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const editConnection = (item) => {
|
|
||||||
isEditConnection.value = true;
|
|
||||||
connectionForm.id = item.id;
|
|
||||||
connectionForm.name = item.name;
|
|
||||||
connectionForm.host = item.host || '';
|
|
||||||
connectionForm.port = item.port || '';
|
|
||||||
connectionForm.username = item.username || '';
|
|
||||||
connectionForm.password = item.password || '';
|
|
||||||
connectionDialogVisible.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteConnection = (item) => {
|
|
||||||
// 实际项目中这里应该调用API删除
|
|
||||||
connections.value = connections.value.filter(conn => conn.id !== item.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const saveConnection = () => {
|
|
||||||
if (isEditConnection.value) {
|
|
||||||
// 更新
|
|
||||||
const index = connections.value.findIndex(conn => conn.id === connectionForm.id);
|
|
||||||
if (index !== -1) {
|
|
||||||
connections.value[index] = { ...connectionForm };
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 新增
|
|
||||||
connections.value.push({
|
|
||||||
id: connections.value.length + 1,
|
|
||||||
...connectionForm,
|
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
connectionDialogVisible.value = false;
|
let req = {
|
||||||
|
db_id: selectedDatabase.value,
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
get_type: 0,
|
||||||
|
};
|
||||||
|
await GetSQLRunHistoryService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
sqlHistory.value = res.data;
|
||||||
|
ElMessage({
|
||||||
|
type: "success",
|
||||||
|
message: "获取SQL执行历史成功",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error("获取SQL执行历史失败:", res.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const executeSql = () => {
|
const executeSql = () => {
|
||||||
|
if (!selectedDatabase.value) {
|
||||||
|
ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "请选择数据库",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
executing.value = true;
|
executing.value = true;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
let req = {
|
let req = {
|
||||||
"token":localStorage.getItem("token"),
|
token: localStorage.getItem("token"),
|
||||||
"id":localStorage.getItem("userId"),
|
id: localStorage.getItem("userId"),
|
||||||
"sql":sqlQuery.value,
|
sql: sqlQuery.value,
|
||||||
"db_id":selectedDatabase.value,
|
db_id: selectedDatabase.value,
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
RunSQLService(req).then((res: any) => {
|
RunSQLService(req)
|
||||||
|
.then((res: any) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
tableData.value = res.data;
|
tableData.value = res.data.Rows;
|
||||||
|
tableColumns.value = res.data.Columns;
|
||||||
|
// let keys = Object.keys(res.data.Rows[0]);
|
||||||
|
//console.log( 'columns:',tableColumns.value);
|
||||||
// tableColumns.value = res.columns;
|
// tableColumns.value = res.columns;
|
||||||
let first = res.data[0];
|
// tableColumns.value = keys.map((key) => {
|
||||||
let keys = Object.keys(first);
|
// return { prop: key, label: key };
|
||||||
tableColumns.value = keys.map((key) => {
|
// });
|
||||||
return { prop: key, label: key };
|
// console.log(res.data);
|
||||||
});
|
|
||||||
console.log(res.data);
|
|
||||||
} else {
|
} else {
|
||||||
console.error('执行SQL失败:', res.message);
|
console.error("执行SQL失败:", res.message);
|
||||||
|
ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: res.message,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}).catch((error: any) => {
|
})
|
||||||
console.error('请求错误:', error);
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|
@ -369,44 +508,7 @@ export default defineComponent({
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTableClick = (data) => {
|
|
||||||
// 点击表名时自动生成查询语句
|
|
||||||
if (!data.children) {
|
|
||||||
sqlQuery.value = `SELECT * FROM ${data.name}`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
databases,
|
|
||||||
selectedDatabase,
|
|
||||||
connections,
|
|
||||||
selectedConnection,
|
|
||||||
sqlQuery,
|
|
||||||
executing,
|
|
||||||
tableData,
|
|
||||||
tableColumns,
|
|
||||||
loading,
|
|
||||||
tables,
|
|
||||||
defaultProps,
|
|
||||||
databaseDialogVisible,
|
|
||||||
isEditDatabase,
|
|
||||||
databaseForm,
|
|
||||||
connectionDialogVisible,
|
|
||||||
isEditConnection,
|
|
||||||
connectionForm,
|
|
||||||
showAddDatabaseDialog,
|
|
||||||
editDatabase,
|
|
||||||
deleteDatabase,
|
|
||||||
saveDatabase,
|
|
||||||
showAddConnectionDialog,
|
|
||||||
editConnection,
|
|
||||||
deleteConnection,
|
|
||||||
saveConnection,
|
|
||||||
executeSql,
|
|
||||||
handleTableClick,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,573 @@
|
||||||
|
<template>
|
||||||
|
<div class="db-manage-container">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<!-- 左侧数据库表列表 -->
|
||||||
|
<el-col :span="4">
|
||||||
|
<div class="table-list">
|
||||||
|
<h3>数据库表</h3>
|
||||||
|
<el-scrollbar height="400px">
|
||||||
|
<el-tree
|
||||||
|
:data="tables"
|
||||||
|
node-key="name"
|
||||||
|
:props="defaultProps"
|
||||||
|
@node-click="handleTableClick"
|
||||||
|
/>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<!-- 右侧主内容区 -->
|
||||||
|
<el-col :span="20">
|
||||||
|
<!-- 顶部下拉选择框 -->
|
||||||
|
<el-row :gutter="20" class="mb-20">
|
||||||
|
<el-col :span="10">
|
||||||
|
<el-select
|
||||||
|
v-model="selectedDatabase"
|
||||||
|
filterable
|
||||||
|
placeholder="请选择数据库"
|
||||||
|
class="w-100"
|
||||||
|
@change="getRunSQLHistory"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<el-icon><search /></el-icon>
|
||||||
|
</template>
|
||||||
|
<el-option
|
||||||
|
v-for="item in databases"
|
||||||
|
:key="item.ID"
|
||||||
|
:label="item.Name"
|
||||||
|
:value="item.ID"
|
||||||
|
>
|
||||||
|
<span>{{ item.Name }}</span>
|
||||||
|
<span class="option-actions">
|
||||||
|
<el-icon @click.stop="editDatabase(item)"><edit /></el-icon>
|
||||||
|
<el-icon @click.stop="deleteDatabase(item)"
|
||||||
|
><delete
|
||||||
|
/></el-icon>
|
||||||
|
</span>
|
||||||
|
</el-option>
|
||||||
|
<template #append>
|
||||||
|
<el-button icon="plus" @click="showAddDatabaseDialog" />
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1">
|
||||||
|
<el-icon @click="showAddDatabaseDialog"><FolderAdd /></el-icon>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-select
|
||||||
|
v-model="selectedConnection"
|
||||||
|
filterable
|
||||||
|
placeholder="请选择服务器"
|
||||||
|
class="w-100"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<el-icon><search /></el-icon>
|
||||||
|
</template>
|
||||||
|
<el-option
|
||||||
|
v-for="item in connections"
|
||||||
|
:key="item.domain"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.domain"
|
||||||
|
>
|
||||||
|
<span>{{ item.name }}</span>
|
||||||
|
</el-option>
|
||||||
|
<template #append>
|
||||||
|
<el-button circle @click="showAddDatabaseDialog" />
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="3">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="showSQLHistoryDialog"
|
||||||
|
class="w-100"
|
||||||
|
:loading="executing"
|
||||||
|
>执行历史SQL</el-button
|
||||||
|
>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- SQL输入框和执行按钮 -->
|
||||||
|
<el-row class="mb-20">
|
||||||
|
<el-col :span="20">
|
||||||
|
<el-input
|
||||||
|
v-model="sqlQuery"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
placeholder="请输入SQL语句"
|
||||||
|
/>
|
||||||
|
<!-- <SqlEditor v-model="sqlQuery" /> -->
|
||||||
|
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="4">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="executeSql"
|
||||||
|
class="w-100"
|
||||||
|
:loading="executing"
|
||||||
|
>
|
||||||
|
执行
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 结果表格 -->
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
style="width: 100%"
|
||||||
|
height="400px"
|
||||||
|
v-horizontal-scroll="'always'"
|
||||||
|
v-loading="loading"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
:key="column.prop"
|
||||||
|
:prop="column.prop"
|
||||||
|
:label="column.label"
|
||||||
|
/>
|
||||||
|
</el-table>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 添加/编辑数据库对话框 -->
|
||||||
|
<el-dialog
|
||||||
|
v-model="databaseDialogVisible"
|
||||||
|
:title="isEditDatabase ? '编辑数据库' : '添加数据库'"
|
||||||
|
width="50%"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="数据库名称" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_NAME"
|
||||||
|
placeholder="请输入数据库名称"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="数据库密码" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_Password"
|
||||||
|
type="password"
|
||||||
|
placeholder="请输入数据库密码"
|
||||||
|
show-password
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="用户名" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_User"
|
||||||
|
placeholder="请输入用户名称"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="IP或域名" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_IP"
|
||||||
|
placeholder="请输入数据库ip或域名"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="数据库端口" required>
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_Port"
|
||||||
|
placeholder="请输入数据库端口"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="数据库类型" required>
|
||||||
|
<el-select
|
||||||
|
v-model="databaseForm.DB_Type"
|
||||||
|
placeholder="请选择数据库类型"
|
||||||
|
>
|
||||||
|
<el-option label="MySQL" value="0" />
|
||||||
|
<el-option label="PostgreSQL" value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form :model="databaseForm" label-width="100px">
|
||||||
|
<el-form-item label="描述信息">
|
||||||
|
<el-input
|
||||||
|
v-model="databaseForm.DB_Desc"
|
||||||
|
placeholder="请输入备注信息"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="databaseDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="saveDatabase">保存</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="sqlHistoryDialogVisible"
|
||||||
|
title="SQL执行历史"
|
||||||
|
width="50%"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-table :data="sqlHistory" stripe width="100%" height="600px" fit>
|
||||||
|
<el-table-column prop="ID" label="SQLID" width="150"></el-table-column>
|
||||||
|
<el-table-column prop="SQL" label="SQL" width="500"> </el-table-column>
|
||||||
|
<el-table-column label="操作" width="270">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="mini"
|
||||||
|
@click.prevent="useCurrSql(scope.$index)"
|
||||||
|
>引用</el-button
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="mini"
|
||||||
|
@click.prevent="DelSqlHistory(scope.$index)"
|
||||||
|
>删除</el-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="sqlHistoryDialogVisible = false">取消</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from "vue";
|
||||||
|
import {
|
||||||
|
FindDBManageListService,
|
||||||
|
AddDBManageService,
|
||||||
|
UpdateDBManageService,
|
||||||
|
RunSQLService,
|
||||||
|
GetSQLRunHistoryService,
|
||||||
|
} from "@/api/dbm";
|
||||||
|
import { DatabaseConfig, ISQLOperation } from "@/types/dbm";
|
||||||
|
import { Search, Edit, Delete, Plus } from "@element-plus/icons-vue";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import SqlEditor from './sqlEditor.vue';
|
||||||
|
|
||||||
|
// 数据库下拉框数据
|
||||||
|
const databases = ref<DatabaseConfig[]>([]);
|
||||||
|
const selectedDatabase = ref("");
|
||||||
|
|
||||||
|
// 连接下拉框数据
|
||||||
|
const connections = ref([
|
||||||
|
{ name: "腾讯服务器", domain: "tx.ljsea.top" },
|
||||||
|
{ name: "阿里云服务器", domain: "al.ljsea.top" },
|
||||||
|
{ name: "家里服务器", domain: "gep.ljsea.top" },
|
||||||
|
]);
|
||||||
|
const supportdedDBTypes = ref({ 0: "mysql", 1: "postgresql" });
|
||||||
|
const selectedConnection = ref("");
|
||||||
|
|
||||||
|
// SQL查询相关
|
||||||
|
const sqlQuery = ref("");
|
||||||
|
const executing = ref(false);
|
||||||
|
const tableData = ref([]);
|
||||||
|
const tableColumns = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
// 数据库表列表
|
||||||
|
const tables = ref([
|
||||||
|
{
|
||||||
|
name: "users",
|
||||||
|
children: [{ name: "id" }, { name: "username" }, { name: "email" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "products",
|
||||||
|
children: [{ name: "id" }, { name: "name" }, { name: "price" }],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const defaultProps = {
|
||||||
|
children: "children",
|
||||||
|
label: "name",
|
||||||
|
};
|
||||||
|
|
||||||
|
// 数据库对话框相关
|
||||||
|
const databaseDialogVisible = ref(false);
|
||||||
|
const sqlHistoryDialogVisible = ref(false);
|
||||||
|
const isEditDatabase = ref(false);
|
||||||
|
const databaseForm = ref<DatabaseConfig>();
|
||||||
|
const sqlHistory = ref<ISQLOperation[]>([]);
|
||||||
|
|
||||||
|
// 连接对话框相关
|
||||||
|
const connectionDialogVisible = ref(false);
|
||||||
|
const isEditConnection = ref(false);
|
||||||
|
const connectionForm = reactive({
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
host: "",
|
||||||
|
port: "",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
});
|
||||||
|
const showSQLHistoryDialog = async () => {
|
||||||
|
sqlHistoryDialogVisible.value = true;
|
||||||
|
console.log('SQL history dialog opened:', sqlHistoryDialogVisible.value);
|
||||||
|
await getRunSQLHistory();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 方法定义
|
||||||
|
const showAddDatabaseDialog = () => {
|
||||||
|
isEditDatabase.value = false;
|
||||||
|
databaseForm.value = {
|
||||||
|
ID: 0,
|
||||||
|
DB_IP: "",
|
||||||
|
DB_Port: 3306,
|
||||||
|
DB_NAME: "",
|
||||||
|
DB_User: "",
|
||||||
|
DB_Password: "",
|
||||||
|
DB_Type: 0,
|
||||||
|
CreatedAt: "",
|
||||||
|
UpdatedAt: "",
|
||||||
|
UserID: 0,
|
||||||
|
DB_Desc: "",
|
||||||
|
DB_STATUS: 0,
|
||||||
|
Name: "",
|
||||||
|
DeletedAt: null,
|
||||||
|
};
|
||||||
|
databaseDialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const editDatabase = (item) => {
|
||||||
|
isEditDatabase.value = true;
|
||||||
|
console.log("editDatabase:", item);
|
||||||
|
databaseForm.value = item;
|
||||||
|
databaseDialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const GetDBManageList = async () => {
|
||||||
|
let req = {
|
||||||
|
get_type: 0,
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
id: localStorage.getItem("userId"),
|
||||||
|
};
|
||||||
|
await FindDBManageListService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
databases.value = res.data;
|
||||||
|
for (let i = 0; i < databases.value.length; i++) {
|
||||||
|
let type = supportdedDBTypes.value[databases.value[i].DB_Type];
|
||||||
|
databases.value[i].Name =
|
||||||
|
type +
|
||||||
|
" - " +
|
||||||
|
databases.value[i].DB_IP +
|
||||||
|
":" +
|
||||||
|
databases.value[i].DB_Port +
|
||||||
|
" - " +
|
||||||
|
databases.value[i].DB_NAME;
|
||||||
|
}
|
||||||
|
ElMessage.success("获取数据库列表成功");
|
||||||
|
console.log("获取数据库列表成功:", databases.value);
|
||||||
|
|
||||||
|
|
||||||
|
// console.log("获取数据库列表成功:", res.data);
|
||||||
|
|
||||||
|
// console.log("获取数据库列表成功:", res.data);
|
||||||
|
// console.log("获取数据库列表成功:", res.data);
|
||||||
|
} else {
|
||||||
|
console.error("获取数据库列表失败:", res.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
GetDBManageList();
|
||||||
|
|
||||||
|
const useCurrSql = (index) => {
|
||||||
|
sqlQuery.value = sqlHistory.value[index].SQL;
|
||||||
|
sqlHistoryDialogVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DelSqlHistory = (index) => {
|
||||||
|
sqlHistory.value.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteDatabase = (item) => {
|
||||||
|
// 实际项目中这里应该调用API删除
|
||||||
|
databases.value = databases.value.filter((db) => db.ID !== item.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveDatabase = () => {
|
||||||
|
let req = {};
|
||||||
|
if (isEditDatabase.value) {
|
||||||
|
// 更新
|
||||||
|
// const index = databases.value.findIndex(db => db.ID === databaseForm.id);
|
||||||
|
// if (index !== -1) {
|
||||||
|
// databases.value[index].Name = databaseForm.name;
|
||||||
|
// }]
|
||||||
|
req = {
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
db_id: databaseForm.value.ID,
|
||||||
|
db_name: databaseForm.value.DB_NAME,
|
||||||
|
db_type: databaseForm.value.DB_Type,
|
||||||
|
db_ip: databaseForm.value.DB_IP,
|
||||||
|
db_port: databaseForm.value.DB_Port,
|
||||||
|
db_user: databaseForm.value.DB_User,
|
||||||
|
db_password: databaseForm.value.DB_Password,
|
||||||
|
db_desc: databaseForm.value.DB_Desc,
|
||||||
|
};
|
||||||
|
UpdateDBManageService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success("更新成功");
|
||||||
|
GetDBManageList();
|
||||||
|
} else {
|
||||||
|
ElMessage.error("更新失败");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 新增
|
||||||
|
// databases.value.push({
|
||||||
|
// id: databases.value.length + 1,
|
||||||
|
// name: databaseForm.name,
|
||||||
|
// });
|
||||||
|
req = {
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
db_id: databaseForm.value.ID,
|
||||||
|
db_name: databaseForm.value.DB_NAME,
|
||||||
|
db_type: databaseForm.value.DB_Type,
|
||||||
|
db_ip: databaseForm.value.DB_IP,
|
||||||
|
db_port: databaseForm.value.DB_Port,
|
||||||
|
db_user: databaseForm.value.DB_User,
|
||||||
|
db_password: databaseForm.value.DB_Password,
|
||||||
|
db_desc: databaseForm.value.DB_Desc,
|
||||||
|
};
|
||||||
|
AddDBManageService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success("添加成功");
|
||||||
|
GetDBManageList();
|
||||||
|
} else {
|
||||||
|
ElMessage.error("添加失败");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
databaseDialogVisible.value = false;
|
||||||
|
};
|
||||||
|
const getRunSQLHistory = async () => {
|
||||||
|
if (!selectedDatabase.value) {
|
||||||
|
ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "请选择数据库",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let req = {
|
||||||
|
db_id: selectedDatabase.value,
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
get_type: 0,
|
||||||
|
};
|
||||||
|
await GetSQLRunHistoryService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
sqlHistory.value = res.data;
|
||||||
|
ElMessage({
|
||||||
|
type: "success",
|
||||||
|
message: "获取SQL执行历史成功",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error("获取SQL执行历史失败:", res.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const executeSql = () => {
|
||||||
|
if (!selectedDatabase.value) {
|
||||||
|
ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "请选择数据库",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
executing.value = true;
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
let req = {
|
||||||
|
token: localStorage.getItem("token"),
|
||||||
|
id: localStorage.getItem("userId"),
|
||||||
|
sql: sqlQuery.value,
|
||||||
|
db_id: selectedDatabase.value,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
RunSQLService(req)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
tableData.value = res.data.Rows;
|
||||||
|
tableColumns.value = res.data.Columns;
|
||||||
|
// let keys = Object.keys(res.data.Rows[0]);
|
||||||
|
//console.log( 'columns:',tableColumns.value);
|
||||||
|
// tableColumns.value = res.columns;
|
||||||
|
// tableColumns.value = keys.map((key) => {
|
||||||
|
// return { prop: key, label: key };
|
||||||
|
// });
|
||||||
|
// console.log(res.data);
|
||||||
|
} else {
|
||||||
|
console.error("执行SQL失败:", res.message);
|
||||||
|
ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: res.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error("请求错误:", error);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
executing.value = false;
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTableClick = (data) => {
|
||||||
|
// 点击表名时自动生成查询语句
|
||||||
|
if (!data.children) {
|
||||||
|
sqlQuery.value = `SELECT * FROM ${data.name}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.db-manage-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-list {
|
||||||
|
background: #fff;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-20 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-100 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-actions {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-actions .el-icon {
|
||||||
|
margin-left: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
<template>
|
||||||
|
<div ref="editorContainer" class="sql-editor-container" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, onUnmounted, watch, type Ref } from 'vue';
|
||||||
|
import { EditorState, EditorView, basicSetup } from '@codemirror/basic-setup';
|
||||||
|
import { sql } from '@codemirror/lang-sql';
|
||||||
|
import { oneDark } from '@codemirror/theme-one-dark'; // 可选主题
|
||||||
|
|
||||||
|
// 定义 props(支持 v-model 双向绑定)
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 定义 emits
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:modelValue', value: string): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 编辑器容器引用
|
||||||
|
const editorContainer: Ref<HTMLElement | null> = ref(null);
|
||||||
|
let editorView: EditorView | null = null;
|
||||||
|
|
||||||
|
// 初始化编辑器
|
||||||
|
const initEditor = () => {
|
||||||
|
if (!editorContainer.value) return;
|
||||||
|
|
||||||
|
// 配置编辑器扩展
|
||||||
|
const extensions = [
|
||||||
|
basicSetup, // 基础功能(行号、语法高亮、快捷键等)
|
||||||
|
sql(), // SQL 语言支持
|
||||||
|
oneDark, // 主题(可选,移除则使用默认主题)
|
||||||
|
EditorView.lineWrapping, // 自动换行
|
||||||
|
EditorView.updateListener.of((update) => {
|
||||||
|
// 监听内容变化并同步到 modelValue
|
||||||
|
if (update.docChanged) {
|
||||||
|
const newValue = update.state.doc.toString();
|
||||||
|
emit('update:modelValue', newValue);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 初始化编辑器状态(使用 modelValue 作为初始内容)
|
||||||
|
const state = EditorState.create({
|
||||||
|
doc: props.modelValue,
|
||||||
|
extensions,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建 EditorView 并挂载到容器
|
||||||
|
editorView = new EditorView({
|
||||||
|
state,
|
||||||
|
parent: editorContainer.value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听 modelValue 变化(外部修改时更新编辑器内容)
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(newValue) => {
|
||||||
|
if (editorView && newValue !== editorView.state.doc.toString()) {
|
||||||
|
editorView.dispatch({
|
||||||
|
changes: { from: 0, to: editorView.state.doc.length, insert: newValue },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 生命周期:挂载后初始化编辑器
|
||||||
|
onMounted(() => {
|
||||||
|
initEditor();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 生命周期:卸载时销毁编辑器(避免内存泄漏)
|
||||||
|
onUnmounted(() => {
|
||||||
|
editorView?.destroy();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.sql-editor-container {
|
||||||
|
height: 400px; /* 必须指定高度 */
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
133
yarn.lock
133
yarn.lock
|
|
@ -87,6 +87,16 @@
|
||||||
resolved "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz"
|
resolved "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz"
|
||||||
integrity sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==
|
integrity sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==
|
||||||
|
|
||||||
|
"@codemirror/autocomplete@^0.20.0":
|
||||||
|
version "0.20.3"
|
||||||
|
resolved "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-0.20.3.tgz"
|
||||||
|
integrity sha512-lYB+NPGP+LEzAudkWhLfMxhTrxtLILGl938w+RcFrGdrIc54A+UgmCoz+McE3IYRFp4xyQcL4uFJwo+93YdgHw==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/language" "^0.20.0"
|
||||||
|
"@codemirror/state" "^0.20.0"
|
||||||
|
"@codemirror/view" "^0.20.0"
|
||||||
|
"@lezer/common" "^0.16.0"
|
||||||
|
|
||||||
"@codemirror/autocomplete@^6.0.0":
|
"@codemirror/autocomplete@^6.0.0":
|
||||||
version "6.18.6"
|
version "6.18.6"
|
||||||
resolved "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz"
|
resolved "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz"
|
||||||
|
|
@ -97,6 +107,29 @@
|
||||||
"@codemirror/view" "^6.17.0"
|
"@codemirror/view" "^6.17.0"
|
||||||
"@lezer/common" "^1.0.0"
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
|
"@codemirror/basic-setup@^0.20.0":
|
||||||
|
version "0.20.0"
|
||||||
|
resolved "https://registry.npmjs.org/@codemirror/basic-setup/-/basic-setup-0.20.0.tgz"
|
||||||
|
integrity sha512-W/ERKMLErWkrVLyP5I8Yh8PXl4r+WFNkdYVSzkXYPQv2RMPSkWpr2BgggiSJ8AHF/q3GuApncDD8I4BZz65fyg==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/autocomplete" "^0.20.0"
|
||||||
|
"@codemirror/commands" "^0.20.0"
|
||||||
|
"@codemirror/language" "^0.20.0"
|
||||||
|
"@codemirror/lint" "^0.20.0"
|
||||||
|
"@codemirror/search" "^0.20.0"
|
||||||
|
"@codemirror/state" "^0.20.0"
|
||||||
|
"@codemirror/view" "^0.20.0"
|
||||||
|
|
||||||
|
"@codemirror/commands@^0.20.0":
|
||||||
|
version "0.20.0"
|
||||||
|
resolved "https://registry.npmjs.org/@codemirror/commands/-/commands-0.20.0.tgz"
|
||||||
|
integrity sha512-v9L5NNVA+A9R6zaFvaTbxs30kc69F6BkOoiEbeFw4m4I0exmDEKBILN6mK+GksJtvTzGBxvhAPlVFTdQW8GB7Q==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/language" "^0.20.0"
|
||||||
|
"@codemirror/state" "^0.20.0"
|
||||||
|
"@codemirror/view" "^0.20.0"
|
||||||
|
"@lezer/common" "^0.16.0"
|
||||||
|
|
||||||
"@codemirror/commands@^6.0.0", "@codemirror/commands@6.x":
|
"@codemirror/commands@^6.0.0", "@codemirror/commands@6.x":
|
||||||
version "6.8.1"
|
version "6.8.1"
|
||||||
resolved "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz"
|
resolved "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz"
|
||||||
|
|
@ -107,6 +140,30 @@
|
||||||
"@codemirror/view" "^6.27.0"
|
"@codemirror/view" "^6.27.0"
|
||||||
"@lezer/common" "^1.1.0"
|
"@lezer/common" "^1.1.0"
|
||||||
|
|
||||||
|
"@codemirror/lang-sql@^6.9.1":
|
||||||
|
version "6.9.1"
|
||||||
|
resolved "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.9.1.tgz"
|
||||||
|
integrity sha512-ecSk3gm/mlINcURMcvkCZmXgdzPSq8r/yfCtTB4vgqGGIbBC2IJIAy7GqYTy5pgBEooTVmHP2GZK6Z7h63CDGg==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/autocomplete" "^6.0.0"
|
||||||
|
"@codemirror/language" "^6.0.0"
|
||||||
|
"@codemirror/state" "^6.0.0"
|
||||||
|
"@lezer/common" "^1.2.0"
|
||||||
|
"@lezer/highlight" "^1.0.0"
|
||||||
|
"@lezer/lr" "^1.0.0"
|
||||||
|
|
||||||
|
"@codemirror/language@^0.20.0":
|
||||||
|
version "0.20.2"
|
||||||
|
resolved "https://registry.npmjs.org/@codemirror/language/-/language-0.20.2.tgz"
|
||||||
|
integrity sha512-WB3Bnuusw0xhVvhBocieYKwJm04SOk5bPoOEYksVHKHcGHFOaYaw+eZVxR4gIqMMcGzOIUil0FsCmFk8yrhHpw==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state" "^0.20.0"
|
||||||
|
"@codemirror/view" "^0.20.0"
|
||||||
|
"@lezer/common" "^0.16.0"
|
||||||
|
"@lezer/highlight" "^0.16.0"
|
||||||
|
"@lezer/lr" "^0.16.0"
|
||||||
|
style-mod "^4.0.0"
|
||||||
|
|
||||||
"@codemirror/language@^6.0.0", "@codemirror/language@6.x":
|
"@codemirror/language@^6.0.0", "@codemirror/language@6.x":
|
||||||
version "6.11.0"
|
version "6.11.0"
|
||||||
resolved "https://registry.npmjs.org/@codemirror/language/-/language-6.11.0.tgz"
|
resolved "https://registry.npmjs.org/@codemirror/language/-/language-6.11.0.tgz"
|
||||||
|
|
@ -119,6 +176,15 @@
|
||||||
"@lezer/lr" "^1.0.0"
|
"@lezer/lr" "^1.0.0"
|
||||||
style-mod "^4.0.0"
|
style-mod "^4.0.0"
|
||||||
|
|
||||||
|
"@codemirror/lint@^0.20.0":
|
||||||
|
version "0.20.3"
|
||||||
|
resolved "https://registry.npmjs.org/@codemirror/lint/-/lint-0.20.3.tgz"
|
||||||
|
integrity sha512-06xUScbbspZ8mKoODQCEx6hz1bjaq9m8W8DxdycWARMiiX1wMtfCh/MoHpaL7ws/KUMwlsFFfp2qhm32oaCvVA==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state" "^0.20.0"
|
||||||
|
"@codemirror/view" "^0.20.2"
|
||||||
|
crelt "^1.0.5"
|
||||||
|
|
||||||
"@codemirror/lint@^6.0.0":
|
"@codemirror/lint@^6.0.0":
|
||||||
version "6.8.5"
|
version "6.8.5"
|
||||||
resolved "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.5.tgz"
|
resolved "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.5.tgz"
|
||||||
|
|
@ -128,6 +194,15 @@
|
||||||
"@codemirror/view" "^6.35.0"
|
"@codemirror/view" "^6.35.0"
|
||||||
crelt "^1.0.5"
|
crelt "^1.0.5"
|
||||||
|
|
||||||
|
"@codemirror/search@^0.20.0":
|
||||||
|
version "0.20.1"
|
||||||
|
resolved "https://registry.npmjs.org/@codemirror/search/-/search-0.20.1.tgz"
|
||||||
|
integrity sha512-ROe6gRboQU5E4z6GAkNa2kxhXqsGNbeLEisbvzbOeB7nuDYXUZ70vGIgmqPu0tB+1M3F9yWk6W8k2vrFpJaD4Q==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state" "^0.20.0"
|
||||||
|
"@codemirror/view" "^0.20.0"
|
||||||
|
crelt "^1.0.5"
|
||||||
|
|
||||||
"@codemirror/search@^6.0.0":
|
"@codemirror/search@^6.0.0":
|
||||||
version "6.5.11"
|
version "6.5.11"
|
||||||
resolved "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz"
|
resolved "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz"
|
||||||
|
|
@ -137,19 +212,44 @@
|
||||||
"@codemirror/view" "^6.0.0"
|
"@codemirror/view" "^6.0.0"
|
||||||
crelt "^1.0.5"
|
crelt "^1.0.5"
|
||||||
|
|
||||||
"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.5.0", "@codemirror/state@6.x":
|
"@codemirror/state@^0.20.0":
|
||||||
|
version "0.20.1"
|
||||||
|
resolved "https://registry.npmjs.org/@codemirror/state/-/state-0.20.1.tgz"
|
||||||
|
integrity sha512-ms0tlV5A02OK0pFvTtSUGMLkoarzh1F8mr6jy1cD7ucSC2X/VLHtQCxfhdSEGqTYlQF2hoZtmLv+amqhdgbwjQ==
|
||||||
|
|
||||||
|
"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.5.0", "@codemirror/state@^6.5.2", "@codemirror/state@6.x":
|
||||||
version "6.5.2"
|
version "6.5.2"
|
||||||
resolved "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz"
|
resolved "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz"
|
||||||
integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==
|
integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@marijn/find-cluster-break" "^1.0.0"
|
"@marijn/find-cluster-break" "^1.0.0"
|
||||||
|
|
||||||
"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0", "@codemirror/view@6.x":
|
"@codemirror/theme-one-dark@^6.1.3":
|
||||||
version "6.36.8"
|
version "6.1.3"
|
||||||
resolved "https://registry.npmjs.org/@codemirror/view/-/view-6.36.8.tgz"
|
resolved "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz"
|
||||||
integrity sha512-yoRo4f+FdnD01fFt4XpfpMCcCAo9QvZOtbrXExn4SqzH32YC6LgzqxfLZw/r6Ge65xyY03mK/UfUqrVw1gFiFg==
|
integrity sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/language" "^6.0.0"
|
||||||
|
"@codemirror/state" "^6.0.0"
|
||||||
|
"@codemirror/view" "^6.0.0"
|
||||||
|
"@lezer/highlight" "^1.0.0"
|
||||||
|
|
||||||
|
"@codemirror/view@^0.20.0", "@codemirror/view@^0.20.2":
|
||||||
|
version "0.20.7"
|
||||||
|
resolved "https://registry.npmjs.org/@codemirror/view/-/view-0.20.7.tgz"
|
||||||
|
integrity sha512-pqEPCb9QFTOtHgAH5XU/oVy9UR/Anj6r+tG5CRmkNVcqSKEPmBU05WtN/jxJCFZBXf6HumzWC9ydE4qstO3TxQ==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state" "^0.20.0"
|
||||||
|
style-mod "^4.0.0"
|
||||||
|
w3c-keyname "^2.2.4"
|
||||||
|
|
||||||
|
"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0", "@codemirror/view@^6.38.1", "@codemirror/view@6.x":
|
||||||
|
version "6.38.1"
|
||||||
|
resolved "https://registry.npmjs.org/@codemirror/view/-/view-6.38.1.tgz"
|
||||||
|
integrity sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@codemirror/state" "^6.5.0"
|
"@codemirror/state" "^6.5.0"
|
||||||
|
crelt "^1.0.6"
|
||||||
style-mod "^4.1.0"
|
style-mod "^4.1.0"
|
||||||
w3c-keyname "^2.2.4"
|
w3c-keyname "^2.2.4"
|
||||||
|
|
||||||
|
|
@ -353,11 +453,23 @@
|
||||||
"@jridgewell/resolve-uri" "^3.1.0"
|
"@jridgewell/resolve-uri" "^3.1.0"
|
||||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||||
|
|
||||||
"@lezer/common@^1.0.0", "@lezer/common@^1.1.0":
|
"@lezer/common@^0.16.0":
|
||||||
|
version "0.16.1"
|
||||||
|
resolved "https://registry.npmjs.org/@lezer/common/-/common-0.16.1.tgz"
|
||||||
|
integrity sha512-qPmG7YTZ6lATyTOAWf8vXE+iRrt1NJd4cm2nJHK+v7X9TsOF6+HtuU/ctaZy2RCrluxDb89hI6KWQ5LfQGQWuA==
|
||||||
|
|
||||||
|
"@lezer/common@^1.0.0", "@lezer/common@^1.1.0", "@lezer/common@^1.2.0":
|
||||||
version "1.2.3"
|
version "1.2.3"
|
||||||
resolved "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz"
|
resolved "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz"
|
||||||
integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==
|
integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==
|
||||||
|
|
||||||
|
"@lezer/highlight@^0.16.0":
|
||||||
|
version "0.16.0"
|
||||||
|
resolved "https://registry.npmjs.org/@lezer/highlight/-/highlight-0.16.0.tgz"
|
||||||
|
integrity sha512-iE5f4flHlJ1g1clOStvXNLbORJoiW4Kytso6ubfYzHnaNo/eo5SKhxs4wv/rtvwZQeZrK3we8S9SyA7OGOoRKQ==
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common" "^0.16.0"
|
||||||
|
|
||||||
"@lezer/highlight@^1.0.0":
|
"@lezer/highlight@^1.0.0":
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz"
|
resolved "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz"
|
||||||
|
|
@ -365,6 +477,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@lezer/common" "^1.0.0"
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
|
"@lezer/lr@^0.16.0":
|
||||||
|
version "0.16.3"
|
||||||
|
resolved "https://registry.npmjs.org/@lezer/lr/-/lr-0.16.3.tgz"
|
||||||
|
integrity sha512-pau7um4eAw94BEuuShUIeQDTf3k4Wt6oIUOYxMmkZgDHdqtIcxWND4LRxi8nI9KuT4I1bXQv67BCapkxt7Ywqw==
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common" "^0.16.0"
|
||||||
|
|
||||||
"@lezer/lr@^1.0.0":
|
"@lezer/lr@^1.0.0":
|
||||||
version "1.4.2"
|
version "1.4.2"
|
||||||
resolved "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz"
|
resolved "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz"
|
||||||
|
|
@ -1289,7 +1408,7 @@ crc-32@~1.2.0, crc-32@~1.2.1:
|
||||||
resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz"
|
resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz"
|
||||||
integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
|
integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
|
||||||
|
|
||||||
crelt@^1.0.5:
|
crelt@^1.0.5, crelt@^1.0.6:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz"
|
resolved "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz"
|
||||||
integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==
|
integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue