add ui
11
wu-lazy-cloud-network-ui/Dockerfile
Executable file
@@ -0,0 +1,11 @@
|
||||
FROM nginx:1.13.0-alpine
|
||||
COPY dist /usr/share/nginx/html/
|
||||
|
||||
##将nginx配置模板复制过去到指定目录
|
||||
COPY default.template /etc/nginx/conf.d/
|
||||
|
||||
#将docker环境下的命令行路径切换到/etc/nginx/conf.d下执行
|
||||
WORKDIR /etc/nginx/conf.d
|
||||
#添加环境变量的写入
|
||||
|
||||
ENTRYPOINT envsubst < default.template > default.conf && cat default.conf && nginx -g 'daemon off;'
|
||||
21
wu-lazy-cloud-network-ui/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Asa
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
281
wu-lazy-cloud-network-ui/README.md
Normal file
@@ -0,0 +1,281 @@
|
||||
|
||||
|
||||

|
||||
|
||||
# lazy-ui
|
||||
|
||||
**[<font color=#FF0000>✈ 国内加速链接</font>](https://gitee.com/asaasa/lazy-ui)**
|
||||
**[<font color=#FF0000>✈ 效果预览</font>](https://lazy-ui.vercel.app/)**
|
||||
**[<font color=#FF0000>✈ 效果预览(备用地址)</font>](http://asaasa.gitee.io/xujianhua)**
|
||||
**走过路过的老铁,帮忙点个小 ⭐⭐⭐⭐⭐,🤝🤝🤝🤝🤝,🙏🙏🙏🙏🙏**
|
||||
|
||||
## 项目简介
|
||||
|
||||
基于**vue3**和**element-plus**开发的企业后台管理模板.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## 功能特性
|
||||
|
||||
项目使用了最新的**vue3 全家桶**+**element-plus**+**mockjs**+**axios**+**eChart5**.项目继成了**mockServe**,可脱离后端自主开发测试
|
||||
对**axios**深度封装,采用动态路由,路由配置更简单,**mockServe**独立开发测试时可在 nodework 直观查看接口数据
|
||||
基于 node 实现自动化开发
|
||||
|
||||
## 环境依赖
|
||||
|
||||
**node 14+**, **vueCli 4+**
|
||||
|
||||
## 部署步骤
|
||||
|
||||
**npm i**
|
||||
**npm run serve**
|
||||
**yarn build / npm run build**
|
||||
**yarn build --report**
|
||||
|
||||
|
||||
## 目录结构描述
|
||||
|
||||
```
|
||||
│ .browserslistrc 浏览器兼容配置
|
||||
│ .eslintrc.js eslint配置文件
|
||||
│ .gitignore git配置文件
|
||||
│ babel.config.js babel配置文件
|
||||
│ jsconfig.json js配置文件
|
||||
│ LICENSE 开源认证
|
||||
│ package-lock.json
|
||||
│ package.json
|
||||
│ README.md 项目说明
|
||||
│ vue.config.js vue配置文件
|
||||
│
|
||||
├─.vscode vscode配置文件
|
||||
│ settings.json
|
||||
│
|
||||
├─node_modules
|
||||
├─public
|
||||
│ favicon.ico
|
||||
│ index.html
|
||||
│
|
||||
└─src
|
||||
│ App.vue
|
||||
│ main.js
|
||||
│ config.js
|
||||
│
|
||||
├─api api管理模块
|
||||
│ │ index.js api管理入口文件
|
||||
│ │ mock-server.js mock服务配置文件
|
||||
│ │
|
||||
│ └─modules api分模块管理
|
||||
│ system.js 模块api文件
|
||||
│
|
||||
├─assets 静态文件
|
||||
│ logo.png
|
||||
│
|
||||
├─components 公共组件目录
|
||||
│ │ Common.vue
|
||||
│ │ FunctionPage.vue
|
||||
│ │
|
||||
│ ├─dashboard
|
||||
│ │ LiveChart.vue
|
||||
│ │ Shortcuts.vue
|
||||
│ │
|
||||
│ └─layout
|
||||
│ │ NavigateBar.vue
|
||||
│ │ SideBar.vue
|
||||
│ │
|
||||
│ └─components
|
||||
│ Breadcrumb.vue
|
||||
│ Hamburger.vue
|
||||
│ Logo.vue
|
||||
│ Personal.vue
|
||||
│ SlideMenu.vue
|
||||
│
|
||||
├─directives 自定义指令目录
|
||||
│ │ index.js 自定义指令入口文件
|
||||
│ │
|
||||
│ └─modules 自定义指令模块目录
|
||||
│ permission.js
|
||||
│ resize.js
|
||||
│
|
||||
├─plugins 插件目录
|
||||
│ axios.js
|
||||
│ element.js
|
||||
│ mock.js
|
||||
│ permission.js
|
||||
│
|
||||
├─router router目录
|
||||
│ globalRoutes.js
|
||||
│ index.js
|
||||
│ mainRoutes.js
|
||||
│
|
||||
├─store vuex目录
|
||||
│ │ getters.js
|
||||
│ │ index.js
|
||||
│ │
|
||||
│ └─modules vuex模块目录
|
||||
│ app.js
|
||||
│
|
||||
├─styles 样式目录
|
||||
│ common.scss
|
||||
│ variables.scss.js
|
||||
│
|
||||
├─utils 公共方法
|
||||
│ index.js
|
||||
│ validate.js
|
||||
│
|
||||
└─views
|
||||
│ 404.vue
|
||||
│ AppMain.vue
|
||||
│ Home.vue
|
||||
│ IFrame.vue
|
||||
│ Login.vue
|
||||
│
|
||||
└─layoutpages
|
||||
│ common.js
|
||||
│
|
||||
├─leisure
|
||||
│ Game.vue
|
||||
│
|
||||
└─system
|
||||
│ Menus.vue
|
||||
│ Roles.vue
|
||||
│ Users.vue
|
||||
│
|
||||
└─components
|
||||
MenuEdit.vue
|
||||
RoleEdit.vue
|
||||
UsersEdit.vue
|
||||
UsersEditRoute.vue
|
||||
```
|
||||
|
||||
## 使用文档
|
||||
|
||||
### 自定义指令
|
||||
|
||||
**v-permission="[array]"**
|
||||
自定义权限指令,参数为一个数组,数组元素为按钮所对应的 key 值
|
||||
|
||||
```js
|
||||
<el-button
|
||||
v-permission="['add']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.add.name)"
|
||||
>{{ buttons.add.name }}
|
||||
</el-button>
|
||||
```
|
||||
|
||||
**v-resize="myChart"**
|
||||
监听 echart 容器的自定义指令,参数为 echart 实例
|
||||
|
||||
```js
|
||||
<div
|
||||
v-resize="myChart"
|
||||
style="height:400px;margin-top:20px"
|
||||
ref="liveChart"
|
||||
></div>
|
||||
```
|
||||
|
||||
### 动态路由
|
||||
|
||||
动态路由的配置可查看 [src\plugins\permission.js](src\plugins\permission.js)
|
||||
主要原理就是根据后端接口返回的树形菜单数据,动态生成路由表并挂载.具体需求字段可在[src\plugins\permission.js](src\plugins\permission.js)中的**fnAddDynamicMenuRoutes**方法中进行配置修改
|
||||
|
||||
```js
|
||||
let route = {
|
||||
path: menuList[i].url.replace(/\//g, "-") + `-${menuList[i].id}`,
|
||||
component: null,
|
||||
name: menuList[i].url.replace(/\//g, "-") + `-${menuList[i].id}`,
|
||||
// meta: {
|
||||
// }
|
||||
};
|
||||
// url以http[s]://开头, 通过iframe展示
|
||||
if (menuList[i].iframe == 1) {
|
||||
route["path"] = `i-${menuList[i].id}`;
|
||||
route["name"] = `i-${menuList[i].id}`;
|
||||
route["props"] = { url: menuList[i].url };
|
||||
route["component"] = () => import("@/views/IFrame.vue");
|
||||
} else {
|
||||
const l = "views/layoutpages/" + menuList[i].url;
|
||||
route["component"] = () => import("@/" + l + ".vue");
|
||||
}
|
||||
routes.push(route);
|
||||
```
|
||||
|
||||
根据需求可以添加更多路由配置或定制化字段,如路由别名等
|
||||
|
||||
### 接口配置
|
||||
|
||||
项目中对 axios 做了封装配置中添加**Global**字段用来控制是否显示全屏 load,默认为 true,如需修改添加 axios 配置可在[src\plugins\axios.js](src\plugins\axios.js)中进行
|
||||
|
||||
#### 添加接口
|
||||
|
||||
本项目对 mock 做了深度集成,在使用其他项目时,mock 接口和项目接口往往都是分开维护很不方便.所以就放在了一起.只用在一处添加即可.接口目录为[src\api\modules](src\api\modules)**不要修改此目录名称**.在该目录下添加对应的接口文件.
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
login: {
|
||||
//接口名称 必须
|
||||
url: "/login", //接口地址 必须
|
||||
type: "post", //请求类型 必须
|
||||
mock: true, //mock细粒度控制开关,非必须,不填则为false
|
||||
response: (opt) => {
|
||||
//启用mock时的返回数据 opt为请求数据头
|
||||
const {
|
||||
body: { userName, pwd },
|
||||
} = opt;
|
||||
let data = {
|
||||
code: "00",
|
||||
message: "登录成功!",
|
||||
token: new Date().getTime(),
|
||||
uname: userName,
|
||||
};
|
||||
if (userName == "Administrator") {
|
||||
if (pwd != "123456") {
|
||||
data = {
|
||||
code: "01",
|
||||
message: "密码错误",
|
||||
};
|
||||
}
|
||||
}
|
||||
return data;
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
必须使用**module.exports**导出
|
||||
|
||||
#### 接口的使用
|
||||
|
||||
项目中已将封装后 axios 实例挂载到自定义字段 window.VE_API 上.调用方式为:
|
||||
|
||||
```js
|
||||
VE_API [ fileName ][ portName ] (params,[config]) //有全局loading
|
||||
VE_API [ fileName ][ portName ] (params,{Global:false) //没有全局loading
|
||||
```
|
||||
|
||||
### 菜单配置
|
||||
|
||||
项目中的菜单时根据后端返回的树形结构数据动态生成,具体可查看[src\components\layout\components\SlideMenu.vue](src\components\layout\components\SlideMenu.vue)
|
||||
|
||||
## 声明
|
||||
|
||||
个人开发维护! 欢迎交流学习!
|
||||
```shell
|
||||
yarn run build
|
||||
|
||||
```
|
||||
|
||||
docker login --username=1207537021@qq.com registry.cn-hangzhou.aliyuncs.com
|
||||
```shell
|
||||
docker build -t registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-acw-server:ui-master .
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-acw-server:ui-master
|
||||
|
||||
```
|
||||
4
wu-lazy-cloud-network-ui/babel.config.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
presets: ["@vue/cli-plugin-babel/preset"],
|
||||
plugins: ["@vue/babel-plugin-jsx"],
|
||||
};
|
||||
45
wu-lazy-cloud-network-ui/default.template
Normal file
@@ -0,0 +1,45 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
#charset koi8-r;
|
||||
#access_log /var/log/nginx/log/host.access.log main;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
add_header version '${vue_http_response_version}';
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# proxy_pass http://127.0.0.1;
|
||||
#}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# root html;
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
# fastcgi_index index.php;
|
||||
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
|
||||
# include fastcgi_params;
|
||||
#}
|
||||
|
||||
# deny access to .htaccess files, if Apache's document root
|
||||
# concurs with nginx's one
|
||||
#
|
||||
#location ~ /\.ht {
|
||||
# deny all;
|
||||
#}
|
||||
}
|
||||
9
wu-lazy-cloud-network-ui/jsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/*"]
|
||||
}
|
||||
24510
wu-lazy-cloud-network-ui/package-lock.json
generated
Normal file
65
wu-lazy-cloud-network-ui/package.json
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "lazy-ui",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.1.0",
|
||||
"@icon-park/vue-next": "^1.4.2",
|
||||
"@vueuse/core": "^10.2.1",
|
||||
"axios": "^1.4.0",
|
||||
"clipboard": "^2.0.11",
|
||||
"core-js": "^3.20.3",
|
||||
"dayjs": "^1.11.9",
|
||||
"echarts": "^5.4.3",
|
||||
"element-plus": "^2.3.8",
|
||||
"normalize.css": "^8.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"qs": "^6.11.2",
|
||||
"sortablejs": "^1.15.0",
|
||||
"uuid": "^9.0.1",
|
||||
"vue": "^3.3.4",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-router": "^4.2.4",
|
||||
"vue3-json-viewer": "^2.2.2",
|
||||
"vuex": "^4.1.0",
|
||||
"xe-utils": "^3.5.11",
|
||||
"zdog": "^1.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.22.9",
|
||||
"@vue/babel-plugin-jsx": "^1.1.5",
|
||||
"@vue/cli-plugin-babel": "^5.0.8",
|
||||
"@vue/cli-plugin-eslint": "^5.0.8",
|
||||
"@vue/cli-plugin-router": "^5.0.8",
|
||||
"@vue/cli-plugin-vuex": "^5.0.8",
|
||||
"@vue/cli-service": "^5.0.8",
|
||||
"@vue/compiler-sfc": "^3.3.4",
|
||||
"@vue/eslint-config-prettier": "^8.0.0",
|
||||
"compression-webpack-plugin": "^10.0.0",
|
||||
"eslint": "^8.46.0",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"eslint-plugin-vue": "^9.16.0",
|
||||
"lint-staged": "^13.2.3",
|
||||
"mockjs": "^1.1.0",
|
||||
"prettier": "^3.0.0",
|
||||
"sass": "^1.64.1",
|
||||
"sass-loader": "^13.3.2",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"vue-cli-plugin-axios": "^0.0.4",
|
||||
"vue-cli-plugin-element-plus": "^0.0.13",
|
||||
"webpack": "5.78.0"
|
||||
},
|
||||
"gitHooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,vue}": [
|
||||
"vue-cli-service lint --fix"
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
wu-lazy-cloud-network-ui/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
wu-lazy-cloud-network-ui/public/favicon.ico1
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
22
wu-lazy-cloud-network-ui/public/index.html
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-cn">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<!-- <meta name="viewport" content="width=device-width,initial-scale=1.0" /> -->
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong
|
||||
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't
|
||||
work properly without JavaScript enabled. Please enable it to
|
||||
continue.</strong
|
||||
>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
6
wu-lazy-cloud-network-ui/src/App.vue
Normal file
@@ -0,0 +1,6 @@
|
||||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<script setup></script>
|
||||
<style lang="scss" scoped></style>
|
||||
41
wu-lazy-cloud-network-ui/src/api/index.js
Normal file
@@ -0,0 +1,41 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const getPathInfo = (p) => path.parse(p);
|
||||
|
||||
/**
|
||||
* @description // 递归读取文件,类似于webpack的require.context()
|
||||
*
|
||||
* @param {String} directory 文件目录
|
||||
* @param {Boolean} useSubdirectories 是否查询子目录,默认false
|
||||
* @param {array} extList 查询文件后缀,默认 ['.js']
|
||||
*
|
||||
*/
|
||||
function autoLoadFile(directory, useSubdirectories = false, extList = [".js"]) {
|
||||
const filesList = {};
|
||||
// 递归读取文件
|
||||
function readFileList(directory, useSubdirectories, extList) {
|
||||
const files = fs.readdirSync(directory);
|
||||
files.forEach((item) => {
|
||||
const fullPath = path.join(directory, item);
|
||||
const stat = fs.statSync(fullPath);
|
||||
if (stat.isDirectory() && useSubdirectories) {
|
||||
readFileList(
|
||||
path.join(directory, item),
|
||||
useSubdirectories,
|
||||
extList,
|
||||
);
|
||||
} else {
|
||||
const info = getPathInfo(fullPath);
|
||||
|
||||
if (extList.includes(info.ext)) {
|
||||
filesList[info.name] = require(fullPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
readFileList(directory, useSubdirectories, extList);
|
||||
|
||||
return filesList;
|
||||
}
|
||||
|
||||
module.exports = autoLoadFile(path.join(__dirname, "./modules"));
|
||||
103
wu-lazy-cloud-network-ui/src/api/mock-server.js
Normal file
@@ -0,0 +1,103 @@
|
||||
// const bodyParser = require("body-parser");
|
||||
const express = require("express");
|
||||
const chokidar = require("chokidar");
|
||||
const chalk = require("chalk");
|
||||
const path = require("path");
|
||||
const Mock = require("mockjs");
|
||||
const apiDir = path.join(process.cwd(), "src/api");
|
||||
|
||||
// 注册mock接口路径
|
||||
function registerRoutes(app) {
|
||||
let mockLastIndex;
|
||||
let mocksForServer = new Array();
|
||||
const api = require("./index.js");
|
||||
Object.keys(api).map((route) => {
|
||||
Object.keys(api[route]).map((item) => {
|
||||
api[route][item].mock &&
|
||||
mocksForServer.push(
|
||||
responseFake(
|
||||
api[route][item].url,
|
||||
api[route][item].type,
|
||||
api[route][item].response,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
// 注册接口
|
||||
for (const mock of mocksForServer) {
|
||||
app[mock.type](mock.url, mock.response);
|
||||
mockLastIndex = app._router.stack.length;
|
||||
// console.log(app._router.stack[12])
|
||||
}
|
||||
// 获取接口的长度
|
||||
const mockRoutesLength = mocksForServer.length;
|
||||
// 注意:mockRoutesLength并不等于定于路由路径的数量,还包括其他路由
|
||||
// console.log(mockRoutesLength,mockLastIndex)
|
||||
return {
|
||||
mockRoutesLength,
|
||||
mockStartIndex: mockLastIndex - mockRoutesLength,
|
||||
};
|
||||
}
|
||||
// 模拟mock server
|
||||
const responseFake = (url, type, respond) => {
|
||||
return {
|
||||
url: url,
|
||||
type: type || "get",
|
||||
response: (req, res) => {
|
||||
console.log(chalk.red("请求", req.path));
|
||||
res.json(
|
||||
Mock.mock(
|
||||
respond instanceof Function ? respond(req, res) : respond,
|
||||
),
|
||||
);
|
||||
},
|
||||
};
|
||||
};
|
||||
// 移除路由
|
||||
function unregisterRoutes() {
|
||||
Object.keys(require.cache).forEach((i) => {
|
||||
console.log(apiDir, i);
|
||||
if (i.includes(apiDir)) {
|
||||
delete require.cache[require.resolve(i)];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 导出服务器app
|
||||
module.exports = (app) => {
|
||||
// 解析post数据
|
||||
app.use(express.json());
|
||||
app.use(
|
||||
express.urlencoded({
|
||||
extended: true,
|
||||
}),
|
||||
);
|
||||
|
||||
// 注册路由表到app上
|
||||
const mockRoutes = registerRoutes(app);
|
||||
let mockRoutesLength = mockRoutes.mockRoutesLength;
|
||||
let mockStartIndex = mockRoutes.mockStartIndex;
|
||||
//* 观察mock下的文件变化(不包括mock-server.js),热更新文件,这样添加数据路由就不用重启了
|
||||
chokidar
|
||||
.watch(apiDir, {
|
||||
ignored: /mock-server/,
|
||||
ignoreInitial: true,
|
||||
})
|
||||
.on("all", (event, path) => {
|
||||
try {
|
||||
// 先移除之前的路由
|
||||
app._router.stack.splice(mockStartIndex, mockRoutesLength);
|
||||
// 清除缓冲
|
||||
unregisterRoutes();
|
||||
// 重新注册路由
|
||||
const mockRoutes = registerRoutes(app);
|
||||
mockRoutesLength = mockRoutes.mockRoutesLength;
|
||||
mockStartIndex = mockRoutes.mockStartIndex;
|
||||
console.log(
|
||||
chalk.magentaBright(`\n > 接口更新成功 --> 详情 ${path}`),
|
||||
);
|
||||
} catch (err) {
|
||||
console.log(chalk.redBright(err));
|
||||
}
|
||||
});
|
||||
};
|
||||
1165
wu-lazy-cloud-network-ui/src/api/modules/system.js
Normal file
1
wu-lazy-cloud-network-ui/src/assets/json/china.json
Normal file
BIN
wu-lazy-cloud-network-ui/src/assets/logo.png
Normal file
|
After Width: | Height: | Size: 188 KiB |
506
wu-lazy-cloud-network-ui/src/components/Common.vue
Normal file
@@ -0,0 +1,506 @@
|
||||
<template>
|
||||
<div class="ve_404">
|
||||
<!-- partial:index.partial.html -->
|
||||
<div class="moon"></div>
|
||||
<div class="moon__crater moon__crater1"></div>
|
||||
<div class="moon__crater moon__crater2"></div>
|
||||
<div class="moon__crater moon__crater3"></div>
|
||||
<div class="star star1">⭐</div>
|
||||
<div class="star star2">⭐</div>
|
||||
<div class="star star3">⭐</div>
|
||||
<div class="star star4">⭐</div>
|
||||
<div class="star star5">⭐</div>
|
||||
<slot>
|
||||
<div class="error">
|
||||
<div class="error__title">404</div>
|
||||
<div class="error__subtitle">🐱🐱🐱(⓿_⓿)🐱🐱🐱</div>
|
||||
<div class="error__description">看来你是迷路了......</div>
|
||||
<router-link to="/">
|
||||
<button class="error__button error__button--active">
|
||||
回到首页
|
||||
</button>
|
||||
</router-link>
|
||||
<!-- <button class="error__button">CONTACT</button> -->
|
||||
</div>
|
||||
</slot>
|
||||
<div class="astronaut" v-resize="{ resize: draw3dAstronaut }">
|
||||
<canvas ref="cav"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Zdog from "zdog";
|
||||
import { ref, onUnmounted, onMounted } from "vue";
|
||||
|
||||
const cav = ref(null);
|
||||
let timer = null;
|
||||
onMounted(() => {
|
||||
draw3dAstronaut();
|
||||
});
|
||||
/**
|
||||
* @description: 画3d太空人
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const draw3dAstronaut = () => {
|
||||
if (!cav.value || !cav.value.parentNode) {
|
||||
console.log("cav.value.parentNode is null" + cav.value);
|
||||
return;
|
||||
}
|
||||
cav.value.width = cav.value.parentNode.clientWidth;
|
||||
cav.value.height = cav.value.parentNode.clientHeight;
|
||||
|
||||
// colours
|
||||
let dark_navy = "#131e38";
|
||||
let orange = "#fe9642";
|
||||
let cream = "#FFF8E7";
|
||||
let light_purple = "#7f3f98";
|
||||
let dark_purple = "#563795";
|
||||
let cheese = "#fbc715";
|
||||
|
||||
// create illo
|
||||
let illo = new Zdog.Illustration({
|
||||
// set canvas with selector
|
||||
element: cav.value,
|
||||
dragRotate: true,
|
||||
zoom: 0.65,
|
||||
});
|
||||
|
||||
/** Body **/
|
||||
// Body
|
||||
let body = new Zdog.RoundedRect({
|
||||
addTo: illo,
|
||||
width: 200,
|
||||
height: 220,
|
||||
color: "white",
|
||||
fill: true,
|
||||
cornerRadius: 16,
|
||||
stroke: 60,
|
||||
});
|
||||
|
||||
// Backpack
|
||||
new Zdog.RoundedRect({
|
||||
addTo: body,
|
||||
width: 180,
|
||||
height: 310,
|
||||
color: orange,
|
||||
fill: true,
|
||||
cornerRadius: 24,
|
||||
stroke: 120,
|
||||
translate: { z: -85, y: -60 },
|
||||
});
|
||||
|
||||
/** arm **/
|
||||
let arm = new Zdog.RoundedRect({
|
||||
addTo: body,
|
||||
height: 30,
|
||||
width: 28,
|
||||
stroke: 60,
|
||||
fill: true,
|
||||
color: dark_purple,
|
||||
translate: { x: -140, y: -64 },
|
||||
cornerRadius: 0.05,
|
||||
});
|
||||
|
||||
new Zdog.RoundedRect({
|
||||
addTo: arm,
|
||||
height: 120,
|
||||
width: 12,
|
||||
stroke: 60,
|
||||
fill: true,
|
||||
color: cream,
|
||||
translate: { y: 120 },
|
||||
cornerRadius: 0.05,
|
||||
});
|
||||
|
||||
// bubble_arm
|
||||
let bubble_arm = new Zdog.Shape({
|
||||
addTo: arm,
|
||||
path: [{ x: -20 }, { x: 20 }],
|
||||
stroke: 32,
|
||||
color: light_purple,
|
||||
translate: { y: 210 },
|
||||
});
|
||||
|
||||
bubble_arm.copy({
|
||||
color: dark_purple,
|
||||
translate: { y: 230 },
|
||||
});
|
||||
|
||||
// hand
|
||||
new Zdog.RoundedRect({
|
||||
addTo: bubble_arm,
|
||||
height: 32,
|
||||
width: 22,
|
||||
translate: { x: -8, y: 60 },
|
||||
fill: true,
|
||||
color: cheese,
|
||||
stroke: 30,
|
||||
});
|
||||
|
||||
new Zdog.RoundedRect({
|
||||
addTo: bubble_arm,
|
||||
height: 24,
|
||||
width: 0,
|
||||
translate: { x: 24, y: 50 },
|
||||
fill: true,
|
||||
color: orange,
|
||||
stroke: 20,
|
||||
});
|
||||
|
||||
arm.copyGraph({
|
||||
translate: { x: 140, y: -64 },
|
||||
rotate: { y: Zdog.TAU / 2 },
|
||||
});
|
||||
|
||||
/** Leg **/
|
||||
let leg = new Zdog.RoundedRect({
|
||||
addTo: body,
|
||||
height: 160,
|
||||
width: 28,
|
||||
stroke: 60,
|
||||
fill: true,
|
||||
color: cream,
|
||||
translate: { x: -56, y: 230 },
|
||||
cornerRadius: 0.05,
|
||||
});
|
||||
|
||||
// bubble_leg
|
||||
let bubble_leg = new Zdog.Shape({
|
||||
addTo: leg,
|
||||
path: [{ x: -28 }, { x: 28 }],
|
||||
stroke: 32,
|
||||
color: light_purple,
|
||||
translate: { y: 100 },
|
||||
});
|
||||
|
||||
bubble_leg.copy({
|
||||
color: dark_purple,
|
||||
translate: { y: 124 },
|
||||
});
|
||||
|
||||
// foot
|
||||
new Zdog.RoundedRect({
|
||||
addTo: leg,
|
||||
width: 96,
|
||||
height: 24,
|
||||
stroke: 40,
|
||||
fill: true,
|
||||
color: cheese,
|
||||
translate: { x: -24, y: 170 },
|
||||
cornerRadius: 24,
|
||||
});
|
||||
|
||||
leg.copyGraph({
|
||||
translate: { x: 56, y: 230 },
|
||||
rotate: { y: Zdog.TAU / 2 },
|
||||
});
|
||||
|
||||
/** Head **/
|
||||
// Head
|
||||
let head = new Zdog.RoundedRect({
|
||||
addTo: body,
|
||||
width: 216,
|
||||
height: 180,
|
||||
depth: 40,
|
||||
cornerRadius: 80,
|
||||
stroke: 60,
|
||||
color: cream,
|
||||
fill: true,
|
||||
translate: { y: -300 },
|
||||
});
|
||||
|
||||
//add helmet
|
||||
let helmet = new Zdog.RoundedRect({
|
||||
addTo: head,
|
||||
width: 210,
|
||||
height: 165,
|
||||
cornerRadius: 64,
|
||||
color: dark_navy,
|
||||
fill: true,
|
||||
backface: false,
|
||||
translate: { z: 20 },
|
||||
});
|
||||
|
||||
//add refletion
|
||||
new Zdog.Rect({
|
||||
addTo: helmet,
|
||||
width: 48,
|
||||
height: 2,
|
||||
stroke: 10,
|
||||
translate: { x: 24, y: -24, z: 10 },
|
||||
color: "white",
|
||||
backface: false,
|
||||
});
|
||||
|
||||
// add ear
|
||||
let ear = new Zdog.RoundedRect({
|
||||
addTo: head,
|
||||
width: 36,
|
||||
height: 72,
|
||||
cornerRadius: 80,
|
||||
stroke: 20,
|
||||
color: orange,
|
||||
fill: true,
|
||||
translate: { x: -140 },
|
||||
});
|
||||
|
||||
ear.copy({
|
||||
translate: { x: 140 },
|
||||
});
|
||||
|
||||
// neck
|
||||
let neck = new Zdog.Shape({
|
||||
addTo: head,
|
||||
path: [{ x: -110 }, { x: 110 }],
|
||||
translate: { y: 120 },
|
||||
stroke: 40,
|
||||
color: light_purple,
|
||||
});
|
||||
|
||||
neck.copy({
|
||||
translate: { y: 160 },
|
||||
color: dark_purple,
|
||||
});
|
||||
|
||||
/** extra **/
|
||||
let stripe_1 = new Zdog.Shape({
|
||||
addTo: body,
|
||||
path: [{ x: -20 }, { x: 20 }],
|
||||
stroke: 10,
|
||||
translate: { x: 200, z: 200 },
|
||||
color: cheese,
|
||||
});
|
||||
|
||||
stripe_1.copy({
|
||||
translate: { x: 320, y: 200, z: -400 },
|
||||
color: cheese,
|
||||
});
|
||||
|
||||
stripe_1.copy({
|
||||
translate: { x: -220, y: 300, z: -400 },
|
||||
color: "white",
|
||||
});
|
||||
|
||||
stripe_1.copy({
|
||||
translate: { x: -100, y: 400, z: -280 },
|
||||
color: light_purple,
|
||||
});
|
||||
|
||||
stripe_1.copy({
|
||||
translate: { x: 50, y: -60, z: 150 },
|
||||
color: orange,
|
||||
});
|
||||
|
||||
stripe_1.copy({
|
||||
translate: { x: -250, y: 80, z: 300 },
|
||||
color: light_purple,
|
||||
});
|
||||
|
||||
stripe_1.copy({
|
||||
translate: { x: -350, y: -280, z: 175 },
|
||||
color: dark_purple,
|
||||
});
|
||||
|
||||
stripe_1.copy({
|
||||
translate: { x: 250, y: -380, z: -175 },
|
||||
color: "white",
|
||||
});
|
||||
|
||||
// update & render
|
||||
illo.updateRenderGraph();
|
||||
|
||||
function animate() {
|
||||
// rotate illo each frame
|
||||
illo.rotate.y += 0.005;
|
||||
illo.rotate.x += 0.005;
|
||||
illo.rotate.z += 0.005;
|
||||
illo.updateRenderGraph();
|
||||
// animate next frame
|
||||
timer = requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
// start animation
|
||||
animate();
|
||||
};
|
||||
onUnmounted(() => {
|
||||
cancelAnimationFrame(timer);
|
||||
timer = null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ve_404 {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(90deg, #2f3640 23%, #181b20 100%);
|
||||
}
|
||||
|
||||
.moon {
|
||||
background: linear-gradient(90deg, #d0d0d0 48%, #919191 100%);
|
||||
position: absolute;
|
||||
top: -30vh;
|
||||
left: -80vh;
|
||||
width: 160vh;
|
||||
height: 160%;
|
||||
content: "";
|
||||
border-radius: 50%;
|
||||
box-shadow: 0px 0px 30px -4px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.moon__crater {
|
||||
position: absolute;
|
||||
content: "";
|
||||
border-radius: 100%;
|
||||
background: linear-gradient(90deg, #7a7a7a 38%, #c3c3c3 100%);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.moon__crater1 {
|
||||
top: 250px;
|
||||
left: 500px;
|
||||
width: 60px;
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
.moon__crater2 {
|
||||
top: 650px;
|
||||
left: 340px;
|
||||
width: 40px;
|
||||
height: 80px;
|
||||
transform: rotate(55deg);
|
||||
}
|
||||
|
||||
.moon__crater3 {
|
||||
top: -20px;
|
||||
left: 40px;
|
||||
width: 65px;
|
||||
height: 120px;
|
||||
transform: rotate(250deg);
|
||||
}
|
||||
|
||||
.star {
|
||||
color: grey;
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
content: "";
|
||||
border-radius: 100%;
|
||||
transform: rotate(250deg);
|
||||
opacity: 0.4;
|
||||
animation-name: shimmer;
|
||||
animation-duration: 1.5s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.star1 {
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
.star2 {
|
||||
top: 60%;
|
||||
left: 90%;
|
||||
animation-delay: 3s;
|
||||
}
|
||||
|
||||
.star3 {
|
||||
top: 10%;
|
||||
left: 70%;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
|
||||
.star4 {
|
||||
top: 90%;
|
||||
left: 40%;
|
||||
}
|
||||
|
||||
.star5 {
|
||||
top: 20%;
|
||||
left: 30%;
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
|
||||
.astronaut {
|
||||
position: absolute;
|
||||
width: 60vw;
|
||||
height: 100vh;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.error {
|
||||
position: absolute;
|
||||
left: 100px;
|
||||
top: 400px;
|
||||
transform: translateY(-60%);
|
||||
font-family: "Righteous", cursive;
|
||||
color: #363e49;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.error__title {
|
||||
font-size: 10em;
|
||||
font-weight: bold;
|
||||
color: #d0d0d0;
|
||||
text-shadow: -5px -5px 0 rgba(0, 0, 0, 0.7);
|
||||
background-image: linear-gradient(90deg, #d0d0d0 48%, #919191 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.error__subtitle {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.error__description {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.error__button {
|
||||
min-width: 7em;
|
||||
margin-top: 3em;
|
||||
margin-right: 0.5em;
|
||||
padding: 0.5em 2em;
|
||||
outline: none;
|
||||
border: 2px solid #2f3640;
|
||||
background-color: transparent;
|
||||
border-radius: 8em;
|
||||
color: #576375;
|
||||
cursor: pointer;
|
||||
transition-duration: 0.2s;
|
||||
font-size: 0.75em;
|
||||
font-family: "Righteous", cursive;
|
||||
}
|
||||
|
||||
.error__button:hover {
|
||||
color: #21252c;
|
||||
}
|
||||
|
||||
.error__button--active {
|
||||
background-color: $base-color;
|
||||
border: 2px solid $base-color;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.error__button--active:hover {
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.5);
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
30
wu-lazy-cloud-network-ui/src/components/FunctionPage.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-page-header
|
||||
@back="$router.back()"
|
||||
:content="title"
|
||||
></el-page-header>
|
||||
<el-alert
|
||||
style="margin-top: 20px"
|
||||
type="info"
|
||||
description="当前为动态权限页面!离开后将无法访问!刷新页面请使用本系统自带刷新按钮!!!"
|
||||
show-icon
|
||||
close-text="知道了"
|
||||
></el-alert>
|
||||
<el-divider></el-divider>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { toRefs, defineProps } from "vue";
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
require: true,
|
||||
},
|
||||
});
|
||||
const { title } = toRefs(props);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
111
wu-lazy-cloud-network-ui/src/components/dashboard/LiveChart.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div
|
||||
v-resize="myChart"
|
||||
style="height: 400px; margin-top: 20px"
|
||||
ref="liveChart"
|
||||
></div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as echarts from "echarts/core";
|
||||
import {
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
} from "echarts/components";
|
||||
import { BarChart } from "echarts/charts";
|
||||
import { CanvasRenderer } from "echarts/renderers";
|
||||
import * as dayjs from "dayjs";
|
||||
import { unwarp } from "@/utils";
|
||||
import { onMounted, ref, onUnmounted } from "vue";
|
||||
|
||||
/**
|
||||
* @description: 生成20条数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const dataList = () => {
|
||||
let date = [];
|
||||
let num = [];
|
||||
let nowTime = new Date().getTime();
|
||||
for (let i = 0; i < 30; i++) {
|
||||
date.push(dayjs(nowTime - i * 1000).format("HH:mm:ss"));
|
||||
num.push((Math.random() * 10).toFixed(0) * 1);
|
||||
}
|
||||
return {
|
||||
date: date.reverse(),
|
||||
num,
|
||||
};
|
||||
};
|
||||
|
||||
echarts.use([
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
BarChart,
|
||||
CanvasRenderer,
|
||||
]);
|
||||
const liveChart = ref(null);
|
||||
const myChart = ref(null);
|
||||
let timer = null;
|
||||
|
||||
let $_dataList = dataList();
|
||||
let option = {
|
||||
title: {
|
||||
text: "用户访问量",
|
||||
},
|
||||
grid: {
|
||||
left: "0",
|
||||
right: "0",
|
||||
top: "10%",
|
||||
bottom: "0",
|
||||
containLabel: true,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
},
|
||||
xAxis: {
|
||||
data: $_dataList.date,
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: $_dataList.num,
|
||||
type: "bar",
|
||||
showBackground: true,
|
||||
backgroundStyle: {
|
||||
color: "rgba(180, 180, 180, 0.2)",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
/**
|
||||
* @description: 动态数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getNewData = (myChart) => {
|
||||
unwarp(myChart.value).setOption(option);
|
||||
|
||||
timer = setInterval(() => {
|
||||
$_dataList.date.shift();
|
||||
$_dataList.num.shift();
|
||||
$_dataList.date.push(dayjs(new Date().getTime()).format("HH:mm:ss"));
|
||||
$_dataList.num.push((Math.random() * 10).toFixed(0) * 1);
|
||||
unwarp(myChart.value).setOption(option);
|
||||
}, 1000);
|
||||
};
|
||||
onMounted(() => {
|
||||
myChart.value = echarts.init(liveChart.value);
|
||||
getNewData(myChart);
|
||||
});
|
||||
onUnmounted(() => {
|
||||
unwarp(myChart.value).dispose();
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
381
wu-lazy-cloud-network-ui/src/components/dashboard/Shortcuts.vue
Normal file
@@ -0,0 +1,381 @@
|
||||
<template>
|
||||
<el-row :gutter="20" style="padding-bottom: 10px">
|
||||
<!-- <el-col :span="12">-->
|
||||
<!-- <div class="ve-card ve_card1">-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <football />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- <div>-->
|
||||
<!-- <p>菜单数量</p>-->
|
||||
<!-- <span>{{ shortcutsData.menuNum }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
<el-col :span="12">
|
||||
<div class="ve-card ve_card2">
|
||||
<el-icon>
|
||||
<user />
|
||||
</el-icon>
|
||||
<div>
|
||||
<p>用户数量</p>
|
||||
<span>{{ shortcutsData.userNum }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="ve-card ve_card1">
|
||||
<el-icon>
|
||||
<grape />
|
||||
</el-icon>
|
||||
<div>
|
||||
<p>数据库实例数量</p>
|
||||
<span>{{ shortcutsData.instanceNum }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col style="padding: 20px">
|
||||
<!-- 内存 -->
|
||||
|
||||
<el-card
|
||||
shadow="always"
|
||||
class="box-card"
|
||||
style="
|
||||
width: 100%;
|
||||
/*flex-wrap: wrap;*/
|
||||
/*float: left;*/
|
||||
/*position: fixed;*/
|
||||
/*display: flex;*/
|
||||
/*flex-wrap: wrap;*/
|
||||
"
|
||||
>
|
||||
<el-progress
|
||||
type="circle"
|
||||
:width="140"
|
||||
:stroke-width="15"
|
||||
:color="colors"
|
||||
:percentage="
|
||||
Number(
|
||||
shortcutsData.useMemory / shortcutsData.totalMemory,
|
||||
) * 100
|
||||
"
|
||||
>
|
||||
<span class="percentage-value"
|
||||
>{{
|
||||
shortcutsData.useMemory +
|
||||
"/" +
|
||||
shortcutsData.totalMemory
|
||||
}}MB</span
|
||||
>
|
||||
<span class="percentage-label">JVM内存使用</span>
|
||||
<span class="percentage-label">
|
||||
<el-button @click="gc()">GC</el-button>
|
||||
</span>
|
||||
</el-progress>
|
||||
<!-- cpu -->
|
||||
<el-progress
|
||||
type="circle"
|
||||
:width="140"
|
||||
:stroke-width="15"
|
||||
:color="colors"
|
||||
:percentage="cpuData.used"
|
||||
>
|
||||
<span class="percentage-value">{{ cpuData.used }}%</span>
|
||||
<span class="percentage-label">当前线程CPU使用</span>
|
||||
<span class="percentage-label">
|
||||
<el-button @click="getCpu()">cpu</el-button>
|
||||
</span>
|
||||
</el-progress>
|
||||
<el-progress
|
||||
type="circle"
|
||||
:width="140"
|
||||
:stroke-width="15"
|
||||
:color="colors"
|
||||
:percentage="cpuData.sys"
|
||||
>
|
||||
<span class="percentage-value">{{ cpuData.sys }}%</span>
|
||||
<span class="percentage-label">当前系统CPU使用</span>
|
||||
<span class="percentage-label">
|
||||
<el-button @click="getCpu()">cpu</el-button>
|
||||
</span>
|
||||
</el-progress>
|
||||
<el-progress>
|
||||
<span class="percentage-value"
|
||||
>CUP名称: {{ cpuData.name }}</span
|
||||
>
|
||||
<span class="percentage-value"
|
||||
>CUP架构: {{ cpuData.arch }}</span
|
||||
>
|
||||
<span class="percentage-value"
|
||||
>CUP版本: {{ cpuData.version }}</span
|
||||
>
|
||||
<span class="percentage-value"
|
||||
>CUP核心数: {{ cpuData.cpuNum }}核</span
|
||||
>
|
||||
</el-progress>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- <el-col :span="12">-->
|
||||
<!-- <div class="ve-card ve_card3">-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <ice-cream />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- <div>-->
|
||||
<!-- <p>角色数量</p>-->
|
||||
<!-- <span>{{ shortcutsData.roleNum }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
<!-- <el-col :span="12">-->
|
||||
<!-- <div class="ve-card ve_card4">-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <food />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- <div>-->
|
||||
<!-- <p>资料数量</p>-->
|
||||
<!-- <span>{{ shortcutsData.menuNum }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
</el-row>
|
||||
<!-- <el-row :gutter="20" style="padding-top: 10px">-->
|
||||
<!-- <el-col :span="12">-->
|
||||
<!-- <div class="ve-card ve_card1">-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <grape />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- <div>-->
|
||||
<!-- <p>数据库实例数量</p>-->
|
||||
<!-- <span>{{ shortcutsData.instanceNum }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
<!-- <el-col :span="12">-->
|
||||
<!-- <div class="ve-card ve_card2">-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <histogram />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- <div>-->
|
||||
<!-- <p>数据库数量</p>-->
|
||||
<!-- <span>{{ shortcutsData.schemaNum }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
<!-- <el-col :span="12">-->
|
||||
<!-- <div class="ve-card ve_card3">-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <management />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- <div>-->
|
||||
<!-- <p>表数量</p>-->
|
||||
<!-- <span>{{ shortcutsData.tableNum }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
<!-- <el-col :span="12">-->
|
||||
<!-- <div class="ve-card ve_card4">-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <position />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- <div>-->
|
||||
<!-- <p>表列数量</p>-->
|
||||
<!-- <span>{{ shortcutsData.tableColumnNum }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
<!-- </el-row>-->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
|
||||
const shortcutsData = ref({
|
||||
menuNum: 0,
|
||||
roleNum: 0,
|
||||
userNum: 0,
|
||||
instanceNum: 0,
|
||||
schemaNum: 0,
|
||||
tableNum: 0,
|
||||
tableColumnNum: 0,
|
||||
maxMemory: 0,
|
||||
totalMemory: 1,
|
||||
freeMemory: 0,
|
||||
useMemory: 0,
|
||||
});
|
||||
const cpuData = ref({
|
||||
cpuNum: "0",
|
||||
total: "0",
|
||||
sys: "0.00",
|
||||
used: "0.00",
|
||||
wait: "0.00",
|
||||
free: "0.00",
|
||||
name: "",
|
||||
arch: "",
|
||||
version: "",
|
||||
});
|
||||
|
||||
const colors = [
|
||||
{ color: "#f56c6c", percentage: 100 },
|
||||
{ color: "#e6a23c", percentage: 80 },
|
||||
{ color: "#5cb87a", percentage: 60 },
|
||||
{ color: "#1989fa", percentage: 40 },
|
||||
{ color: "#6f7ad3", percentage: 20 },
|
||||
];
|
||||
|
||||
const timer = ref();
|
||||
|
||||
/**
|
||||
* 获取jvm信息
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getJvmInfo = async () => {
|
||||
const { code, data } = await VE_API.system.jvmRunTimeMemory();
|
||||
if (code === 0) {
|
||||
console.log(data);
|
||||
shortcutsData.value.maxMemory = data.maxMemory;
|
||||
shortcutsData.value.totalMemory = data.totalMemory;
|
||||
shortcutsData.value.freeMemory = data.freeMemory;
|
||||
shortcutsData.value.useMemory = data.useMemory;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* gc
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const gc = async () => {
|
||||
const { code, data } = await VE_API.system.jvmGC();
|
||||
if (code === 0) {
|
||||
console.log(data);
|
||||
await getJvmInfo();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* gc
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getCpu = async () => {
|
||||
const { code, data } = await VE_API.system.jvmCPU();
|
||||
if (code === 0) {
|
||||
cpuData.value = data;
|
||||
console.log(data);
|
||||
}
|
||||
};
|
||||
onMounted(async () => {
|
||||
const { code, data } = await VE_API.system.shortcutsData();
|
||||
if (code === 0) {
|
||||
console.log(data);
|
||||
shortcutsData.value = data;
|
||||
}
|
||||
await getJvmInfo();
|
||||
await getCpu();
|
||||
timer.value = setTimeout(() => {
|
||||
//需要定时执行的代码
|
||||
getJvmInfo();
|
||||
getCpu();
|
||||
}, 3000);
|
||||
});
|
||||
onUnmounted(() => {
|
||||
clearTimeout(timer.value);
|
||||
timer.value = "";
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-row {
|
||||
height: 50%;
|
||||
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.ve-card {
|
||||
border-radius: 10px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 500ms;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 3px 3px 6px 1px rgba(0, 0, 0, 0.2);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 100px;
|
||||
margin: 0 20px;
|
||||
}
|
||||
|
||||
div {
|
||||
flex: 1;
|
||||
padding-right: 12px;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 60px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ve_card1 {
|
||||
background: #409eff;
|
||||
|
||||
&:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
.ve_card2 {
|
||||
background: #67c23a;
|
||||
|
||||
&:hover {
|
||||
color: #67c23a;
|
||||
}
|
||||
}
|
||||
|
||||
.ve_card3 {
|
||||
background: #e6a23c;
|
||||
|
||||
&:hover {
|
||||
color: #e6a23c;
|
||||
}
|
||||
}
|
||||
|
||||
.ve_card4 {
|
||||
background: #f56c6c;
|
||||
|
||||
&:hover {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
.percentage-value {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.percentage-label {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.el-progress--line {
|
||||
margin-bottom: 15px;
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.el-progress--circle {
|
||||
margin-right: 15px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div class="ve_nav_bar">
|
||||
<hamburger></hamburger>
|
||||
<breadcrumb></breadcrumb>
|
||||
<personal></personal>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import Hamburger from "./components/Hamburger.vue";
|
||||
import Breadcrumb from "./components/Breadcrumb.vue";
|
||||
import Personal from "./components/Personal.vue";
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.ve_nav_bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
61
wu-lazy-cloud-network-ui/src/components/layout/SideBar.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<router-link to="/">
|
||||
<logo />
|
||||
</router-link>
|
||||
<div class="ve_el_menu">
|
||||
<el-scrollbar>
|
||||
<el-menu
|
||||
:default-active="defaultActive"
|
||||
:collapse="opened"
|
||||
:collapseTransition="false"
|
||||
unique-opened
|
||||
:background-color="sideBgColor"
|
||||
:text-color="sideTextColor"
|
||||
:active-text-color="sideActiveTextColor"
|
||||
>
|
||||
<slide-menu
|
||||
v-for="item in menus"
|
||||
:key="item.id"
|
||||
:menu="item"
|
||||
></slide-menu>
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
nav_height,
|
||||
sideBgColor,
|
||||
sideTextColor,
|
||||
sideActiveTextColor,
|
||||
} from "@/styles/variables.scss.js";
|
||||
import { computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { useRoute } from "vue-router";
|
||||
import Logo from "./components/Logo";
|
||||
import SlideMenu from "./components/SlideMenu";
|
||||
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const opened = computed(() => store.getters.opened);
|
||||
const menus = computed(() => store.getters.menuList);
|
||||
const defaultActive = computed(() => {
|
||||
let i = route.name.indexOf("/");
|
||||
if (i < 0) {
|
||||
return "/" + route.name;
|
||||
} else {
|
||||
return "/" + route.name.slice(0, i);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
a:active {
|
||||
color: $base-color;
|
||||
}
|
||||
.ve_el_menu {
|
||||
background: $sideBgColor;
|
||||
height: calc(100vh - v-bind(nav_height));
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
|
||||
<el-breadcrumb-item v-for="(item, index) in list" :key="index">
|
||||
{{ item }}
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { treeFindPath } from "@/utils";
|
||||
import { useStore } from "vuex";
|
||||
import { useRoute } from "vue-router";
|
||||
import { computed } from "vue";
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const menuList = computed(() => store.getters.menuList).value;
|
||||
const list = computed(() => {
|
||||
let name = route.name;
|
||||
let i = route.name.indexOf("/");
|
||||
if (i > -1) {
|
||||
name = route.name.slice(0, i);
|
||||
}
|
||||
let j = name.lastIndexOf("-");
|
||||
return treeFindPath(
|
||||
menuList,
|
||||
(data) => data.id === name.slice(j + 1) * 1,
|
||||
"name",
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="ve_slider_menu" @click="fn_slider_menu">
|
||||
<el-icon>
|
||||
<component :is="opened ? 'expand' : 'fold'" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { TOGGLE_SLIDER } from "@/store/modules/app/type";
|
||||
import { computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
const store = useStore();
|
||||
const opened = computed(() => store.getters.opened);
|
||||
const fn_slider_menu = () => {
|
||||
store.dispatch(`app/${TOGGLE_SLIDER}`);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ve_slider_menu {
|
||||
cursor: pointer;
|
||||
margin-right: 10px;
|
||||
i {
|
||||
font-size: 40px;
|
||||
}
|
||||
&:hover i {
|
||||
color: $base-color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<el-tooltip :content="title" placement="right-end" effect="dark">
|
||||
<div class="ve_menu_logo">
|
||||
<div class="ve_logo_img">
|
||||
<el-image
|
||||
style="height: 100%"
|
||||
:src="require('../../../assets/logo.png')"
|
||||
fit="contain"
|
||||
></el-image>
|
||||
</div>
|
||||
<!-- content to trigger tooltip here -->
|
||||
<h3 v-show="!opened" class="ve_logo_title">
|
||||
{{ title }}
|
||||
</h3>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
const store = useStore();
|
||||
const opened = computed(() => store.getters.opened);
|
||||
const title = "lazy-ui";
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ve_menu_logo {
|
||||
width: 100%;
|
||||
height: $nav-height;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
.ve_logo_img {
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
// 和side收缩后的宽度一致
|
||||
width: $side-close-width;
|
||||
// padding: 10px;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.ve_logo_title {
|
||||
width: $side-open-width;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
color: #000;
|
||||
&:hover {
|
||||
color: $base-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<div class="ve_personal">
|
||||
<el-button-group>
|
||||
<el-button
|
||||
title="刷新"
|
||||
style="border: none; font-size: 20px"
|
||||
circle
|
||||
plain
|
||||
@click="reload()"
|
||||
>
|
||||
<el-icon :size="20" style="vertical-align: middle">
|
||||
<Refresh />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<el-button
|
||||
title="全屏"
|
||||
style="border: none; font-size: 20px"
|
||||
circle
|
||||
plain
|
||||
@click="toggle()"
|
||||
>
|
||||
<el-icon :size="14" style="vertical-align: middle">
|
||||
<full-screen />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<el-button
|
||||
:title="dark ? '夜间模式' : '明亮模式'"
|
||||
style="border: none; font-size: 20px"
|
||||
circle
|
||||
plain
|
||||
@click="toggleTheme()"
|
||||
>
|
||||
<el-icon :size="14" style="vertical-align: middle">
|
||||
<component :is="dark ? 'moon' : 'sunny'" />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-dropdown @command="handleCommand">
|
||||
<span class="ve_nav_dropdown">
|
||||
你好!{{ uname }}
|
||||
<el-icon>
|
||||
<arrow-down-bold />
|
||||
</el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item :command="{ name: 'Login' }">
|
||||
退出登录
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<!-- <router-link :to="{ name: 'Login' }">
|
||||
<el-link :underline="false">退出</el-link>
|
||||
</router-link> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useStore } from "vuex";
|
||||
import { useRouter } from "vue-router";
|
||||
import { inject, computed, ref } from "vue";
|
||||
import { useFullscreen } from "@vueuse/core";
|
||||
const { toggle } = useFullscreen();
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const uname = computed(() => store.getters.uname);
|
||||
const reload = inject("reload");
|
||||
const handleCommand = (command) => {
|
||||
router.push(command);
|
||||
};
|
||||
const dark = ref(false);
|
||||
const toggleTheme = () => {
|
||||
dark.value = !dark.value;
|
||||
document.documentElement.classList.toggle("dark");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ve_personal {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
.ve_nav_dropdown {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<el-sub-menu
|
||||
:index="menu.code + ''"
|
||||
v-if="menu.type == 0 && filerMenus(menu.children)"
|
||||
>
|
||||
<template #title>
|
||||
<el-icon :size="16" style="margin-right: 6px">
|
||||
<component :is="menu.icon" />
|
||||
</el-icon>
|
||||
<span class="el-menu-item-text">{{ menu.name }}</span>
|
||||
</template>
|
||||
<slide-menu
|
||||
v-for="child in menu.children"
|
||||
:key="child.code"
|
||||
:menu="child"
|
||||
></slide-menu>
|
||||
</el-sub-menu>
|
||||
<el-menu-item
|
||||
v-else-if="menu.type == 1"
|
||||
:index="setIndex(menu)"
|
||||
@click="clickMenu(menu)"
|
||||
>
|
||||
<template #title>
|
||||
<el-icon :size="16" style="margin-right: 6px">
|
||||
<component :is="menu.icon" />
|
||||
</el-icon>
|
||||
<span class="el-menu-item-text">{{ menu.name }}</span>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRouter } from "vue-router";
|
||||
import { defineProps, toRefs } from "vue";
|
||||
const props = defineProps(["menu"]);
|
||||
const { menu } = toRefs(props);
|
||||
|
||||
// const reload = inject("reload");
|
||||
const router = useRouter();
|
||||
const clickMenu = (menu) => {
|
||||
let name = menu.url.replace(/\//g, "-") + `-${menu.code}`;
|
||||
if (menu.iframe === 1) {
|
||||
name = `i-${menu.code}`;
|
||||
}
|
||||
router.push({
|
||||
name,
|
||||
});
|
||||
};
|
||||
|
||||
const setIndex = (menu) => {
|
||||
let index = `/${menu.url.replace(/\//g, "-")}-${menu.code}`;
|
||||
if (menu.iframe === 1) {
|
||||
index = `/i-${menu.code}`;
|
||||
}
|
||||
return index;
|
||||
};
|
||||
/**
|
||||
* @description:过滤空目录
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const filerMenus = (menus) => {
|
||||
if (menus && menus.length > 0) {
|
||||
let _menus = XE.toTreeArray(menus);
|
||||
return _menus.some((item) => item.type == 1);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
li.el-menu-item.is-active {
|
||||
background-color: darken($sideBgColor, 15%) !important;
|
||||
}
|
||||
.el-menu-item .el-icon svg {
|
||||
vertical-align: unset;
|
||||
}
|
||||
.el-menu-item {
|
||||
//border: 2px solid #ccc;
|
||||
//background: #eef4fe;
|
||||
}
|
||||
.el-sub-menu__title .el-icon svg {
|
||||
vertical-align: unset;
|
||||
}
|
||||
.el-menu-item-text {
|
||||
//color: #303133;
|
||||
}
|
||||
// .el-sub-menu.is-active:not(.is-opened) .el-sub-menu__title i {
|
||||
// color: $base-color;
|
||||
// }
|
||||
</style>
|
||||
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<div v-addClass class="ve_table">
|
||||
<!-- table工具条 -->
|
||||
<el-row v-delete class="ve_header_row_class_name ve_p_10">
|
||||
<slot name="tool_bar"></slot>
|
||||
</el-row>
|
||||
<div class="ve_table_page">
|
||||
<!-- 列表 -->
|
||||
<div class="ve_table_content" ref="tableBox">
|
||||
<el-row
|
||||
:gutter="20"
|
||||
style="margin-right: 15px; margin-left: -5px"
|
||||
type="flex"
|
||||
v-loading="loading"
|
||||
>
|
||||
<el-col
|
||||
v-for="(item, index) in $attrs.table"
|
||||
:key="index"
|
||||
:span="6"
|
||||
>
|
||||
<el-card
|
||||
class="box-card"
|
||||
shadow="always"
|
||||
:body-style="{ padding: '0px' }"
|
||||
@row-click="
|
||||
(row, column, event) =>
|
||||
(ve_rowIndex = rowClick(event))
|
||||
"
|
||||
:row-class-name="
|
||||
({ rowIndex }) =>
|
||||
rowClassName(rowIndex, ve_rowIndex)
|
||||
"
|
||||
:cell-class-name="
|
||||
({ rowIndex }) =>
|
||||
cellClassName(rowIndex, ve_rowIndex)
|
||||
"
|
||||
>
|
||||
<!-- 展示具体数据 -->
|
||||
</el-card>
|
||||
</el-col>
|
||||
<slot></slot>
|
||||
<template #append>
|
||||
<slot name="append"></slot>
|
||||
</template>
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据"></el-empty>
|
||||
</template>
|
||||
</el-row>
|
||||
<el-table
|
||||
ref="elTable"
|
||||
height="100%"
|
||||
stripe
|
||||
border
|
||||
highlight-current-row
|
||||
header-row-class-name="ve_header_row_class_name"
|
||||
header-cell-class-name="ve_header_cell_class_name"
|
||||
style="width: 100%"
|
||||
v-bind="$attrs.table"
|
||||
@selection-change="selectionChange"
|
||||
>
|
||||
<slot></slot>
|
||||
<template #append>
|
||||
<slot name="append"></slot>
|
||||
</template>
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据"></el-empty>
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- 分页 -->
|
||||
<el-pagination
|
||||
background
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:page-sizes="[
|
||||
10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000,
|
||||
]"
|
||||
:hide-on-single-page="false"
|
||||
v-bind="$attrs.pagination"
|
||||
>
|
||||
<slot name="pagination"></slot>
|
||||
</el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from "vue";
|
||||
|
||||
export default {
|
||||
name: "CardTable",
|
||||
inheritAttrs: false,
|
||||
directives: {
|
||||
delete: (el) => {
|
||||
const length = el.children.length;
|
||||
if (length <= 0) {
|
||||
el.parentNode && el.parentNode.removeChild(el);
|
||||
}
|
||||
},
|
||||
addClass: (el) => {
|
||||
el.parentNode && el.parentNode.classList.add("ve_flex_col");
|
||||
},
|
||||
},
|
||||
setup(props, context) {
|
||||
const { emit } = context;
|
||||
const elTable = ref(null);
|
||||
const ve_rowIndex = ref(null);
|
||||
|
||||
const tableBox = ref(null);
|
||||
/**
|
||||
* @description:行点击事件
|
||||
* @return {*}
|
||||
* @param event
|
||||
*/
|
||||
const rowClick = (event) => {
|
||||
// return event.currentTarget.rowIndex;
|
||||
return event;
|
||||
};
|
||||
/**
|
||||
* @description:高亮当前行
|
||||
* @return {*}
|
||||
* @param rowIndex
|
||||
* @param ve_rowIndex
|
||||
*/
|
||||
const rowClassName = (rowIndex, ve_rowIndex) => {
|
||||
if (rowIndex === ve_rowIndex) {
|
||||
return "ve_row_class_name";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description:高亮单元格
|
||||
* @return {*}
|
||||
* @param rowIndex
|
||||
* @param ve_rowIndex
|
||||
*/
|
||||
const cellClassName = (rowIndex, ve_rowIndex) => {
|
||||
if (rowIndex === ve_rowIndex) {
|
||||
return "ve_cell_class_name";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
const selectionChange = (val) => {
|
||||
// console.log(val);
|
||||
emit("selectionChange", val);
|
||||
};
|
||||
|
||||
return {
|
||||
elTable,
|
||||
tableBox,
|
||||
|
||||
ve_rowIndex,
|
||||
cellClassName,
|
||||
rowClassName,
|
||||
rowClick,
|
||||
selectionChange,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ve_table {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.ve_table_page {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.ve_table_content {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div v-addClass class="ve_table">
|
||||
<!-- table工具条 -->
|
||||
<el-row v-delete class="ve_header_row_class_name ve_p_10">
|
||||
<slot name="tool_bar"></slot>
|
||||
</el-row>
|
||||
<div class="ve_table_page">
|
||||
<!-- 列表 -->
|
||||
<div class="ve_table_content" ref="tableBox">
|
||||
<el-table
|
||||
ref="elTable"
|
||||
height="100%"
|
||||
stripe
|
||||
border
|
||||
highlight-current-row
|
||||
@row-click="
|
||||
(row, column, event) => (ve_rowIndex = rowClick(event))
|
||||
"
|
||||
:row-class-name="
|
||||
({ rowIndex }) => rowClassName(rowIndex, ve_rowIndex)
|
||||
"
|
||||
:cell-class-name="
|
||||
({ rowIndex }) => cellClassName(rowIndex, ve_rowIndex)
|
||||
"
|
||||
header-row-class-name="ve_header_row_class_name"
|
||||
header-cell-class-name="ve_header_cell_class_name"
|
||||
style="width: 100%"
|
||||
v-bind="$attrs.table"
|
||||
@selection-change="selectionChange"
|
||||
>
|
||||
<slot></slot>
|
||||
<template #append><slot name="append"></slot></template>
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据"></el-empty>
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- 分页 -->
|
||||
<el-pagination
|
||||
background
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:page-sizes="[
|
||||
10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000,
|
||||
]"
|
||||
:hide-on-single-page="false"
|
||||
v-bind="$attrs.pagination"
|
||||
>
|
||||
<slot name="pagination"></slot>
|
||||
</el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from "vue";
|
||||
export default {
|
||||
name: "VeTable",
|
||||
inheritAttrs: false,
|
||||
directives: {
|
||||
delete: (el) => {
|
||||
const length = el.children.length;
|
||||
if (length <= 0) {
|
||||
el.parentNode && el.parentNode.removeChild(el);
|
||||
}
|
||||
},
|
||||
addClass: (el) => {
|
||||
el.parentNode && el.parentNode.classList.add("ve_flex_col");
|
||||
},
|
||||
},
|
||||
setup(props, context) {
|
||||
const { emit } = context;
|
||||
const elTable = ref(null);
|
||||
const ve_rowIndex = ref(null);
|
||||
|
||||
const tableBox = ref(null);
|
||||
/**
|
||||
* @description:行点击事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const rowClick = (event) => {
|
||||
// return event.currentTarget.rowIndex;
|
||||
return event;
|
||||
};
|
||||
/**
|
||||
* @description:高亮当前行
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const rowClassName = (rowIndex, ve_rowIndex) => {
|
||||
if (rowIndex == ve_rowIndex) {
|
||||
return "ve_row_class_name";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description:高亮单元格
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const cellClassName = (rowIndex, ve_rowIndex) => {
|
||||
if (rowIndex == ve_rowIndex) {
|
||||
return "ve_cell_class_name";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
const selectionChange = (val) => {
|
||||
// console.log(val);
|
||||
emit("selectionChange", val);
|
||||
};
|
||||
|
||||
return {
|
||||
elTable,
|
||||
tableBox,
|
||||
|
||||
ve_rowIndex,
|
||||
cellClassName,
|
||||
rowClassName,
|
||||
rowClick,
|
||||
selectionChange,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ve_table {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.ve_table_page {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.ve_table_content {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,18 @@
|
||||
export default {
|
||||
install: (app) => {
|
||||
const files = require.context(
|
||||
"@/components/veBaseComponents",
|
||||
false,
|
||||
/\.vue$/,
|
||||
);
|
||||
files.keys().forEach((key) => {
|
||||
// 获取组件配置
|
||||
const componentConfig = files(key);
|
||||
// 全局注册组件
|
||||
app.component(
|
||||
componentConfig.default.name,
|
||||
componentConfig.default,
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
4
wu-lazy-cloud-network-ui/src/config.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
dev_mock: false, //开发环境启用mock true:启用
|
||||
pro_mock: false, //生产环境启用mock true:启用
|
||||
};
|
||||
12
wu-lazy-cloud-network-ui/src/directives/index.js
Normal file
@@ -0,0 +1,12 @@
|
||||
export default {
|
||||
install: (app, { router, store }) => {
|
||||
const files = require.context("@/directives/modules", false, /\.js$/);
|
||||
files.keys().forEach((key) => {
|
||||
let name = key.replace(/(\.\/|\.js)/g, "");
|
||||
let method = files(key).default;
|
||||
app.directive(name, (el, binding) =>
|
||||
method(el, binding, app, router, store),
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
const permission = (el, binding, app, router, store) => {
|
||||
const { value } = binding;
|
||||
function checkArray(permission) {
|
||||
let path = app.config.globalProperties.$route.name;
|
||||
|
||||
let _permission = permission.map((element) => {
|
||||
let url = path.replace(/-/g, "/") + "/" + element;
|
||||
return url;
|
||||
});
|
||||
let arr = store.getters.permissionList;
|
||||
return _permission.some((key) => arr.includes(key));
|
||||
}
|
||||
|
||||
if (value && value.length > 0) {
|
||||
let hasPermission = checkArray(value);
|
||||
if (!hasPermission) {
|
||||
// 没有权限 移除Dom元素
|
||||
el.parentNode && el.parentNode.removeChild(el);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default permission;
|
||||
14
wu-lazy-cloud-network-ui/src/directives/modules/resize.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { useElementSize, debouncedWatch } from "@vueuse/core";
|
||||
const resize = (el, binding) => {
|
||||
const { width } = useElementSize(el);
|
||||
if (width.value === 0) return;
|
||||
const { value } = binding;
|
||||
debouncedWatch(
|
||||
width,
|
||||
() => {
|
||||
value && value.resize();
|
||||
},
|
||||
{ debounce: 500 },
|
||||
);
|
||||
};
|
||||
export default resize;
|
||||
27
wu-lazy-cloud-network-ui/src/main.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import { createApp } from "vue";
|
||||
import axios from "@/plugins/axios";
|
||||
import App from "@/App.vue";
|
||||
import router from "@/router";
|
||||
import store from "@/store";
|
||||
import installElementPlus from "@/plugins/element";
|
||||
import elementIcon from "@/plugins/svgicon";
|
||||
import permission from "@/plugins/permission";
|
||||
import mock from "@/plugins/mock";
|
||||
import directives from "@/directives";
|
||||
import veBaseComponents from "@/components/veBaseComponents";
|
||||
// import JsonViewer from 'vue-json-viewer';
|
||||
|
||||
import "normalize.css/normalize.css";
|
||||
import "nprogress/nprogress.css";
|
||||
import "@/styles/common.scss";
|
||||
const app = createApp(App);
|
||||
app.use(mock)
|
||||
.use(elementIcon)
|
||||
.use(veBaseComponents)
|
||||
.use(store)
|
||||
.use(router)
|
||||
.use(installElementPlus)
|
||||
.use(axios, { router, store, opt: "VE_API" })
|
||||
.use(permission, { router, store })
|
||||
.use(directives, { router, store })
|
||||
.mount("#app");
|
||||
231
wu-lazy-cloud-network-ui/src/plugins/axios.js
Normal file
@@ -0,0 +1,231 @@
|
||||
/* eslint-disable indent */
|
||||
"use strict";
|
||||
|
||||
import axios from "axios";
|
||||
// import Qs from "qs";
|
||||
import NProgress from "nprogress";
|
||||
import { SET_TOKEN } from "@/store/modules/app/type";
|
||||
|
||||
// Full config: https://github.com/axios/axios#request-config
|
||||
// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
|
||||
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
|
||||
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
const install = (app, { router, store, opt }) => {
|
||||
let config = {
|
||||
Global: true,
|
||||
// baseURL: process.env.baseURL || process.env.apiUrl || ""
|
||||
// timeout: 60 * 1000, // Timeout
|
||||
// withCredentials: true, // Check cross-site Access-Control
|
||||
// {"userName":"Administrator","pwd":"123456"}
|
||||
// userName=Administrator&pwd=123456
|
||||
};
|
||||
// if (VE_ENV.MODE === "production") {
|
||||
// console.log("VE_ENV.MODE:" + VE_ENV.MODE);
|
||||
// config.transformRequest = [(data) => Qs.parse(data)];
|
||||
// }
|
||||
|
||||
const _axios = axios.create(config);
|
||||
let ve_loading;
|
||||
let ve_message = null;
|
||||
let loadingCount = 0;
|
||||
// 请求拦截
|
||||
_axios.interceptors.request.use(
|
||||
(config) => {
|
||||
NProgress.done();
|
||||
if (config.Global) {
|
||||
NProgress.start();
|
||||
ve_loading = app.config.globalProperties.$loading({
|
||||
lock: true,
|
||||
text: "Loading",
|
||||
spinner: "el-icon-loading",
|
||||
background: "rgba(0,0,0,0.1)",
|
||||
});
|
||||
}
|
||||
loadingCount++;
|
||||
//*请求头添加token
|
||||
const token = store.getters.token;
|
||||
const access_token = store.getters.access_token;
|
||||
const refresh_token = store.getters.refresh_token;
|
||||
const zone_id = store.getters.zone_id;
|
||||
// debugger;
|
||||
token && (config.headers.Authorization = token);
|
||||
|
||||
if (access_token) {
|
||||
config.headers.access_token = access_token;
|
||||
}
|
||||
|
||||
if (refresh_token) {
|
||||
config.headers.refresh_token = refresh_token;
|
||||
}
|
||||
if (zone_id) {
|
||||
config.headers.zone_id = zone_id;
|
||||
}
|
||||
// Do something before request is sent
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
// Do something with request error
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
// Add a response interceptor
|
||||
// 响应拦截
|
||||
_axios.interceptors.response.use(
|
||||
(response) => {
|
||||
// TODO 根据响应头更新token
|
||||
store.dispatch(`app/${SET_TOKEN}`, new Date().getTime());
|
||||
loadingCount--;
|
||||
if (loadingCount <= 0) {
|
||||
NProgress.done();
|
||||
ve_loading.close();
|
||||
}
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let contentType = response.headers["content-type"];
|
||||
if (
|
||||
"application/octet-stream" === contentType &&
|
||||
response.status === 200
|
||||
) {
|
||||
return response;
|
||||
}
|
||||
let type = "success";
|
||||
if (response.data.code !== 0) {
|
||||
type = "error";
|
||||
}
|
||||
if (ve_message) {
|
||||
ve_message.close();
|
||||
ve_message = null;
|
||||
}
|
||||
ve_message = app.config.globalProperties.$message({
|
||||
type,
|
||||
message: response.data.message,
|
||||
});
|
||||
// Do something with response data
|
||||
return response.data;
|
||||
},
|
||||
(error) => {
|
||||
loadingCount--;
|
||||
if (loadingCount <= 0) {
|
||||
NProgress.done();
|
||||
ve_loading.close();
|
||||
}
|
||||
if (error && error.response) {
|
||||
let message = "";
|
||||
switch (error.response.status) {
|
||||
case 400:
|
||||
message = "请求错误";
|
||||
break;
|
||||
case 401: {
|
||||
message = "未授权,请登录";
|
||||
router.replace({
|
||||
name: "Login",
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 403:
|
||||
message = "没有权限,拒绝访问";
|
||||
break;
|
||||
case 404:
|
||||
message = `请求地址出错`;
|
||||
break;
|
||||
case 408:
|
||||
message = "请求超时";
|
||||
break;
|
||||
case 500:
|
||||
message = "服务器内部错误";
|
||||
break;
|
||||
case 501:
|
||||
message = "服务未实现";
|
||||
break;
|
||||
case 502:
|
||||
message = "网关错误";
|
||||
break;
|
||||
case 503:
|
||||
message = "服务不可用";
|
||||
break;
|
||||
case 504:
|
||||
message = "网关超时";
|
||||
break;
|
||||
case 505:
|
||||
message = "HTTP版本不受支持";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ve_message) {
|
||||
ve_message.close();
|
||||
ve_message = null;
|
||||
}
|
||||
ve_message = app.config.globalProperties.$message({
|
||||
message,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
// Do something with response error
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* 字符串替换
|
||||
*
|
||||
*
|
||||
*
|
||||
var data = {
|
||||
name:"张三",
|
||||
age:23,
|
||||
sex:"男"
|
||||
}
|
||||
var text = "我叫{{name}},我今年{{age}}岁,我的性别是{{sex}}!".format(data);
|
||||
console.log(text);
|
||||
*
|
||||
*
|
||||
*
|
||||
* @returns {String}
|
||||
*/
|
||||
String.prototype.format = function () {
|
||||
if (arguments.length === 0) return this;
|
||||
var obj = arguments[0];
|
||||
var s = this;
|
||||
for (var key in obj) {
|
||||
s = s.replace(new RegExp("\\{\\{" + key + "\\}\\}", "g"), obj[key]);
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
const method = {
|
||||
post: (url, p, config) => _axios.post(url, p, config),
|
||||
put: (url, p, config) => _axios.put(url, p, config),
|
||||
getUrl: (url, p, config) =>
|
||||
_axios.get(url.format(p), { params: p, data: p }, config),
|
||||
get: (url, p, config) =>
|
||||
_axios.get(url, Object.assign(config, { params: p })),
|
||||
delete: (url, p, config) =>
|
||||
_axios.delete(url.format(p), { params: p, data: p }, config),
|
||||
deleteUrl: (url, p, config) =>
|
||||
_axios.delete(url.format(p), { params: p, data: p }, config),
|
||||
deleteBody: (url, p, config) => _axios.delete(url, { data: p }, config),
|
||||
// patch: (url, p, config) =>
|
||||
// _axios.patch(url, Object.assign(config, { params: p })),
|
||||
patch: (url, p, config) => _axios.patch(url, p, config),
|
||||
patchUrl: (url, p, config) =>
|
||||
_axios.patch(url.format(p), { params: p, data: p }, config),
|
||||
};
|
||||
|
||||
let api = {};
|
||||
const files = require.context("@/api/modules", false, /\.js$/);
|
||||
files.keys().forEach((key) => {
|
||||
const fileName = key.replace(/(\.\/|\.js)/g, "");
|
||||
api[fileName] = {};
|
||||
let obj = files(key);
|
||||
Object.keys(obj).forEach((item) => {
|
||||
api[fileName][item] = (p, config = {}) =>
|
||||
method[obj[item].type](obj[item].url, p, config);
|
||||
});
|
||||
});
|
||||
|
||||
window[opt] = api;
|
||||
app.config.globalProperties[opt] = api;
|
||||
};
|
||||
|
||||
export default { install };
|
||||
13
wu-lazy-cloud-network-ui/src/plugins/element.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import ElementPlus from "element-plus";
|
||||
import "element-plus/dist/index.css";
|
||||
// import zhCn from "element-plus/es/locale/lang/zh-cn";
|
||||
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
|
||||
import "dayjs/locale/zh-cn";
|
||||
export default {
|
||||
install: (app) => {
|
||||
app.use(ElementPlus, {
|
||||
locale: zhCn,
|
||||
size: "default",
|
||||
});
|
||||
},
|
||||
};
|
||||
20
wu-lazy-cloud-network-ui/src/plugins/mock.js
Normal file
@@ -0,0 +1,20 @@
|
||||
export default {
|
||||
install: () => {
|
||||
const config = require("@/config");
|
||||
if (config.pro_mock && VE_ENV.MODE === "production") {
|
||||
const Mock = require("mockjs"); //引入
|
||||
|
||||
const files = require.context("@/api/modules", false, /\.js$/);
|
||||
files.keys().forEach((key) => {
|
||||
let obj = files(key);
|
||||
Object.keys(obj).forEach((item) => {
|
||||
Mock.mock(
|
||||
obj[item].url,
|
||||
obj[item].type,
|
||||
obj[item].response,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
387
wu-lazy-cloud-network-ui/src/plugins/permission.js
Normal file
@@ -0,0 +1,387 @@
|
||||
import { SET_MENU_LIST, SET_PERMISSION_LIST } from "@/store/modules/app/type";
|
||||
|
||||
import globalRoutes from "@/router/globalRoutes";
|
||||
import mainRoutes from "@/router/mainRoutes";
|
||||
import NProgress from "nprogress";
|
||||
|
||||
/**
|
||||
* 判断当前路由类型, global: 全局路由, main: 主入口路由
|
||||
* @param {*} route 当前路由
|
||||
*/
|
||||
function fnCurrentRouteType(route, globalRoutes = []) {
|
||||
let temp = [];
|
||||
for (let i = 0; i < globalRoutes.length; i++) {
|
||||
if (route.name === globalRoutes[i].name) {
|
||||
return "global";
|
||||
} else if (
|
||||
globalRoutes[i].children &&
|
||||
globalRoutes[i].children.length >= 1
|
||||
) {
|
||||
temp = temp.concat(globalRoutes[i].children);
|
||||
}
|
||||
}
|
||||
return temp.length >= 1 ? fnCurrentRouteType(route, temp) : "main";
|
||||
}
|
||||
|
||||
export default {
|
||||
install: (app, { router, store }) => {
|
||||
// let router = opt;
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
const token = store.getters.token;
|
||||
if (
|
||||
router.options.isAddDynamicMenuRoutes ||
|
||||
fnCurrentRouteType(to, globalRoutes) === "global"
|
||||
) {
|
||||
//* 1. 已经添加 or 全局路由, 直接访问
|
||||
if (to.meta.title) {
|
||||
document.title = to.meta.title;
|
||||
}
|
||||
NProgress.start();
|
||||
next();
|
||||
} else {
|
||||
// let token = sessionStorage.getItem("token");
|
||||
if (!token || !/\S/.test(token)) {
|
||||
next({ name: "Login" });
|
||||
} else {
|
||||
let data = await VE_API.system.userMenuList();
|
||||
// let data = await VE_API.system.menuList();
|
||||
if (data && data.code === 0) {
|
||||
// const uname = store.getters.uname;
|
||||
// if ("admin" === uname && data.data.length === 0) {
|
||||
// data.data = data.data.concat(menuList);
|
||||
// }
|
||||
if (data.data.length === 0) {
|
||||
data.data = data.data.concat(menuList);
|
||||
}
|
||||
let _list = XE.clone(data.data, true);
|
||||
|
||||
data.data = XE.mapTree(
|
||||
XE.toArrayTree(_list, {
|
||||
sortKey: "sort",
|
||||
key: "code",
|
||||
parentKey: "parentCode",
|
||||
}),
|
||||
(item) => {
|
||||
if (
|
||||
item.children &&
|
||||
item.children.length <= 0
|
||||
) {
|
||||
delete item.children;
|
||||
}
|
||||
return item;
|
||||
},
|
||||
);
|
||||
await fnAddDynamicMenuRoutes(data.data);
|
||||
router.options.isAddDynamicMenuRoutes = true;
|
||||
await store.dispatch(`app/${SET_MENU_LIST}`, data.data);
|
||||
await store.dispatch(
|
||||
`app/${SET_PERMISSION_LIST}`,
|
||||
data.data,
|
||||
);
|
||||
NProgress.start();
|
||||
next({ ...to, replace: true });
|
||||
} else {
|
||||
next({ name: "Login" });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
router.afterEach(() => {
|
||||
NProgress.done();
|
||||
});
|
||||
|
||||
/**
|
||||
* 添加动态(菜单)路由
|
||||
* @param {*} menuList 菜单列表
|
||||
* @param {*} routes 递归创建的动态(菜单)路由
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const fnAddDynamicMenuRoutes = async (menuList = [], routes = []) => {
|
||||
let temp = [];
|
||||
for (let i = 0; i < menuList.length; i++) {
|
||||
if (
|
||||
menuList[i].type === 0 &&
|
||||
menuList[i].children &&
|
||||
menuList[i].children.length >= 1
|
||||
) {
|
||||
temp = temp.concat(menuList[i].children);
|
||||
} else if (menuList[i].type === 1) {
|
||||
// } else if (menuList[i].type==1 && /\S/.test(menuList[i].url)) {
|
||||
// const url = menuList[i].url.replace(/\//g, "_");
|
||||
let route = {
|
||||
path:
|
||||
menuList[i].url.replace(/\//g, "-") +
|
||||
`-${menuList[i].code}`,
|
||||
component: null,
|
||||
name:
|
||||
menuList[i].url.replace(/\//g, "-") +
|
||||
`-${menuList[i].code}`,
|
||||
// meta: {
|
||||
// }
|
||||
};
|
||||
// url以http[s]://开头, 通过iframe展示
|
||||
if (menuList[i].iframe === 1) {
|
||||
route["path"] = `i-${menuList[i].code}`;
|
||||
route["name"] = `i-${menuList[i].code}`;
|
||||
route["props"] = { url: menuList[i].url };
|
||||
route["component"] = () => import("@/views/IFrame.vue");
|
||||
} else {
|
||||
const l = "views/layoutpages/" + menuList[i].url;
|
||||
route["component"] = () => import("@/" + l + ".vue");
|
||||
}
|
||||
routes.push(route);
|
||||
}
|
||||
}
|
||||
if (temp.length >= 1) {
|
||||
fnAddDynamicMenuRoutes(temp, routes);
|
||||
} else {
|
||||
mainRoutes.children = mainRoutes.children.concat(routes);
|
||||
// mainRoutes.children = routes;
|
||||
console.log(
|
||||
"控制台打印--> ~ file: permission.js ~ line 127 ~ fnAddDynamicMenuRoutes ~ mainRoutes.children",
|
||||
mainRoutes.children,
|
||||
);
|
||||
|
||||
await router.addRoute(mainRoutes);
|
||||
await router.addRoute({
|
||||
path: "/:w+",
|
||||
redirect: { name: "404" },
|
||||
});
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 默认菜单
|
||||
* @type {[{name: string, icon: string, id: number, sort: number, iframe: number, menu: string, type: number, parentCode: number, url: string}, {name: string, icon: string, id: number, sort: number, iframe: number, menu: string, type: number, parentCode: number, url: string}, {name: string, icon: string, id: number, sort: number, iframe: number, menu: string, type: number, parentCode: number, url: string}, {name: string, icon: string, id: number, sort: number, iframe: number, menu: string, type: number, parentCode: number, url: string}, {name: string, icon: string, id: number, sort: number, iframe: number, menu: string, type: number, parentCode: number, url: string}, null, null, null, null, null, null, null, null, null, null, null, null, null]}
|
||||
*/
|
||||
const menuList = [
|
||||
{
|
||||
parentCode: -1,
|
||||
code: 100,
|
||||
id: 100,
|
||||
name: "系统设置", //看官网,这个名字是3-5之间的
|
||||
url: "",
|
||||
menu: "",
|
||||
type: 0,
|
||||
icon: "Setting",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 100,
|
||||
code: 1,
|
||||
id: 1,
|
||||
name: "用户管理", //看官网,这个名字是3-5之间的
|
||||
url: "system/Users", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "",
|
||||
type: 1,
|
||||
icon: "UserFilled",
|
||||
sort: 2,
|
||||
iframe: 0,
|
||||
},
|
||||
{
|
||||
parentCode: 1,
|
||||
code: 2,
|
||||
id: 2,
|
||||
name: "查询", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "search",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 1,
|
||||
code: 3,
|
||||
id: 3,
|
||||
name: "添加", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "add",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 1,
|
||||
code: 4,
|
||||
id: 4,
|
||||
name: "编辑", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "edit",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 100,
|
||||
code: 5,
|
||||
id: 5,
|
||||
name: "菜单管理", //看官网,这个名字是3-5之间的
|
||||
url: "system/Menus", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "",
|
||||
type: 1,
|
||||
icon: "Menu",
|
||||
sort: 1,
|
||||
iframe: 0,
|
||||
},
|
||||
{
|
||||
parentCode: 5,
|
||||
code: "restore",
|
||||
id: 51,
|
||||
name: "恢复出厂设置", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "restore",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 5,
|
||||
code: 6,
|
||||
id: 6,
|
||||
name: "查询", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "search",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 5,
|
||||
code: 7,
|
||||
id: 7,
|
||||
name: "添加", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "add",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 5,
|
||||
code: 8,
|
||||
id: 8,
|
||||
name: "编辑", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "edit",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 5,
|
||||
code: 9,
|
||||
id: 9,
|
||||
name: "添加子级", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "addChild",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 5,
|
||||
code: 10,
|
||||
id: 10,
|
||||
name: "添加按钮", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "addBtn",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 100,
|
||||
code: 11,
|
||||
id: 11,
|
||||
name: "角色管理", //看官网,这个名字是3-5之间的
|
||||
url: "system/Roles", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "",
|
||||
type: 1,
|
||||
icon: "HelpFilled",
|
||||
sort: 3,
|
||||
iframe: 0,
|
||||
},
|
||||
{
|
||||
parentCode: 11,
|
||||
code: 12,
|
||||
id: 12,
|
||||
name: "查询", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "search",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 11,
|
||||
code: 13,
|
||||
id: 13,
|
||||
name: "添加", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "add",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 11,
|
||||
code: 14,
|
||||
id: 14,
|
||||
name: "编辑", //看官网,这个名字是3-5之间的
|
||||
url: "", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "edit",
|
||||
type: 2,
|
||||
icon: "",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: -1,
|
||||
code: 15,
|
||||
id: 15,
|
||||
name: "参考资料", //看官网,这个名字是3-5之间的
|
||||
url: "",
|
||||
menu: "",
|
||||
type: 0,
|
||||
icon: "DocumentCopy",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 15,
|
||||
code: 16,
|
||||
id: 16,
|
||||
name: "vue3.0", //看官网,这个名字是3-5之间的
|
||||
url: "https://www.vue3js.cn/docs/zh/", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "",
|
||||
type: 1,
|
||||
icon: "Promotion",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
{
|
||||
parentCode: 15,
|
||||
code: 17,
|
||||
id: 17,
|
||||
name: "element-plus", //看官网,这个名字是3-5之间的
|
||||
url: "https://element-plus.org/#/zh-CN", //这个类似上面的id一个,只是初始值是从100开始的
|
||||
menu: "",
|
||||
type: 1,
|
||||
icon: "ElemeFilled",
|
||||
sort: 1,
|
||||
iframe: 1,
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
9
wu-lazy-cloud-network-ui/src/plugins/svgicon.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import * as components from "@element-plus/icons-vue";
|
||||
export default {
|
||||
install: (app) => {
|
||||
for (const key in components) {
|
||||
const componentConfig = components[key];
|
||||
app.component(componentConfig.name, componentConfig);
|
||||
}
|
||||
},
|
||||
};
|
||||
17
wu-lazy-cloud-network-ui/src/router/globalRoutes.js
Normal file
@@ -0,0 +1,17 @@
|
||||
export default [
|
||||
{
|
||||
path: "/login",
|
||||
name: "Login",
|
||||
component: () => import("@/views/Login.vue"),
|
||||
},
|
||||
{
|
||||
path: "/register",
|
||||
name: "Register",
|
||||
component: () => import("@/views/Register.vue"),
|
||||
},
|
||||
{
|
||||
path: "/404",
|
||||
name: "404",
|
||||
component: () => import("@/views/404.vue"),
|
||||
},
|
||||
];
|
||||
11
wu-lazy-cloud-network-ui/src/router/index.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { createRouter, createWebHashHistory } from "vue-router";
|
||||
import globalRoutes from "./globalRoutes";
|
||||
import mainRoutes from "./mainRoutes";
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
scrollBehavior: () => ({ y: 0 }),
|
||||
isAddDynamicMenuRoutes: false, // 是否已经添加动态(菜单)路由
|
||||
routes: globalRoutes.concat(mainRoutes),
|
||||
});
|
||||
export default router;
|
||||
13
wu-lazy-cloud-network-ui/src/router/mainRoutes.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export default {
|
||||
path: "/",
|
||||
name: "AppMain",
|
||||
component: () => import("@/views/AppMain.vue"),
|
||||
redirect: { name: "Home" },
|
||||
children: [
|
||||
{
|
||||
path: "home",
|
||||
name: "Home",
|
||||
component: () => import("@/views/Home.vue"),
|
||||
},
|
||||
],
|
||||
};
|
||||
BIN
wu-lazy-cloud-network-ui/src/static/add.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
wu-lazy-cloud-network-ui/src/static/database.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
wu-lazy-cloud-network-ui/src/static/file.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
wu-lazy-cloud-network-ui/src/static/folder.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
wu-lazy-cloud-network-ui/src/static/key.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
wu-lazy-cloud-network-ui/src/static/music-default-pic.png
Normal file
|
After Width: | Height: | Size: 992 KiB |
BIN
wu-lazy-cloud-network-ui/src/static/redis.png
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
10
wu-lazy-cloud-network-ui/src/store/getters.js
Normal file
@@ -0,0 +1,10 @@
|
||||
export default {
|
||||
opened: (state) => state.app.slider.opened,
|
||||
token: (state) => state.app.token,
|
||||
access_token: (state) => state.app.access_token,
|
||||
refresh_token: (state) => state.app.refresh_token,
|
||||
zone_id: (state) => state.app.zone_id,
|
||||
uname: (state) => state.app.uname,
|
||||
menuList: (state) => state.app.menuList,
|
||||
permissionList: (state) => state.app.permissionList,
|
||||
};
|
||||
13
wu-lazy-cloud-network-ui/src/store/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
let modules = {};
|
||||
const files = require.context("./modules", true, /index.js$/);
|
||||
files.keys().forEach((key) => {
|
||||
const fileName = key.split("/")[1];
|
||||
modules[fileName] = files(key).default;
|
||||
});
|
||||
|
||||
import { createStore } from "vuex";
|
||||
import getters from "./getters";
|
||||
export default createStore({
|
||||
getters,
|
||||
modules,
|
||||
});
|
||||
101
wu-lazy-cloud-network-ui/src/store/modules/app/index.js
Normal file
@@ -0,0 +1,101 @@
|
||||
import {
|
||||
TOGGLE_SLIDER,
|
||||
SET_TOKEN,
|
||||
SET_UNAME,
|
||||
SET_MENU_LIST,
|
||||
SET_PERMISSION_LIST,
|
||||
SET_REFRESH_TOKEN,
|
||||
SET_ACCESS_TOKEN,
|
||||
SET_ZONE_ID,
|
||||
} from "./type.js";
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
slider: {
|
||||
opened: JSON.parse(sessionStorage.getItem("opened")),
|
||||
},
|
||||
token: sessionStorage.getItem("token") || "",
|
||||
access_token: sessionStorage.getItem("access_token") || "",
|
||||
refresh_token: sessionStorage.getItem("refresh_token") || "",
|
||||
zone_id: sessionStorage.getItem("zone_id") || "",
|
||||
menuList: null,
|
||||
permissionList: [],
|
||||
uname: sessionStorage.getItem("uname") || "",
|
||||
},
|
||||
mutations: {
|
||||
[TOGGLE_SLIDER](state) {
|
||||
state.slider.opened = !state.slider.opened;
|
||||
sessionStorage.setItem(
|
||||
"opened",
|
||||
JSON.stringify(state.slider.opened),
|
||||
);
|
||||
},
|
||||
[SET_TOKEN](state, token) {
|
||||
state.token = token;
|
||||
sessionStorage.setItem("token", state.token);
|
||||
},
|
||||
[SET_UNAME](state, uname) {
|
||||
state.uname = uname;
|
||||
sessionStorage.setItem("uname", state.uname);
|
||||
},
|
||||
[SET_ACCESS_TOKEN](state, access_token) {
|
||||
state.access_token = access_token;
|
||||
sessionStorage.setItem("access_token", state.access_token);
|
||||
},
|
||||
[SET_REFRESH_TOKEN](state, refresh_token) {
|
||||
state.refresh_token = refresh_token;
|
||||
sessionStorage.setItem("refresh_token", state.refresh_token);
|
||||
},
|
||||
[SET_ZONE_ID](state, zone_id) {
|
||||
state.zone_id = zone_id;
|
||||
sessionStorage.setItem("zone_id", state.zone_id);
|
||||
},
|
||||
[SET_MENU_LIST](state, menuList) {
|
||||
state.menuList = menuList;
|
||||
},
|
||||
[SET_PERMISSION_LIST](state, permissionList) {
|
||||
state.permissionList = permissionList;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
[TOGGLE_SLIDER]({ commit }) {
|
||||
commit(TOGGLE_SLIDER);
|
||||
},
|
||||
[SET_TOKEN]({ commit }, token) {
|
||||
commit(SET_TOKEN, token);
|
||||
},
|
||||
[SET_ACCESS_TOKEN]({ commit }, access_token) {
|
||||
commit(SET_ACCESS_TOKEN, access_token);
|
||||
},
|
||||
[SET_REFRESH_TOKEN]({ commit }, refresh_token) {
|
||||
commit(SET_REFRESH_TOKEN, refresh_token);
|
||||
},
|
||||
[SET_ZONE_ID]({ commit }, zone_id) {
|
||||
commit(SET_ZONE_ID, zone_id);
|
||||
},
|
||||
[SET_UNAME]({ commit }, uname) {
|
||||
commit(SET_UNAME, uname);
|
||||
},
|
||||
[SET_MENU_LIST]({ commit }, menuList) {
|
||||
commit(SET_MENU_LIST, menuList);
|
||||
},
|
||||
[SET_PERMISSION_LIST]({ commit }, menuList) {
|
||||
let allMenus = XE.filterTree(menuList, (item) => item.type === 1, {
|
||||
sortKey: "sort",
|
||||
key: "code",
|
||||
parentKey: "parentCode",
|
||||
});
|
||||
let permissionList = [];
|
||||
allMenus.forEach((item) => {
|
||||
if (item.children && item.children.length > 0) {
|
||||
item.children.forEach((menu) => {
|
||||
permissionList.push(
|
||||
`${item.url}/${item.code}/${menu.menu}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
commit(SET_PERMISSION_LIST, permissionList);
|
||||
},
|
||||
},
|
||||
};
|
||||
8
wu-lazy-cloud-network-ui/src/store/modules/app/type.js
Normal file
@@ -0,0 +1,8 @@
|
||||
export const TOGGLE_SLIDER = "TOGGLE_SLIDER";
|
||||
export const SET_TOKEN = "SET_TOKEN";
|
||||
export const SET_ACCESS_TOKEN = "access_token";
|
||||
export const SET_REFRESH_TOKEN = "refresh_token";
|
||||
export const SET_UNAME = "SET_UNAME";
|
||||
export const SET_ZONE_ID = "ZONE_ID"; // 空间区域ID
|
||||
export const SET_MENU_LIST = "SET_MENU_LIST";
|
||||
export const SET_PERMISSION_LIST = "SET_PERMISSION_LIST";
|
||||
65
wu-lazy-cloud-network-ui/src/styles/common.scss
Normal file
@@ -0,0 +1,65 @@
|
||||
html {
|
||||
background: #fff;
|
||||
transition: color 300ms, background-color 300ms;
|
||||
&.dark {
|
||||
filter: contrast(100%) invert(100%);
|
||||
img {
|
||||
filter: hue-rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
.ve_header_row_class_name,
|
||||
.el-table__fixed-right-patch {
|
||||
background: $main-bg-color !important;
|
||||
}
|
||||
.ve_header_cell_class_name {
|
||||
background: $main-bg-color !important;
|
||||
}
|
||||
.ve_cell_class_name {
|
||||
background: $base-color !important;
|
||||
border-color: $base-color !important;
|
||||
}
|
||||
.ve_row_class_name {
|
||||
background: $base-color !important;
|
||||
}
|
||||
.ve_p_10 {
|
||||
padding: 10px;
|
||||
}
|
||||
//滚动条的宽度
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
//滚动条的滑块
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(144, 147, 153, 0.3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
.ve_select_option_slot {
|
||||
font-size: 12px;
|
||||
float: left;
|
||||
line-height: initial;
|
||||
padding-bottom: 10px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.ve_option_box {
|
||||
width: calc(50% - 132px);
|
||||
}
|
||||
.size-watch {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
visibility: hidden;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.ve_flex_col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - #{$nav-height} - 80px);
|
||||
}
|
||||
11
wu-lazy-cloud-network-ui/src/styles/variables.scss.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const variables = {
|
||||
main_bg_color: "#f5f5f5",
|
||||
base_color: "#409EFF",
|
||||
nav_height: "50px",
|
||||
side_close_width: "65px",
|
||||
side_open_width: "160px",
|
||||
sideBgColor: "#545c64",
|
||||
sideTextColor: "#fff",
|
||||
sideActiveTextColor: "#ffd04b",
|
||||
};
|
||||
module.exports = variables;
|
||||
106
wu-lazy-cloud-network-ui/src/utils/index.js
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @description:树形结构转一维数组
|
||||
* @param {*} nodes
|
||||
* @return {*}
|
||||
*/
|
||||
export function jsonToArray(nodes) {
|
||||
let pid = -1;
|
||||
const toArray = (nodes) => {
|
||||
let r = [];
|
||||
if (Array.isArray(nodes)) {
|
||||
for (let i = 0, l = nodes.length; i < l; i++) {
|
||||
nodes[i].pid = pid;
|
||||
r.push(nodes[i]); // 取每项数据放入一个新数组
|
||||
if (
|
||||
Array.isArray(nodes[i]["children"]) &&
|
||||
nodes[i]["children"].length > 0
|
||||
) {
|
||||
// 若存在children则递归调用,把数据拼接到新数组中,并且删除该children
|
||||
pid = nodes[i].id;
|
||||
r = r.concat(toArray(nodes[i]["children"]));
|
||||
delete nodes[i]["children"];
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
};
|
||||
return toArray(nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description:一维数组转树形结构
|
||||
* @param {*} treeArray
|
||||
* @return {*}
|
||||
*/
|
||||
export function arrayToJson(treeArray) {
|
||||
var r = [];
|
||||
var tmpMap = {};
|
||||
for (var i = 0, l = treeArray.length; i < l; i++) {
|
||||
//* 以每条数据的id作为obj的key值,数据作为value值存入到一个临时对象里面
|
||||
tmpMap[treeArray[i]["id"]] = treeArray[i];
|
||||
}
|
||||
for (i = 0, l = treeArray.length; i < l; i++) {
|
||||
var key = tmpMap[treeArray[i]["pid"]];
|
||||
//*循环每一条数据的pid,假如这个临时对象有这个key值,就代表这个key对应的数据有children,需要Push进去
|
||||
//*如果这一项数据属于哪个数据的子级
|
||||
if (key) {
|
||||
// *如果这个数据没有children
|
||||
if (!key["children"]) {
|
||||
key["children"] = [];
|
||||
key["children"].push(treeArray[i]);
|
||||
//* 如果这个数据有children
|
||||
} else {
|
||||
key["children"].push(treeArray[i]);
|
||||
}
|
||||
} else {
|
||||
//*如果没有这个Key值,就代表找不到属于哪个数据,那就代表没有父级,直接放在最外层
|
||||
r.push(treeArray[i]);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取节点的所有父节点
|
||||
* @param {*} tree
|
||||
* @param {*} func
|
||||
* @param {*} path
|
||||
* @return {*}
|
||||
*/
|
||||
export const treeFindPath = (tree, func, name = "id", path = []) => {
|
||||
if (!tree) return [];
|
||||
for (const data of tree) {
|
||||
//* 这里按照你的需求来存放最后返回的内容吧
|
||||
path.push(data[name]);
|
||||
if (func(data)) return path;
|
||||
if (data.children) {
|
||||
const findChildren = treeFindPath(data.children, func, name, path);
|
||||
if (findChildren.length) return findChildren;
|
||||
}
|
||||
path.pop();
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: 拆箱函数,解决tooltip显示问题
|
||||
* @param {*} obj
|
||||
* @return {*}
|
||||
*/
|
||||
export const unwarp = (obj) => obj && (obj.__v_raw || obj.valueOf() || obj);
|
||||
|
||||
/**
|
||||
* @description:获取所有的el-svg-icon组件名
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
export const icons = () => {
|
||||
const components = require("@element-plus/icons-vue");
|
||||
console.log("🚀 ~ file: index.js ~ line 107 ~ icons ~ e", components);
|
||||
|
||||
const names = [];
|
||||
for (const key in components) {
|
||||
names.push(components[key].name);
|
||||
}
|
||||
return names;
|
||||
};
|
||||
57
wu-lazy-cloud-network-ui/src/utils/validate.js
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 邮箱
|
||||
* @param {* s
|
||||
*/
|
||||
export const isEmail = (s) =>
|
||||
/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3){1,2)$/.test(s);
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
* @param {* s
|
||||
*/
|
||||
export const isMobile = (s) => /^1[3-8][0-9]{9$/.test(s);
|
||||
|
||||
/**
|
||||
* 电话号码
|
||||
* @param {* s
|
||||
*/
|
||||
export const isPhone = (s) => /^([0-9]{3,4-)?[0-9]{7,8$/.test(s);
|
||||
|
||||
/**
|
||||
* URL地址
|
||||
* @param {* s
|
||||
*/
|
||||
export const isURL = (s) => /^http[s]?:\/\/.*/.test(s);
|
||||
|
||||
/**
|
||||
* ip地址
|
||||
* @param {* s
|
||||
*/
|
||||
export const isIP = (s) =>
|
||||
/^(25[0-5]|2[0-4]\d|[0-1]\d{2|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2|[1-9]?\d)$/.test(
|
||||
s,
|
||||
);
|
||||
|
||||
/**
|
||||
* 字符串
|
||||
* @param {* s
|
||||
*/
|
||||
export const isString = (s) => /^[A-Za-z0-9_\-\u4e00-\u9fa5]+$/.test(s);
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @param {type
|
||||
* @: exp
|
||||
* 非负浮点数字
|
||||
*/
|
||||
export const isNumber = (s) => /^\d+(\.\d+)?$/.test(s);
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @param {type
|
||||
* @:
|
||||
* 银行卡正则
|
||||
*/
|
||||
|
||||
export const isBank = (s) =>
|
||||
/^([1-9]{1)(\d{11|\d{15|\d{16|\d{17|\d{18)$/.test(s);
|
||||
9
wu-lazy-cloud-network-ui/src/views/404.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<common></common>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Common from "@/components/Common";
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
50
wu-lazy-cloud-network-ui/src/views/AppMain.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<el-container>
|
||||
<el-aside width="auto"><side-bar></side-bar></el-aside>
|
||||
<el-container>
|
||||
<el-header :height="nav_height">
|
||||
<navigate-bar></navigate-bar>
|
||||
</el-header>
|
||||
<el-main>
|
||||
<el-scrollbar
|
||||
style="
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
"
|
||||
>
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="el-zoom-in-top" mode="out-in">
|
||||
<component :key="routerAlive" :is="Component" />
|
||||
</transition>
|
||||
</router-view>
|
||||
</el-scrollbar>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</template>
|
||||
<script setup>
|
||||
import { nav_height } from "@/styles/variables.scss.js";
|
||||
import NavigateBar from "@/components/layout/NavigateBar.vue";
|
||||
import SideBar from "@/components/layout/SideBar.vue";
|
||||
import { provide, ref, watchEffect } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
const routerAlive = ref(null);
|
||||
watchEffect(() => {
|
||||
routerAlive.value = route.name;
|
||||
});
|
||||
provide("reload", () => {
|
||||
routerAlive.value = Math.random() + "_" + Math.random();
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.el-main {
|
||||
height: calc(100vh - v-bind(nav_height));
|
||||
background: $main-bg-color;
|
||||
:deep(.el-scrollbar__bar.is-horizontal) {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
37
wu-lazy-cloud-network-ui/src/views/Home.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div class="ve_home">
|
||||
<el-row>
|
||||
<el-col :span="16"><dashboard /></el-col>
|
||||
<el-col :span="8">
|
||||
<el-calendar class="ve_calendar"></el-calendar>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<live-chart />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import dashboard from "@/components/dashboard/Shortcuts";
|
||||
import LiveChart from "@/components/dashboard/LiveChart";
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ve_calendar {
|
||||
background: #f56c6c;
|
||||
border-radius: 10px;
|
||||
&:hover {
|
||||
box-shadow: 3px 3px 6px 1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
:deep(.el-calendar__body) {
|
||||
padding-bottom: 12px !important;
|
||||
.el-calendar-day {
|
||||
height: auto !important;
|
||||
}
|
||||
.el-calendar-table td {
|
||||
border: none;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
42
wu-lazy-cloud-network-ui/src/views/IFrame.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div
|
||||
v-loading="load"
|
||||
element-loading-text="拼命加载中"
|
||||
element-loading-spinner="el-icon-loading"
|
||||
>
|
||||
<iframe ref="iframe" :src="props.url" frameborder="0"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, onMounted, ref } from "vue";
|
||||
import { nav_height } from "@/styles/variables.scss.js";
|
||||
|
||||
const props = defineProps({
|
||||
url: { type: String },
|
||||
});
|
||||
const load = ref(true);
|
||||
const iframe = ref(null);
|
||||
|
||||
const setLoad = () => {
|
||||
const $onLoad = () => {
|
||||
load.value = false;
|
||||
};
|
||||
if (iframe.value.attachEvent) {
|
||||
iframe.value.attachEvent("onload", $onLoad);
|
||||
} else {
|
||||
iframe.value.onload = $onLoad;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
setLoad();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
iframe {
|
||||
width: 100%;
|
||||
height: calc(100vh - v-bind(nav_height) - 83px);
|
||||
}
|
||||
</style>
|
||||
148
wu-lazy-cloud-network-ui/src/views/Login.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<common>
|
||||
<div class="ve_container">
|
||||
<el-card :body-style="{ background: 'rgba(0,0,0,0.15)' }">
|
||||
<router-link style="float: right" :to="{ path: 'register' }"
|
||||
>注册</router-link
|
||||
>
|
||||
<h1>Lazy-UI</h1>
|
||||
<transition name="el-fade-in-linear">
|
||||
<el-form
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
v-show="!success"
|
||||
class="ve_form"
|
||||
ref="ref_form"
|
||||
:inline="false"
|
||||
@keyup.enter="onSubmit"
|
||||
>
|
||||
<el-form-item prop="username">
|
||||
<el-input
|
||||
v-model.trim="username"
|
||||
placeholder="用户名"
|
||||
>
|
||||
<template #prepend>
|
||||
<el-icon :size="20"><Avatar /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
v-model.trim="password"
|
||||
show-password
|
||||
placeholder="密码"
|
||||
>
|
||||
<template #prepend>
|
||||
<el-icon :size="20"><Key /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
class="ve_submit"
|
||||
type="primary"
|
||||
@click="onSubmit"
|
||||
>
|
||||
登录
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</transition>
|
||||
</el-card>
|
||||
</div>
|
||||
</common>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
SET_ACCESS_TOKEN,
|
||||
SET_REFRESH_TOKEN,
|
||||
SET_TOKEN,
|
||||
SET_UNAME,
|
||||
SET_ZONE_ID,
|
||||
} from "@/store/modules/app/type";
|
||||
import Common from "@/components/Common";
|
||||
import { ref, reactive, toRefs } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { useRouter } from "vue-router";
|
||||
const rules = {
|
||||
username: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
||||
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
||||
};
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const form = reactive({
|
||||
username: "",
|
||||
password: "",
|
||||
});
|
||||
const { username, password } = toRefs(form);
|
||||
const ref_form = ref(null);
|
||||
const success = ref(false);
|
||||
sessionStorage.clear();
|
||||
store.dispatch(`app/${SET_TOKEN}`, "");
|
||||
router.options.isAddDynamicMenuRoutes = false;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
ref_form.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
const data = await VE_API.system.login(form);
|
||||
if (data.code === 0) {
|
||||
await store.dispatch(`app/${SET_TOKEN}`, data.data);
|
||||
await store.dispatch(
|
||||
`app/${SET_ACCESS_TOKEN}`,
|
||||
data.data.accessToken,
|
||||
);
|
||||
await store.dispatch(
|
||||
`app/${SET_REFRESH_TOKEN}`,
|
||||
data.data.refreshToken,
|
||||
);
|
||||
await store.dispatch(`app/${SET_UNAME}`, form.username);
|
||||
// 获取用户信息
|
||||
const userResult = await VE_API.system.resolvingUser({
|
||||
accessToken: data.data.accessToken,
|
||||
});
|
||||
|
||||
console.log(userResult);
|
||||
if (userResult && userResult.id) {
|
||||
await store.dispatch(`app/${SET_ZONE_ID}`, userResult.id);
|
||||
}
|
||||
success.value = true;
|
||||
router.push({ name: "AppMain" });
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ve_container {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 400px;
|
||||
top: 50%;
|
||||
left: 100px;
|
||||
transform: translateY(-50%);
|
||||
transition: all 1s;
|
||||
min-height: 273px;
|
||||
text-align: center;
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
transition: all 1s;
|
||||
font-weight: bold;
|
||||
margin-bottom: 36px;
|
||||
}
|
||||
.ve_form {
|
||||
.ve_submit {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.el-input-group__prepend) {
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
144
wu-lazy-cloud-network-ui/src/views/Register.vue
Normal file
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<common>
|
||||
<div class="ve_container">
|
||||
<el-card :body-style="{ background: 'rgba(0,0,0,0.15)' }">
|
||||
<router-link style="float: right" :to="{ path: 'login' }"
|
||||
>登录</router-link
|
||||
>
|
||||
<h1>Lazy-UI</h1>
|
||||
<transition name="el-fade-in-linear">
|
||||
<el-form
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
v-show="!success"
|
||||
class="ve_form"
|
||||
ref="ref_form"
|
||||
:inline="false"
|
||||
@keyup.enter="onSubmit"
|
||||
>
|
||||
<el-form-item prop="username" label="注册账号">
|
||||
<el-input
|
||||
v-model.trim="username"
|
||||
placeholder="注册账号"
|
||||
>
|
||||
<template #prepend>
|
||||
<el-icon :size="20"><Avatar /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password" label="账号密码">
|
||||
<el-input
|
||||
v-model.trim="password"
|
||||
show-password
|
||||
placeholder="账号密码"
|
||||
>
|
||||
<template #prepend>
|
||||
<el-icon :size="20"><Key /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="checkPassword" label="密码确认">
|
||||
<el-input
|
||||
v-model.trim="checkPassword"
|
||||
show-password
|
||||
placeholder="密码确认"
|
||||
>
|
||||
<template #prepend>
|
||||
<el-icon :size="20"><Key /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
class="ve_submit"
|
||||
type="primary"
|
||||
@click="onSubmit"
|
||||
>
|
||||
注册
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</transition>
|
||||
</el-card>
|
||||
</div>
|
||||
</common>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { SET_TOKEN, SET_UNAME } from "@/store/modules/app/type";
|
||||
import Common from "@/components/Common";
|
||||
import { ref, reactive, toRefs, getCurrentInstance } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { useRouter } from "vue-router";
|
||||
const rules = {
|
||||
username: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
||||
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
||||
checkPassword: [{ required: true, message: "密码确认", trigger: "blur" }],
|
||||
};
|
||||
const { proxy } = getCurrentInstance();
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const form = reactive({
|
||||
username: "",
|
||||
password: "",
|
||||
checkPassword: "",
|
||||
});
|
||||
const { username, password, checkPassword } = toRefs(form);
|
||||
const ref_form = ref(null);
|
||||
const success = ref(false);
|
||||
sessionStorage.clear();
|
||||
store.dispatch(`app/${SET_TOKEN}`, "");
|
||||
router.options.isAddDynamicMenuRoutes = false;
|
||||
|
||||
const onSubmit = () => {
|
||||
// 验证两个密码是否一样
|
||||
if (form.password === form.checkPassword) {
|
||||
ref_form.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
const data = await VE_API.system.register(form);
|
||||
if (data.code === 0) {
|
||||
store.dispatch(`app/${SET_TOKEN}`, data.data);
|
||||
store.dispatch(`app/${SET_UNAME}`, form.username);
|
||||
success.value = true;
|
||||
router.push({ name: "AppMain" });
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
proxy.$message({
|
||||
type: "error",
|
||||
message: "请确认,两次输入密码是否一致!",
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ve_container {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 400px;
|
||||
top: 50%;
|
||||
left: 100px;
|
||||
transform: translateY(-50%);
|
||||
transition: all 1s;
|
||||
min-height: 273px;
|
||||
text-align: center;
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
transition: all 1s;
|
||||
font-weight: bold;
|
||||
margin-bottom: 36px;
|
||||
}
|
||||
.ve_form {
|
||||
.ve_submit {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.el-input-group__prepend) {
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,8 @@
|
||||
const acwMenu = {
|
||||
description: "数据库管理平台",
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "DataLine",
|
||||
name: "数据库管理平台",
|
||||
};
|
||||
export default acwMenu;
|
||||
@@ -0,0 +1,241 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select
|
||||
v-model="instanceId"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
@change="(val) => getSchemaList(val)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="数据库库名" prop="schemaName">
|
||||
<el-select
|
||||
v-model="schema"
|
||||
filterable
|
||||
placeholder="数据库实例"
|
||||
@change="findInstanceSchemaColumnList"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="文件数据" prop="data">
|
||||
<el-upload
|
||||
name="data"
|
||||
:multiple="false"
|
||||
:show-file-list="true"
|
||||
:on-change="onChange"
|
||||
limit="1"
|
||||
v-model="data"
|
||||
placeholder=""
|
||||
clearable
|
||||
:auto-upload="false"
|
||||
>
|
||||
<!-- <el-button size="medium" type="primary">上传文件</el-button>-->
|
||||
<div style="padding: 10px 0">
|
||||
<Icon
|
||||
type="ios-cloud-upload"
|
||||
size="52"
|
||||
style="#3399ff"
|
||||
></Icon>
|
||||
<p style="margin-top: 10px; font-size: 14px">
|
||||
点击或拖拽文件至此即可上传文件
|
||||
</p>
|
||||
<p
|
||||
style="
|
||||
margin-top: 20px;
|
||||
font-size: 14px;
|
||||
color: red;
|
||||
"
|
||||
>
|
||||
请上传10GB以内的待测对象
|
||||
</p>
|
||||
</div>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<span>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库信息导入",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
add: { name: "添加" },
|
||||
edit: { name: "编辑" },
|
||||
del: { name: "删除" },
|
||||
analysisSchema: { name: "解析schema" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "MagicStick",
|
||||
name: "数据库信息导入",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
<script setup>
|
||||
import { reactive, toRefs, onMounted, ref } from "vue";
|
||||
|
||||
const rules = {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入文件名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
|
||||
data: [
|
||||
{
|
||||
required: true,
|
||||
message: "请上传文件",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
type: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择文件类型",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
schema: "",
|
||||
instanceId: "",
|
||||
data: [],
|
||||
});
|
||||
const { schema, instanceId, data } = toRefs(form);
|
||||
const serverList = ref(null);
|
||||
const schemaList = ref(null);
|
||||
|
||||
/**
|
||||
* 获取数据库实例
|
||||
*/
|
||||
const getInstanceList = () => {
|
||||
// 查询数据库实例
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
const getSchemaList = (databaseInstance = null) => {
|
||||
console.log(databaseInstance);
|
||||
// 查询数据schema信息
|
||||
VE_API.system
|
||||
.schemaList({
|
||||
instanceId: instanceId.value,
|
||||
})
|
||||
.then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
getInstanceList();
|
||||
});
|
||||
|
||||
/**
|
||||
* 计算文件大小
|
||||
* @param fileSize
|
||||
* @returns {string}
|
||||
*/
|
||||
const formatFileSize = (fileSize) => {
|
||||
if (fileSize < 1024) {
|
||||
return fileSize + "B";
|
||||
} else if (fileSize < 1024 * 1024) {
|
||||
let temp = fileSize / 1024;
|
||||
temp = temp.toFixed(2);
|
||||
return temp + "KB";
|
||||
} else if (fileSize < 1024 * 1024 * 1024) {
|
||||
let temp = fileSize / (1024 * 1024);
|
||||
temp = temp.toFixed(2);
|
||||
return temp + "MB";
|
||||
} else {
|
||||
let temp = fileSize / (1024 * 1024 * 1024);
|
||||
temp = temp.toFixed(2);
|
||||
return temp + "GB";
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 文件更改
|
||||
* */
|
||||
const onChange = (file) => {
|
||||
var name = file.name;
|
||||
var size = file.size;
|
||||
form.name = name;
|
||||
form.uid = file.uid;
|
||||
if (size != null) {
|
||||
form.length = formatFileSize(size);
|
||||
}
|
||||
|
||||
form.data = file.raw;
|
||||
if (name !== null) {
|
||||
var split = name.split(".");
|
||||
form.type = split[split.length - 1];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let fd = new FormData();
|
||||
fd.append("multipartFileList", form.data); //传文件
|
||||
fd.append("instanceId", form.instanceId);
|
||||
fd.append("schema", form.schema);
|
||||
|
||||
let res = await VE_API.system.aceSchemaImportData(fd);
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
console.log(code);
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,289 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="类型(1:自动产生的、2:手动添加的)" prop="type">
|
||||
<el-select
|
||||
v-model="type"
|
||||
placeholder="类型(1:自动产生的、2:手动添加的)"
|
||||
clearable
|
||||
@change="getDataList"
|
||||
>
|
||||
<el-option label="自动产生的" value="1" />
|
||||
<el-option label="手动添加的" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="原始表" prop="sourceTable">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="sourceTable"
|
||||
placeholder="原始表"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="原始表字段" prop="sourceTableColumn">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="sourceTableColumn"
|
||||
placeholder="原始表字段"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['add']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.add.name)"
|
||||
>
|
||||
{{ buttons.add.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['analysisSchema']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleAnalysisSchemaEdit()"
|
||||
>
|
||||
{{ buttons.analysisSchema.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column
|
||||
prop="instanceId"
|
||||
label="数据库实例ID"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="schema"
|
||||
label="数据库实例schema"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="sourceTable"
|
||||
label="原始表"
|
||||
></el-table-column>
|
||||
<el-table-column prop="sourceTableColumn" label="原始表字段">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="relationTable"
|
||||
label="关系表"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="relationTableColumn"
|
||||
label="关系表字段"
|
||||
></el-table-column>
|
||||
<el-table-column prop="relation" label="关系"></el-table-column>
|
||||
<el-table-column
|
||||
prop="type"
|
||||
label="类型(1:自动产生的、2:手动添加的)"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['edit']"
|
||||
@click.prevent="handleEdit(buttons.edit.name, row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.edit.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['del']"
|
||||
@click.prevent="handleDel(row.id)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
|
||||
<!-- 编辑组件 -->
|
||||
<acw-table-association-relation-edit
|
||||
v-if="showDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
<acw-table-association-relation-analysis-schema-edit
|
||||
v-if="showAnalysisSchemaDialog"
|
||||
:showDialog="showAnalysisSchemaDialog"
|
||||
@closeDialog="handleAnalysisSchemaDialog($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "表关联关系",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
add: { name: "添加" },
|
||||
edit: { name: "编辑" },
|
||||
del: { name: "删除" },
|
||||
analysisSchema: { name: "解析schema" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Flag",
|
||||
name: "表关联关系管理",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import { reactive, toRefs, ref, onMounted, getCurrentInstance } from "vue";
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
import AcwTableAssociationRelationEdit from "@/views/layoutpages/acw/components/AcwTableAssociationRelationEdit.vue";
|
||||
import AcwTableAssociationRelationAnalysisSchemaEdit from "@/views/layoutpages/acw/components/AcwTableAssociationRelationAnalysisSchemaEdit.vue";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const rowData = ref(null);
|
||||
const dialogTitle = ref("");
|
||||
const showDialog = ref(false);
|
||||
const showAnalysisSchemaDialog = ref(false);
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const params = reactive({
|
||||
type: "2",
|
||||
sourceTable: "",
|
||||
sourceTableColumn: "",
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { type, sourceTable, sourceTableColumn, size, current, total } =
|
||||
toRefs(params);
|
||||
|
||||
/**
|
||||
* 左侧服务器树
|
||||
* @type {Ref<UnwrapRef<*[]>>}
|
||||
*/
|
||||
const leftServerTree = ref([]);
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEdit = (title, row = null) => {
|
||||
showDialog.value = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: dialog事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handelDialog = (e) => {
|
||||
showDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
|
||||
const handleAnalysisSchemaEdit = () => {
|
||||
showAnalysisSchemaDialog.value = true;
|
||||
};
|
||||
const handleAnalysisSchemaDialog = (e) => {
|
||||
showAnalysisSchemaDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
|
||||
/**删除行数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDel = (id) => {
|
||||
proxy
|
||||
.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
const { code } =
|
||||
await VE_API.system.acwTableAssociationRelationDelete({ id });
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } =
|
||||
await VE_API.system.acwTableAssociationRelationPage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
record.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
leftServerTree.value = record;
|
||||
}
|
||||
};
|
||||
onMounted(async () => {
|
||||
await getDataList();
|
||||
// maxHeight(pagination, queryForm, toolBar, ve_max_height);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.prefix {
|
||||
color: var(--el-color-primary);
|
||||
margin-right: 10px;
|
||||
}
|
||||
.prefix.is-leaf {
|
||||
color: var(--el-color-success);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="接口分组" prop="interfaceGroup">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="interfaceGroup"
|
||||
placeholder="接口分组"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="接口描述" prop="interfaceDescribe">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="interfaceDescribe"
|
||||
placeholder="接口描述"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['add']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.add.name)"
|
||||
>
|
||||
{{ buttons.add.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<el-table-column prop="tag" label="接口分组"></el-table-column>
|
||||
<el-table-column
|
||||
prop="description"
|
||||
label="接口描述"
|
||||
></el-table-column>
|
||||
<el-table-column prop="method" label="接口类型"></el-table-column>
|
||||
<el-table-column prop="path" label="接口地址"></el-table-column>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['edit']"
|
||||
@click.prevent="handleEdit(buttons.edit.name, row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.edit.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['del']"
|
||||
@click.prevent="handleDel(row.id)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['info']"
|
||||
@click.prevent="handleInfo('详情', row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.info.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
|
||||
<!-- 编辑组件 -->
|
||||
<api-factory-edit
|
||||
v-if="showDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
<!-- 编辑组件 -->
|
||||
<api-factory-edit
|
||||
v-if="showInfo"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showInfo"
|
||||
@closeDialog="handelInfo($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "接口工厂查询与设置",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
add: { name: "添加" },
|
||||
edit: { name: "编辑" },
|
||||
del: { name: "删除" },
|
||||
info: { name: "详情" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Histogram",
|
||||
name: "接口工厂管理",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import ApiFactoryEdit from "@/views/layoutpages/acw/components/ApiFactoryEdit";
|
||||
import { reactive, toRefs, ref, onMounted, getCurrentInstance } from "vue";
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const rowData = ref(null);
|
||||
const dialogTitle = ref("");
|
||||
const showDialog = ref(false);
|
||||
const showInfo = ref(false);
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const params = reactive({
|
||||
interfaceGroup: "",
|
||||
interfaceDescribe: "",
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { interfaceGroup, interfaceDescribe, size, current, total } =
|
||||
toRefs(params);
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEdit = (title, row = null) => {
|
||||
showDialog.value = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: dialog事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handelDialog = (e) => {
|
||||
showDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
/**删除行数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDel = (id) => {
|
||||
proxy
|
||||
.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
const { code } = await VE_API.system.apiDelete({ id });
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 行信息
|
||||
*/
|
||||
const handleInfo = (title, row = null) => {
|
||||
showInfo.value = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
const handelInfo = (e) => {
|
||||
showInfo.value = e;
|
||||
getDataList();
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } = await VE_API.system.apiPage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
}
|
||||
};
|
||||
onMounted(async () => {
|
||||
await getDataList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,207 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="应用名" prop="applicationName">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="applicationName"
|
||||
placeholder="应用名"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['add']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.add.name)"
|
||||
>
|
||||
{{ buttons.add.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column
|
||||
prop="projectName"
|
||||
label="项目名"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="applicationName"
|
||||
label="应用名"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="schemaName"
|
||||
label="数据库名称"
|
||||
></el-table-column>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['edit']"
|
||||
@click.prevent="handleEdit(buttons.edit.name, row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.edit.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['del']"
|
||||
@click.prevent="handleDel(row.applicationId)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
|
||||
<!-- 编辑组件 -->
|
||||
<application-edit
|
||||
v-if="showDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "acw应用查询与设置",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
add: { name: "添加" },
|
||||
edit: { name: "编辑" },
|
||||
del: { name: "删除" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Histogram",
|
||||
name: "ACW应用管理",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import ApplicationEdit from "./components/ApplicationEdit";
|
||||
import { reactive, toRefs, ref, onMounted, getCurrentInstance } from "vue";
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const rowData = ref(null);
|
||||
const dialogTitle = ref("");
|
||||
const showDialog = ref(false);
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const params = reactive({
|
||||
applicationName: "",
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { applicationName, size, current, total } = toRefs(params);
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEdit = (title, row = null) => {
|
||||
showDialog.value = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: dialog事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handelDialog = (e) => {
|
||||
showDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
/**删除行数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDel = (applicationId) => {
|
||||
console.log(applicationId);
|
||||
proxy
|
||||
.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
const { code } = await VE_API.system.applicationDelete({
|
||||
id: applicationId,
|
||||
});
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } = await VE_API.system.applicationPage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
}
|
||||
};
|
||||
onMounted(async () => {
|
||||
await getDataList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,344 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="服务器名称" prop="instanceName">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="instanceName"
|
||||
placeholder="服务器名称"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="是否初始化数据库到本地"
|
||||
prop="initializeToLocal"
|
||||
>
|
||||
<el-select
|
||||
v-model="initializeToLocal"
|
||||
placeholder="是否初始化数据库到本地"
|
||||
clearable
|
||||
@change="getDataList"
|
||||
>
|
||||
<el-option label="初始化数据库到本地" value="true" />
|
||||
<el-option label="不初始化数据库到本地" value="false" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['add']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.add.name)"
|
||||
>
|
||||
{{ buttons.add.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column
|
||||
prop="instanceName"
|
||||
label="服务器名称"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="driverClassName"
|
||||
label="驱动程序类名"
|
||||
></el-table-column>
|
||||
<el-table-column prop="username" label="登录名"></el-table-column>
|
||||
<el-table-column prop="password" label="登陆密码">
|
||||
<template v-slot="{ row }">
|
||||
<span>
|
||||
{{
|
||||
row.password &&
|
||||
row.password
|
||||
.split("")
|
||||
.fill("*", 1, -1)
|
||||
.join()
|
||||
.replace(/\,/g, "")
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="host" label="host"></el-table-column>
|
||||
<el-table-column prop="port" label="端口"></el-table-column>
|
||||
<el-table-column prop="status" label="状态"></el-table-column>
|
||||
<el-table-column prop="sort" label="排序"></el-table-column>
|
||||
<el-table-column label="数据源类型">
|
||||
<template v-slot="{ row }">
|
||||
<el-select
|
||||
v-model="row.lazyDataSourceType"
|
||||
placeholder="数据源类型"
|
||||
disabled
|
||||
>
|
||||
<el-option label="MySQL" value="MySQL" />
|
||||
<el-option label="H2" value="H2" />
|
||||
<el-option label="CLICK_HOUSE" value="CLICK_HOUSE" />
|
||||
<el-option label="POSTGRESQL" value="POSTGRESQL" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否初始化数据库到本地">
|
||||
<template v-slot="{ row }">
|
||||
<el-select
|
||||
v-model="row.initializeToLocal"
|
||||
placeholder="是否初始化数据库到本地"
|
||||
disabled
|
||||
>
|
||||
<el-option label="初始化数据库到本地" :value="true" />
|
||||
<el-option
|
||||
label="不初始化数据库到本地"
|
||||
:value="false"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['edit']"
|
||||
@click.prevent="handleEdit(buttons.edit.name, row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.edit.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['del']"
|
||||
@click.prevent="handleDel(row.id)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['reload']"
|
||||
@click="handleDatabaseInstanceReload(row.id)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.reload.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['backups']"
|
||||
@click="handleBackUpsRoute(row.id)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.backups.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
|
||||
<!-- 编辑组件 -->
|
||||
<database-instance-edit
|
||||
v-if="showDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
<!-- schema组件 -->
|
||||
<database-schema-edit
|
||||
v-if="showschemaDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showschemaDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库服务器查询与设置",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
add: { name: "添加" },
|
||||
edit: { name: "编辑" },
|
||||
del: { name: "删除" },
|
||||
reload: { name: "初始化服务器" },
|
||||
backups: { name: "实例备份" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Coin",
|
||||
name: "数据库实例管理",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import databaseInstanceEdit from "./components/DatabaseInstanceEdit";
|
||||
import DatabaseSchemaEdit from "./components/DatabaseSchemaEdit";
|
||||
import { reactive, toRefs, ref, onMounted, getCurrentInstance } from "vue";
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
getAsyncRouteName,
|
||||
} from "@/views/layoutpages/common";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const rowData = ref(null);
|
||||
const dialogTitle = ref("");
|
||||
const showDialog = ref(false);
|
||||
const showschemaDialog = ref(false);
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const params = reactive({
|
||||
instanceName: "",
|
||||
initializeToLocal: "",
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { instanceName, initializeToLocal, size, current, total } =
|
||||
toRefs(params);
|
||||
|
||||
/**
|
||||
* 左侧服务器树
|
||||
* @type {Ref<UnwrapRef<*[]>>}
|
||||
*/
|
||||
const leftServerTree = ref([]);
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEdit = (title, row = null) => {
|
||||
showDialog.value = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: 数据库实例备份信息
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleBackUpsRoute = async (title) => {
|
||||
let path = "acw/DatabaseInstanceBackUps";
|
||||
const toName = await getAsyncRouteName(title, path, "add", {
|
||||
router,
|
||||
route,
|
||||
});
|
||||
router.push({ name: toName });
|
||||
};
|
||||
/**
|
||||
* 重新加载实例
|
||||
*/
|
||||
const handleDatabaseInstanceReload = async (id) => {
|
||||
// 重新加载服务器
|
||||
console.log("重新加载服务器:" + id);
|
||||
const { code } = await VE_API.system.databaseInstanceReload({ id });
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description: dialog事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handelDialog = (e) => {
|
||||
showDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
/**删除行数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDel = (id) => {
|
||||
proxy
|
||||
.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
const { code } = await VE_API.system.databaseInstanceDelete({ id });
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } = await VE_API.system.databaseInstancePage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
record.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
leftServerTree.value = record;
|
||||
}
|
||||
};
|
||||
onMounted(async () => {
|
||||
await getDataList();
|
||||
// maxHeight(pagination, queryForm, toolBar, ve_max_height);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.prefix {
|
||||
color: var(--el-color-primary);
|
||||
margin-right: 10px;
|
||||
}
|
||||
.prefix.is-leaf {
|
||||
color: var(--el-color-success);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- <el-descriptions border>-->
|
||||
<!-- <el-descriptions-item label="实例名称"-->
|
||||
<!-- >实例名称-->
|
||||
<!-- </el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="实例数据库数量"-->
|
||||
<!-- >实例数据库数量-->
|
||||
<!-- </el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="实例表数量"-->
|
||||
<!-- >实例表数量-->
|
||||
<!-- </el-descriptions-item>-->
|
||||
<!-- </el-descriptions>-->
|
||||
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select
|
||||
v-model="params.instanceId"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['backups']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.backups.name)"
|
||||
>
|
||||
{{ buttons.backups.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column prop="id" label="记录ID"></el-table-column>
|
||||
<el-table-column
|
||||
prop="instanceName"
|
||||
label="实例名称"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="schemaNum"
|
||||
label="数据库数量"
|
||||
></el-table-column>
|
||||
<el-table-column prop="status" label="状态"></el-table-column>
|
||||
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['del']"
|
||||
@click.prevent="handleDel(row.id)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
<database-instance-back-ups-add
|
||||
v-if="showsBackUpsDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showsBackUpsDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatabaseInstanceBackUpsAdd from "@/views/layoutpages/acw/components/DatabaseInstanceBackUpsAdd";
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
export default {
|
||||
components: { DatabaseInstanceBackUpsAdd },
|
||||
data: () => ({
|
||||
description: "数据库实例备份",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
del: { name: "删除数据库实例备份" },
|
||||
backups: { name: "实例备份" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Guide",
|
||||
name: "数据库实例备份",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
<script setup>
|
||||
import { reactive, toRefs, ref, defineProps, onMounted } from "vue";
|
||||
import databaseInstanceBackUpsAdd from "./components/DatabaseInstanceBackUpsAdd";
|
||||
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const { rowData } = toRefs(props);
|
||||
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const showsBackUpsDialog = ref(false);
|
||||
const serverList = ref(null);
|
||||
|
||||
const params = reactive({
|
||||
instanceName: "",
|
||||
initializeToLocal: "",
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
name: "",
|
||||
userName: "",
|
||||
password: "",
|
||||
role: "",
|
||||
status: 1,
|
||||
});
|
||||
const { size, current, total } = toRefs(params);
|
||||
const { userName, name, password, role, status } = toRefs(form);
|
||||
const roleList = ref([]);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((name.value = rowData.value.name),
|
||||
(userName.value = rowData.value.userName),
|
||||
(password.value = rowData.value.password),
|
||||
(role.value = rowData.value.role),
|
||||
(status.value = rowData.value.status));
|
||||
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEdit = (title, row = null) => {
|
||||
showsBackUpsDialog.value = true;
|
||||
rowData.value = row;
|
||||
};
|
||||
/**
|
||||
* 删除数据库事例备份
|
||||
*/
|
||||
const handleDel = async (id) => {
|
||||
const { code } = await VE_API.system.databaseInstanceBackUpDelete({
|
||||
id: id,
|
||||
});
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description: 获取角色列表
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getRoleList = async () => {
|
||||
const { code, data } = await VE_API.system.roleList(
|
||||
{
|
||||
page: 1,
|
||||
size: 10,
|
||||
},
|
||||
{ Global: false },
|
||||
);
|
||||
if (code === "0") {
|
||||
const { list } = data;
|
||||
roleList.value = list;
|
||||
}
|
||||
};
|
||||
getRoleList();
|
||||
|
||||
/**
|
||||
* 隐藏弹框
|
||||
* */
|
||||
const handelDialog = (e) => {
|
||||
showsBackUpsDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } =
|
||||
await VE_API.system.databaseInstanceBackUpPage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
record.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
return serverList.value;
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getServerInstanceList();
|
||||
await getDataList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<el-tabs
|
||||
v-model="currentConsoleTableKey"
|
||||
type="card"
|
||||
closable
|
||||
@tab-remove="closeCurrentConsoleTable(currentConsoleTableKey)"
|
||||
>
|
||||
<el-tab-pane
|
||||
v-for="item in consoleTableList"
|
||||
:key="item.index"
|
||||
:label="item.title"
|
||||
:name="item.name"
|
||||
>
|
||||
<database-query-console />
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane
|
||||
key="lastConsoleTable"
|
||||
label="新增页签"
|
||||
name="新增页签name"
|
||||
@onclick="addConsoleTable(currentConsoleTableKey)"
|
||||
>
|
||||
<el-button
|
||||
size="small"
|
||||
@click="addConsoleTable(currentConsoleTableKey)"
|
||||
>
|
||||
新增页签
|
||||
</el-button>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
<script>
|
||||
import DatabaseQueryConsole from "@/views/layoutpages/acw/components/DatabaseQueryConsole.vue";
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库多表复杂查询控制台",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
downLoad: { name: "导出查询结果为Excel" },
|
||||
downLoadUpsert: { name: "Upsert下载查询结果" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "IceCream",
|
||||
name: "数据库多表复杂查询控制台",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
|
||||
// 当前页
|
||||
const currentConsoleTableKey = ref(0);
|
||||
// 查询sql的所有列
|
||||
const consoleTableList = ref([
|
||||
{
|
||||
index: 0,
|
||||
name: 0,
|
||||
title: "执行查询",
|
||||
},
|
||||
]);
|
||||
|
||||
/**
|
||||
* 添加页签
|
||||
*/
|
||||
const addConsoleTable = (currentIndex) => {
|
||||
console.log("当前标签页🏷️" + currentIndex);
|
||||
currentConsoleTableKey.value = consoleTableList.value.length + 1;
|
||||
consoleTableList.value.push({
|
||||
name: currentConsoleTableKey.value,
|
||||
title: "执行查询 (" + currentConsoleTableKey.value + ")",
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 关闭当前table
|
||||
*/
|
||||
const closeCurrentConsoleTable = (currentIndex) => {
|
||||
console.log("删除页签" + currentIndex);
|
||||
consoleTableList.value.splice(currentIndex - 1, 1);
|
||||
};
|
||||
|
||||
onMounted(async () => {});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,626 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="数据库实例" property="instanceId">
|
||||
<el-select
|
||||
v-model="instanceId"
|
||||
@change="getDataList"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库库名" prop="schemaName">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="schemaName"
|
||||
placeholder="数据库库名"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="是否初始化数据库到本地"
|
||||
prop="initializeToLocal"
|
||||
>
|
||||
<el-select
|
||||
v-model="initializeToLocal"
|
||||
placeholder="是否初始化数据库到本地"
|
||||
clearable
|
||||
@change="getDataList"
|
||||
>
|
||||
<el-option label="初始化数据库到本地" value="true" />
|
||||
<el-option label="不初始化数据库到本地" value="false" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
border
|
||||
style="width: 80%"
|
||||
@selectionChange="handleSelectionChange"
|
||||
ref="multipleTableRef"
|
||||
>
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['add']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.add.name)"
|
||||
>
|
||||
{{ buttons.add.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['batchDel']"
|
||||
size="small"
|
||||
type="danger"
|
||||
@click="batchDel"
|
||||
>
|
||||
{{ buttons.batchDel.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['batchExportData']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="batchExportData"
|
||||
>
|
||||
{{ buttons.batchExportData.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['schemaDeriveView']"
|
||||
@click="
|
||||
handleSchemaDeriveView(
|
||||
buttons.schemaDeriveView.name,
|
||||
row,
|
||||
)
|
||||
"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.schemaDeriveView.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<!-- <el-table-column prop="id" label="ID"></el-table-column>-->
|
||||
<el-table-column
|
||||
prop="instanceName"
|
||||
label="数据库实例"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="schemaName"
|
||||
label="数据库库名"
|
||||
></el-table-column>
|
||||
<el-table-column label="是否初始化数据库到本地">
|
||||
<template v-slot="{ row }">
|
||||
<el-select
|
||||
v-model="row.initializeToLocal"
|
||||
placeholder="是否初始化数据库到本地"
|
||||
disabled
|
||||
>
|
||||
<el-option label="初始化数据库到本地" :value="true" />
|
||||
<el-option
|
||||
label="不初始化数据库到本地"
|
||||
:value="false"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="dataLength"
|
||||
label="数据大小"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="indexLength"
|
||||
label="索引大小"
|
||||
></el-table-column>
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="characterSet"-->
|
||||
<!-- label="字符集"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="sortingRules"-->
|
||||
<!-- label="排序规则"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column prop="ext" label="ext"></el-table-column>-->
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['edit']"
|
||||
@click.prevent="handleEdit(buttons.edit.name, row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.edit.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['exportData']"
|
||||
@click.prevent="handleExportData(row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.exportData.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['exportStructure']"
|
||||
@click.prevent="handleExportStructure(row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.exportStructure.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['exportStructureExcel']"
|
||||
@click.prevent="handleExportStructureExcel(row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.exportStructureExcel.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['del']"
|
||||
@click.prevent="handleDel(row)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['reload']"
|
||||
@click="handleDatabaseSchemaReload(row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.reload.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
|
||||
<!-- 编辑组件 -->
|
||||
<database-schema-edit
|
||||
v-if="showDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
<!-- 数据库衍生视图 -->
|
||||
<database-schema-derive-view
|
||||
v-if="showSchemaDeriveViewDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showSchemaDeriveViewDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库信息查询与设置",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
add: { name: "添加" },
|
||||
edit: { name: "编辑" },
|
||||
del: { name: "删除" },
|
||||
exportData: { name: "导出数据" },
|
||||
exportStructure: { name: "导出结构为SQL" },
|
||||
exportStructureExcel: { name: "导出结构为Excel" },
|
||||
batchDel: { name: "批量删除" },
|
||||
batchExportData: { name: "批量导出数据" },
|
||||
reload: { name: "初始化schema" },
|
||||
schemaDeriveView: { name: "数据库衍生视图" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "IceDrink",
|
||||
name: "数据库信息管理",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import databaseSchemaEdit from "./components/DatabaseSchemaEdit";
|
||||
import { reactive, toRefs, ref, onMounted, getCurrentInstance } from "vue";
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
import DatabaseSchemaDeriveView from "@/views/layoutpages/acw/components/DatabaseSchemaDeriveView.vue";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const rowData = ref(null);
|
||||
const dialogTitle = ref("");
|
||||
const showDialog = ref(false);
|
||||
const showSchemaDeriveViewDialog = ref(false);
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const serverList = ref(null);
|
||||
// 批量删除选中的 schema
|
||||
const batchSelectDatabaseSchemaList = ref([]);
|
||||
|
||||
const params = reactive({
|
||||
instanceId: "",
|
||||
schemaName: "",
|
||||
initializeToLocal: false,
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { instanceId, schemaName, initializeToLocal, size, current, total } =
|
||||
toRefs(params);
|
||||
const multipleTableRef = ref(null);
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEdit = (title, row = null) => {
|
||||
showDialog.value = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: dialog事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handelDialog = (e) => {
|
||||
showDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
/**
|
||||
*
|
||||
* 批量导出数据
|
||||
*/
|
||||
const batchExportData = () => {
|
||||
if (batchSelectDatabaseSchemaList.value.length == 0) {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "请选择一个schema",
|
||||
});
|
||||
return;
|
||||
}
|
||||
proxy
|
||||
.$confirm("此操作将批量导出数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
let databaseSchemaDeleteCommandList =
|
||||
batchSelectDatabaseSchemaList.value.map((item) => {
|
||||
return {
|
||||
instanceName: item.instanceName,
|
||||
schema: item.schemaName,
|
||||
};
|
||||
});
|
||||
let res = await VE_API.system.batchExportSchemaData(
|
||||
databaseSchemaDeleteCommandList,
|
||||
{
|
||||
responseType: "blob",
|
||||
},
|
||||
);
|
||||
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
getDataList();
|
||||
});
|
||||
};
|
||||
/**
|
||||
*
|
||||
* 批量删除
|
||||
*/
|
||||
const batchDel = () => {
|
||||
if (batchSelectDatabaseSchemaList.value.length === 0) {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "请选择一个schema",
|
||||
});
|
||||
return;
|
||||
}
|
||||
proxy
|
||||
.$confirm(
|
||||
`此操作将批量永久删除【${batchSelectDatabaseSchemaList.value.length}】个数据库, 是否继续?`,
|
||||
"提示",
|
||||
{
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
},
|
||||
)
|
||||
.then(async () => {
|
||||
let databaseSchemaDeleteCommandList =
|
||||
batchSelectDatabaseSchemaList.value.map((item) => {
|
||||
return {
|
||||
instanceName: item.instanceName,
|
||||
instanceId: item.instanceId,
|
||||
schema: item.schemaName,
|
||||
};
|
||||
});
|
||||
const { code } = await VE_API.system.batchDeleteInstanceSchema(
|
||||
databaseSchemaDeleteCommandList,
|
||||
);
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**删除行数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDel = (row) => {
|
||||
proxy
|
||||
.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
if (row === undefined) {
|
||||
getDataList();
|
||||
} else {
|
||||
let databaseSchemaDeleteCommandList = [
|
||||
{
|
||||
instanceName: row.instanceName,
|
||||
instanceId: row.instanceId,
|
||||
schema: row.schemaName,
|
||||
},
|
||||
];
|
||||
const { code } = await VE_API.system.batchDeleteInstanceSchema(
|
||||
databaseSchemaDeleteCommandList,
|
||||
);
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**导出数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleExportData = (row) => {
|
||||
proxy
|
||||
.$confirm("此操作将导出数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
if (row == undefined) {
|
||||
getDataList();
|
||||
} else {
|
||||
let databaseSchemaDeleteCommandList = [
|
||||
{
|
||||
instanceName: row.instanceName,
|
||||
schema: row.schemaName,
|
||||
},
|
||||
];
|
||||
let res = await VE_API.system.batchExportSchemaData(
|
||||
databaseSchemaDeleteCommandList,
|
||||
{
|
||||
responseType: "blob",
|
||||
},
|
||||
);
|
||||
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
getDataList();
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 导出结构
|
||||
*/
|
||||
const handleExportStructure = async (row) => {
|
||||
let res = await VE_API.system.exportTableStructureSql(row, {
|
||||
responseType: "blob",
|
||||
});
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
};
|
||||
/**
|
||||
* 导出结构
|
||||
*/
|
||||
const handleExportStructureExcel = async (row) => {
|
||||
let res = await VE_API.system.exportTableStructureExcel(row, {
|
||||
responseType: "blob",
|
||||
});
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
};
|
||||
/**
|
||||
* 全选事件
|
||||
*
|
||||
*/
|
||||
const handleSelectionChange = (val) => {
|
||||
batchSelectDatabaseSchemaList.value = val;
|
||||
console.log(batchSelectDatabaseSchemaList.value);
|
||||
};
|
||||
|
||||
/**
|
||||
* 数据库衍生视图
|
||||
* @param row
|
||||
*/
|
||||
const handleSchemaDeriveView = (title, row) => {
|
||||
console.log(row);
|
||||
showSchemaDeriveViewDialog.value = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
/**
|
||||
* 初始化数据库schema
|
||||
* **/
|
||||
const handleDatabaseSchemaReload = async (row) => {
|
||||
const { code, data } = await VE_API.system.schemaReload({
|
||||
instanceId: row.instanceId,
|
||||
schema: row.schemaName,
|
||||
});
|
||||
if (code === 0) {
|
||||
console.log("success");
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } = await VE_API.system.schemaPage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
}
|
||||
};
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
if (serverList.value.length == 0) {
|
||||
return;
|
||||
}
|
||||
params.instanceId = serverList.value[0].id;
|
||||
|
||||
getDataList();
|
||||
});
|
||||
};
|
||||
onMounted(async () => {
|
||||
await getServerInstanceList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ve_container {
|
||||
::v-deep
|
||||
.el-table__header
|
||||
.el-table-column--selection
|
||||
.cell
|
||||
.el-checkbox:after {
|
||||
color: #606266;
|
||||
content: "全选";
|
||||
font-size: 12px;
|
||||
margin-left: 2px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,348 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- <el-descriptions border>-->
|
||||
<!-- <el-descriptions-item label="实例名称"-->
|
||||
<!-- >实例名称-->
|
||||
<!-- </el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="实例数据库数量"-->
|
||||
<!-- >实例数据库数量-->
|
||||
<!-- </el-descriptions-item>-->
|
||||
<!-- <el-descriptions-item label="实例表数量"-->
|
||||
<!-- >实例表数量-->
|
||||
<!-- </el-descriptions-item>-->
|
||||
<!-- </el-descriptions>-->
|
||||
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select
|
||||
v-model="params.instanceId"
|
||||
@change="getSchemaList"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库名" prop="schemaName">
|
||||
<el-select
|
||||
clearable
|
||||
filterable
|
||||
@change="getDataList"
|
||||
v-model="params.schemaName"
|
||||
placeholder="数据库名"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['backups']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.backups.name)"
|
||||
>
|
||||
{{ buttons.backups.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column prop="id" label="记录ID"></el-table-column>
|
||||
<el-table-column
|
||||
prop="instanceName"
|
||||
label="实例名称"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="schemaName"
|
||||
label="数据库名称"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="tableNum"
|
||||
label="数据库表数量"
|
||||
:sortable="true"
|
||||
></el-table-column>
|
||||
<el-table-column prop="status" label="状态"></el-table-column>
|
||||
<el-table-column prop="path" label="备份数据库地址"
|
||||
><template #default="scope">
|
||||
<a
|
||||
style="color: #7099f9"
|
||||
@click="downloadBackUps(scope.row)"
|
||||
>{{ scope.row.path }}
|
||||
</a>
|
||||
</template></el-table-column
|
||||
>
|
||||
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['down']"
|
||||
@click.prevent="downloadBackUps(row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.down.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['del']"
|
||||
@click.prevent="handleDel(row.id)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
<database-schema-back-ups-add
|
||||
v-if="showsBackUpsDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showsBackUpsDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库备份",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
down: { name: "下载" },
|
||||
del: { name: "删除" },
|
||||
backups: { name: "数据库备份" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Ship",
|
||||
name: "数据库备份",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
<script setup>
|
||||
import { reactive, toRefs, ref, defineProps, onMounted } from "vue";
|
||||
|
||||
import databaseSchemaBackUpsAdd from "./components/DatabaseSchemaBackUpsAdd";
|
||||
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const { rowData } = toRefs(props);
|
||||
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const showsBackUpsDialog = ref(false);
|
||||
const serverList = ref(null);
|
||||
|
||||
const schemaList = ref(null);
|
||||
|
||||
const params = reactive({
|
||||
instanceId: "",
|
||||
// status: 1,
|
||||
schemaName: "",
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { size, current, total } = toRefs(params);
|
||||
|
||||
const form = reactive({
|
||||
instanceId: "",
|
||||
status: 1,
|
||||
});
|
||||
const { instanceId, status } = toRefs(form);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((instanceId.value = rowData.value.instanceId),
|
||||
(status.value = rowData.value.status));
|
||||
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEdit = (title, row = null) => {
|
||||
showsBackUpsDialog.value = true;
|
||||
rowData.value = row;
|
||||
};
|
||||
/**
|
||||
* 删除备份记录
|
||||
* @param id
|
||||
*/
|
||||
const handleDel = async (id) => {
|
||||
const { code } = await VE_API.system.databaseSchemaBackUpRemove({ id: id });
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
};
|
||||
/**
|
||||
*@param row 行数据
|
||||
* 下载备份数据
|
||||
*
|
||||
* */
|
||||
const downloadBackUps = async (row) => {
|
||||
// console.log(row);
|
||||
let res = await VE_API.system.downLocalFile(
|
||||
{ path: row.path },
|
||||
{
|
||||
responseType: "blob",
|
||||
},
|
||||
);
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
};
|
||||
|
||||
/**
|
||||
* 隐藏弹框
|
||||
* */
|
||||
const handelDialog = (e) => {
|
||||
showsBackUpsDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } = await VE_API.system.databaseSchemaBackUpPage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
record.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取 数据库
|
||||
* @param instanceId 数据库实例ID
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getSchemaList = async (instanceId) => {
|
||||
let res;
|
||||
if (instanceId == null) {
|
||||
return;
|
||||
} else {
|
||||
res = await VE_API.system.schemaList({
|
||||
instanceId,
|
||||
});
|
||||
}
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaList.value = data;
|
||||
if (schemaList.value) {
|
||||
// 默认第一个实例的第一个数据库
|
||||
params.schemaName = schemaList.value[0].schemaName;
|
||||
}
|
||||
return schemaList.value;
|
||||
}
|
||||
};
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
// 默认第一个实例
|
||||
if (serverList.value && serverList.value.length > 0) {
|
||||
params.instanceId = serverList.value[0].id;
|
||||
getSchemaList(params.instanceId);
|
||||
}
|
||||
return serverList.value;
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getServerInstanceList();
|
||||
await getDataList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<el-tabs
|
||||
v-model="currentConsoleTableKey"
|
||||
type="card"
|
||||
closable
|
||||
@tab-remove="closeCurrentConsoleTable(currentConsoleTableKey)"
|
||||
>
|
||||
<el-tab-pane
|
||||
v-for="item in consoleTableList"
|
||||
:key="item.index"
|
||||
:label="item.title"
|
||||
:name="item.name"
|
||||
>
|
||||
<database-table-console />
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane
|
||||
key="lastConsoleTable"
|
||||
label="新增页签"
|
||||
name="新增页签name"
|
||||
@onclick="addConsoleTable(currentConsoleTableKey)"
|
||||
>
|
||||
<el-button
|
||||
size="small"
|
||||
@click="addConsoleTable(currentConsoleTableKey)"
|
||||
>
|
||||
新增单表查询页签
|
||||
</el-button>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "单表查询控制台",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
downLoad: { name: "导出查询结果为Excel" },
|
||||
downLoadUpsert: { name: "Upsert下载查询结果" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Finished",
|
||||
name: "单表查询控制台",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import DatabaseTableConsole from "@/views/layoutpages/acw/components/DatabaseTableConsole.vue";
|
||||
|
||||
// 当前页
|
||||
const currentConsoleTableKey = ref(0);
|
||||
// 查询sql的所有列
|
||||
const consoleTableList = ref([
|
||||
{
|
||||
index: 0,
|
||||
name: 0,
|
||||
title: "执行查询",
|
||||
},
|
||||
]);
|
||||
|
||||
/**
|
||||
* 添加页签
|
||||
*/
|
||||
const addConsoleTable = (currentIndex) => {
|
||||
console.log("当前标签页🏷️" + currentIndex);
|
||||
currentConsoleTableKey.value = consoleTableList.value.length + 1;
|
||||
consoleTableList.value.push({
|
||||
name: currentConsoleTableKey.value,
|
||||
title: "执行查询 (" + currentConsoleTableKey.value + ")",
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 关闭当前table
|
||||
*/
|
||||
const closeCurrentConsoleTable = (currentIndex) => {
|
||||
console.log("删除页签" + currentIndex);
|
||||
consoleTableList.value.splice(currentIndex - 1, 1);
|
||||
};
|
||||
|
||||
onMounted(async () => {});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,480 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="数据库实例" property="instanceId">
|
||||
<el-select
|
||||
v-model="params.instanceId"
|
||||
@change="getSchemaList"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库名" prop="schemaName">
|
||||
<el-select
|
||||
clearable
|
||||
v-model="params.schemaName"
|
||||
placeholder="数据库名"
|
||||
@change="getDataList"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaNameList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="表名" prop="tableName">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="tableName"
|
||||
placeholder="表名"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="是否初始化数据库到本地"
|
||||
prop="initializeToLocal"
|
||||
>
|
||||
<el-select
|
||||
v-model="initializeToLocal"
|
||||
placeholder="是否初始化数据库到本地"
|
||||
clearable
|
||||
@change="getDataList"
|
||||
>
|
||||
<el-option label="初始化数据库到本地" value="true" />
|
||||
<el-option label="不初始化数据库到本地" value="false" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
@selectionChange="handleSelectionChange"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['add']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEditRoute(buttons.add.name)"
|
||||
>
|
||||
{{ buttons.add.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['batchDel']"
|
||||
size="small"
|
||||
type="danger"
|
||||
@click="batchDelTable"
|
||||
>
|
||||
{{ buttons.batchDel.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column
|
||||
prop="schemaName"
|
||||
label="数据库库名"
|
||||
></el-table-column>
|
||||
<el-table-column prop="tableName" label="表名称"> </el-table-column>
|
||||
<el-table-column
|
||||
prop="tableComment"
|
||||
label="表描述"
|
||||
width="120"
|
||||
></el-table-column>
|
||||
<el-table-column prop="tableType" label="表类型"></el-table-column>
|
||||
<el-table-column
|
||||
prop="tableRows"
|
||||
sortable
|
||||
label="表行数"
|
||||
></el-table-column>
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="avgRowLength"-->
|
||||
<!-- label="avgRowLength"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="autoIncrement"-->
|
||||
<!-- label="autoIncrement"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="checkTime"-->
|
||||
<!-- label="checkTime"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column prop="checksum" label="checksum"></el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="createOptions"-->
|
||||
<!-- label="createOptions"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column prop="dataFree" label="dataFree"></el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="dataLength"-->
|
||||
<!-- label="dataLength"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<el-table-column prop="engine" label="表引擎"></el-table-column>
|
||||
<el-table-column
|
||||
prop="dataLength"
|
||||
label="数据大小"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="indexLength"
|
||||
label="索引大小"
|
||||
></el-table-column>
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="maxDataLength"-->
|
||||
<!-- label="maxDataLength"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="rowFormat"-->
|
||||
<!-- label="rowFormat"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="tableCatalog"-->
|
||||
<!-- label="tableCatalog"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="tableCollation"-->
|
||||
<!-- label="tableCollation"-->
|
||||
<!-- ></el-table-column>-->
|
||||
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
label="创建时间"
|
||||
></el-table-column>
|
||||
<el-table-column prop="version" label="版本"></el-table-column>
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
label="更新时间"
|
||||
></el-table-column>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['edit']"
|
||||
@click.prevent="handleEditRoute(buttons.edit.name, row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.edit.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['del']"
|
||||
@click.prevent="handleDel(row)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['more']"
|
||||
@click.prevent="handleShowMore(buttons.more.name, row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.more.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
|
||||
<!-- 编辑组件 -->
|
||||
<database-table-edit
|
||||
v-if="showDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showDialog"
|
||||
@closeDialog="handleDialog($event)"
|
||||
/>
|
||||
<!-- 更多 -->
|
||||
<database-table-more
|
||||
v-if="showMore"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showMore"
|
||||
@closeDialog="handleShowMoreDialog($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库表查询与设置",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
add: { name: "添加表" },
|
||||
edit: { name: "编辑" },
|
||||
// crud: { name: "表crud操作" },
|
||||
del: { name: "删除" },
|
||||
batchDel: { name: "批量删除" },
|
||||
more: { name: "更多" },
|
||||
|
||||
java_code: { name: "Java代码本地生成" },
|
||||
export_insert_sql: { name: "导出insert-sql" },
|
||||
export_upsert_sql: { name: "导出upsert-sql" },
|
||||
export_table_excel: { name: "导出表结构.excel" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "CopyDocument",
|
||||
name: "数据库表管理",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import DatabaseTableEdit from "./components/DatabaseTableEdit";
|
||||
import DatabaseTableMore from "./components/DatabaseTableMore";
|
||||
import { reactive, toRefs, ref, onMounted, getCurrentInstance } from "vue";
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
getAsyncRouteName,
|
||||
} from "@/views/layoutpages/common";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
const { proxy } = getCurrentInstance();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const rowData = ref(null);
|
||||
const dialogTitle = ref("");
|
||||
const showDialog = ref(false);
|
||||
const showMore = ref(false);
|
||||
const showJavaCodeDialog = ref(false);
|
||||
const showDocumentDialog = ref(false);
|
||||
const showTableColumnDialog = ref(false);
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const schemaNameList = ref(null);
|
||||
const serverList = ref(null);
|
||||
|
||||
const batchSelectDatabaseSchemaTableList = ref([]);
|
||||
const params = reactive({
|
||||
tableName: "",
|
||||
schemaName: "",
|
||||
instanceId: "",
|
||||
initializeToLocal: false,
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
const { tableName, initializeToLocal, size, current, total } = toRefs(params);
|
||||
/**
|
||||
* @description: 添加页面路由式
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEditRoute = async (title, row = null) => {
|
||||
let path = "acw/components/DatabaseTableEdit";
|
||||
const toName = await getAsyncRouteName(title, path, "add", {
|
||||
router,
|
||||
route,
|
||||
});
|
||||
router.push({
|
||||
name: toName,
|
||||
query: row,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 展示更多
|
||||
*
|
||||
* */
|
||||
const handleShowMore = (title, row = null) => {
|
||||
console.log(showMore.value);
|
||||
showMore.value = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
const handleShowMoreDialog = (e) => {
|
||||
showMore.value = e;
|
||||
getDataList();
|
||||
};
|
||||
/**
|
||||
* @description: dialog事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDialog = (e) => {
|
||||
showDialog.value = e;
|
||||
showJavaCodeDialog.value = e;
|
||||
showDocumentDialog.value = e;
|
||||
showTableColumnDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 全选事件
|
||||
*
|
||||
*/
|
||||
const handleSelectionChange = (val) => {
|
||||
batchSelectDatabaseSchemaTableList.value = val;
|
||||
console.log(batchSelectDatabaseSchemaTableList.value);
|
||||
};
|
||||
/**
|
||||
*
|
||||
* 批量删除
|
||||
*/
|
||||
const batchDelTable = () => {
|
||||
if (batchSelectDatabaseSchemaTableList.value.length == 0) {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "请选择一个表",
|
||||
});
|
||||
return;
|
||||
}
|
||||
proxy
|
||||
.$confirm("此操作将批量永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
let databaseSchemaDeleteCommandList =
|
||||
batchSelectDatabaseSchemaTableList.value.map((item) => {
|
||||
return {
|
||||
instanceId: item.instanceId,
|
||||
schemaName: item.schemaName,
|
||||
tableName: item.tableName,
|
||||
};
|
||||
});
|
||||
const { code } = await VE_API.system.batchDeleteTableDelete(
|
||||
databaseSchemaDeleteCommandList,
|
||||
);
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**删除行数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDel = (row) => {
|
||||
proxy
|
||||
.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
const { code } = await VE_API.system.tableDelete({
|
||||
instanceId: row.instanceId,
|
||||
schemaName: row.schemaName,
|
||||
tableName: row.tableName,
|
||||
});
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
// console.log(params);
|
||||
const { code, data } = await VE_API.system.tablePage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取 数据库
|
||||
* @param instanceId 数据库实例ID
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getSchemaList = async (instanceId) => {
|
||||
let res;
|
||||
if (instanceId == null) {
|
||||
return;
|
||||
} else {
|
||||
res = await VE_API.system.schemaList({
|
||||
instanceId,
|
||||
});
|
||||
}
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaNameList.value = data;
|
||||
if (schemaNameList.value.list !== 0) {
|
||||
params.schemaName = schemaNameList.value[0].schemaName;
|
||||
}
|
||||
}
|
||||
await getDataList();
|
||||
};
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then(async (res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
if (serverList.value.length !== 0) {
|
||||
// 设置默认instance
|
||||
params.instanceId = serverList.value[0].id;
|
||||
getSchemaList(params.instanceId);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getServerInstanceList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,381 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="数据库实例" property="instanceId">
|
||||
<el-select
|
||||
v-model="params.instanceId"
|
||||
@change="getSchemaList"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库名" prop="schemaNameId">
|
||||
<el-select
|
||||
clearable
|
||||
v-model="params.schemaNameId"
|
||||
placeholder="数据库名"
|
||||
@change="getDataList"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaNameList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="表名" prop="tableName">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="tableName"
|
||||
placeholder="表名"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="填充状态" prop="status">
|
||||
<el-select
|
||||
v-model="status"
|
||||
placeholder="填充状态"
|
||||
clearable
|
||||
@change="getDataList"
|
||||
>
|
||||
<el-option label="成功" :value="true" />
|
||||
<el-option label="失败" :value="false" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
@selectionChange="handleSelectionChange"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['add']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.add.name)"
|
||||
>
|
||||
{{ buttons.add.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['batchDel']"
|
||||
size="small"
|
||||
type="danger"
|
||||
@click="batchDelDatabaseTableAutoStuffed"
|
||||
>
|
||||
{{ buttons.batchDel.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="id" label="填充记录ID"> </el-table-column>
|
||||
<el-table-column
|
||||
prop="instanceName"
|
||||
label="数据库实例"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="schemaName"
|
||||
label="数据库库名"
|
||||
></el-table-column>
|
||||
<el-table-column prop="tableName" label="表名称"> </el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="autoStuffedNum"
|
||||
label="自动填充数量"
|
||||
></el-table-column>
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template v-slot="{ row }">
|
||||
<el-select
|
||||
v-model="row.status"
|
||||
placeholder="数据填充状态"
|
||||
disabled
|
||||
>
|
||||
<el-option label="成功" :value="true" />
|
||||
<el-option label="失败" :value="false" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
label="创建时间"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
label="更新时间"
|
||||
></el-table-column>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['edit']"
|
||||
@click.prevent="handleEdit(buttons.edit.name, row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.edit.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['del']"
|
||||
@click.prevent="handleDel(row.id)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
|
||||
<!-- 编辑组件 -->
|
||||
<database-table-auto-stuffed-edit
|
||||
v-if="showDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showDialog"
|
||||
@closeDialog="handleDialog($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库表数据自动填充查询与设置",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
add: { name: "添加自动填充记录" },
|
||||
edit: { name: "编辑自动填充记录" },
|
||||
del: { name: "删除自动填充记录" },
|
||||
batchDel: { name: "批量删除自动填充记录" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "PictureRounded",
|
||||
name: "数据库表数据自动填充",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import DatabaseTableAutoStuffedEdit from "./components/DatabaseTableAutoStuffedEdit";
|
||||
|
||||
import { reactive, toRefs, ref, onMounted, getCurrentInstance } from "vue";
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
const { proxy } = getCurrentInstance();
|
||||
const rowData = ref(null);
|
||||
const dialogTitle = ref("");
|
||||
const showDialog = ref(false);
|
||||
|
||||
const showJavaCodeDialog = ref(false);
|
||||
const showDocumentDialog = ref(false);
|
||||
const showTableColumnDialog = ref(false);
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const schemaNameList = ref(null);
|
||||
const serverList = ref(null);
|
||||
const batchSelectDatabaseTableAutoStuffedList = ref(null);
|
||||
const params = reactive({
|
||||
tableName: "",
|
||||
schemaNameId: "",
|
||||
instanceId: "",
|
||||
status: true,
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { tableName, status, size, current, total } = toRefs(params);
|
||||
|
||||
/**
|
||||
* 全选事件
|
||||
*
|
||||
*/
|
||||
const handleSelectionChange = (val) => {
|
||||
batchSelectDatabaseTableAutoStuffedList.value = val;
|
||||
console.log(batchSelectDatabaseTableAutoStuffedList.value);
|
||||
};
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEdit = (title, row = null) => {
|
||||
showDialog.value = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
/**
|
||||
* @description: dialog事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDialog = (e) => {
|
||||
showDialog.value = e;
|
||||
showJavaCodeDialog.value = e;
|
||||
showDocumentDialog.value = e;
|
||||
showTableColumnDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* 批量删除
|
||||
*/
|
||||
const batchDelDatabaseTableAutoStuffed = () => {
|
||||
if (batchSelectDatabaseTableAutoStuffedList.value.length == 0) {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "请选择一个填充记录",
|
||||
});
|
||||
return;
|
||||
}
|
||||
proxy
|
||||
.$confirm("此操作将批量永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
let ids = batchSelectDatabaseTableAutoStuffedList.value.map(
|
||||
(item) => {
|
||||
return item.id;
|
||||
},
|
||||
);
|
||||
console.log(ids);
|
||||
const { code } =
|
||||
await VE_API.system.tableAutoStuffedRecordBatchDelete(ids);
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**删除行数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDel = (id) => {
|
||||
proxy
|
||||
.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
const { code } = await VE_API.system.tableAutoStuffedRecordDelete({
|
||||
id,
|
||||
});
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } =
|
||||
await VE_API.system.tableAutoStuffedRecordPage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取 数据库
|
||||
* @param instanceId 数据库实例ID
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getSchemaList = async (instanceId) => {
|
||||
let res;
|
||||
if (instanceId == null) {
|
||||
res = await VE_API.system.schemaList();
|
||||
} else {
|
||||
res = await VE_API.system.schemaList({
|
||||
instanceId,
|
||||
});
|
||||
}
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaNameList.value = data;
|
||||
}
|
||||
await getDataList();
|
||||
};
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getServerInstanceList();
|
||||
await getDataList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
210
wu-lazy-cloud-network-ui/src/views/layoutpages/acw/Project.vue
Normal file
@@ -0,0 +1,210 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="projectName"
|
||||
placeholder="项目名称"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['add']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.add.name)"
|
||||
>
|
||||
{{ buttons.add.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<el-table-column
|
||||
prop="projectName"
|
||||
label="项目名称"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="instanceName"
|
||||
label="数据库实例"
|
||||
></el-table-column>
|
||||
<el-table-column prop="version" label="version"></el-table-column>
|
||||
<el-table-column
|
||||
prop="ormFrameEnums"
|
||||
label="ORM框架"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="uiFrameEnums"
|
||||
label="UI框架"
|
||||
></el-table-column>
|
||||
<el-table-column prop="owner" label="项目拥有者"></el-table-column>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['edit']"
|
||||
@click.prevent="handleEdit(buttons.edit.name, row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.edit.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['del']"
|
||||
@click.prevent="handleDel(row.id)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
|
||||
<!-- 编辑组件 -->
|
||||
<project-edit
|
||||
v-if="showDialog"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "acw项目查询与设置",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
add: { name: "添加" },
|
||||
edit: { name: "编辑" },
|
||||
del: { name: "删除" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Mug",
|
||||
name: "ACW项目管理",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import ProjectEdit from "./components/ProjectEdit";
|
||||
import { reactive, toRefs, ref, onMounted, getCurrentInstance } from "vue";
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const rowData = ref(null);
|
||||
const dialogTitle = ref("");
|
||||
const showDialog = ref(false);
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const params = reactive({
|
||||
projectName: "",
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { projectName, size, current, total } = toRefs(params);
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEdit = (title, row = null) => {
|
||||
showDialog.value = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: dialog事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handelDialog = (e) => {
|
||||
showDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
/**删除行数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDel = (id) => {
|
||||
proxy
|
||||
.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
const { code } = await VE_API.system.projectDelete({ id });
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } = await VE_API.system.projectPage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
}
|
||||
};
|
||||
onMounted(async () => {
|
||||
await getDataList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,643 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="服务器名称" prop="instanceName">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="instanceName"
|
||||
placeholder="服务器名称"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-button
|
||||
v-permission="['addInstance']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleEdit(buttons.addInstance.name)"
|
||||
>
|
||||
{{ buttons.addInstance.name }}
|
||||
</el-button>
|
||||
|
||||
<el-row v-if="tableData && tableData.length > 0">
|
||||
<el-col span="8" style="margin-right: 10%">
|
||||
<el-tree
|
||||
:props="resourceProps"
|
||||
:load="loadNode"
|
||||
:data="tableData"
|
||||
@node-click="checkNode"
|
||||
lazy
|
||||
show-checkbox
|
||||
:filter-node-method="filterNode"
|
||||
>
|
||||
<template #default="{ data }">
|
||||
<span class="custom-tree-node">
|
||||
<img
|
||||
v-if="data.type === 'instance'"
|
||||
src="../../../../src/static/redis.png"
|
||||
style="width: 16px; height: 16px"
|
||||
/>
|
||||
<img
|
||||
v-if="data.type === 'database'"
|
||||
src="../../../../src/static/database.png"
|
||||
style="width: 16px; height: 16px"
|
||||
/>
|
||||
<img
|
||||
v-if="data.type === 'key'"
|
||||
src="../../../../src/static/key.png"
|
||||
style="width: 16px; height: 16px"
|
||||
/>
|
||||
<!-- 实例展示 -->
|
||||
<span v-if="data.type === 'instance'">
|
||||
{{ data.name }}
|
||||
</span>
|
||||
<el-button
|
||||
v-if="data.type === 'instance'"
|
||||
v-permission="['editInstance']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="
|
||||
handleEdit(buttons.editInstance.name, data)
|
||||
"
|
||||
>
|
||||
{{ buttons.editInstance.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="data.type === 'instance'"
|
||||
v-permission="['delInstance']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleDel(data.id)"
|
||||
>
|
||||
{{ buttons.delInstance.name }}
|
||||
</el-button>
|
||||
<!-- 数据库展示 -->
|
||||
<span v-if="data.type === 'database'">
|
||||
{{ data.name }} ({{ data.keysNum }})
|
||||
</span>
|
||||
<!-- key展示 -->
|
||||
<span v-if="data.type === 'key'">
|
||||
{{ data.name }}
|
||||
</span>
|
||||
|
||||
<el-button
|
||||
v-if="data.type === 'key'"
|
||||
v-permission="['delKey']"
|
||||
@click.prevent="handleDelKey(data)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.delKey.name }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-col>
|
||||
<el-col
|
||||
span="16"
|
||||
v-if="
|
||||
currentClickRowData &&
|
||||
(currentClickRowData.type === 'database' ||
|
||||
currentClickRowData.type === 'key')
|
||||
"
|
||||
style="position: absolute; right: 20px"
|
||||
>
|
||||
<!-- 搜索key -->
|
||||
<!-- <el-form ref="queryForm" :inline="true" :model="params">-->
|
||||
<!-- <el-form-item label="key" prop="key">-->
|
||||
<!-- <el-input-->
|
||||
<!-- clearable-->
|
||||
<!-- v-model="instanceName"-->
|
||||
<!-- placeholder="key"-->
|
||||
<!-- ></el-input>-->
|
||||
<!-- </el-form-item>-->
|
||||
|
||||
<!-- <el-form-item>-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- @click="onSubmit(params, getDataList)"-->
|
||||
<!-- >-->
|
||||
<!-- {{ buttons.search.name }}-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-button-->
|
||||
<!-- @click="resetForm(queryForm, params, getDataList)"-->
|
||||
<!-- >-->
|
||||
<!-- 重置-->
|
||||
<!-- </el-button>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-form>-->
|
||||
<!-- 展示database 下多有的keys -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: currentShowData.redisInstanceConsoleFindKeysValues,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(
|
||||
val,
|
||||
params,
|
||||
findKeysValues(currentClickRowData.value),
|
||||
),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(
|
||||
val,
|
||||
params,
|
||||
findKeysValues(currentClickRowData.value),
|
||||
),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['addKey']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleKeyEdit({})"
|
||||
>
|
||||
{{ buttons.addKey.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column prop="key" label="key"></el-table-column>
|
||||
<el-table-column
|
||||
prop="value"
|
||||
label="value"
|
||||
></el-table-column>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-button
|
||||
v-permission="['editKey']"
|
||||
@click.prevent="handleKeyEdit(row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.editKey.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['delKey']"
|
||||
@click.prevent="handleDelKey(row)"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.delKey.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
<!-- 展示database 的keys结束 -->
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-empty v-show="tableData.length === 0" />
|
||||
<!-- 列表 -->
|
||||
<!-- <ve-table-->
|
||||
<!-- :table="{-->
|
||||
<!-- data: tableData,-->
|
||||
<!-- }"-->
|
||||
<!-- :pagination="{-->
|
||||
<!-- onSizeChange: (val) =>-->
|
||||
<!-- handleSizeChange(val, params, getDataList),-->
|
||||
<!-- onCurrentChange: (val) =>-->
|
||||
<!-- handleCurrentChange(val, params, getDataList),-->
|
||||
<!-- currentPage: current,-->
|
||||
<!-- pageSize: size,-->
|
||||
<!-- total: total,-->
|
||||
<!-- }"-->
|
||||
<!-- >-->
|
||||
<!-- <template #tool_bar>-->
|
||||
<!-- <el-button-->
|
||||
<!-- v-permission="['add']"-->
|
||||
<!-- size="small"-->
|
||||
<!-- type="primary"-->
|
||||
<!-- @click="handleEdit(buttons.add.name)"-->
|
||||
<!-- >-->
|
||||
<!-- {{ buttons.add.name }}-->
|
||||
<!-- </el-button>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="instanceName"-->
|
||||
<!-- label="服务器名称"-->
|
||||
<!-- ></el-table-column>-->
|
||||
<!-- <el-table-column prop="username" label="登录名"></el-table-column>-->
|
||||
<!-- <el-table-column prop="password" label="登陆密码">-->
|
||||
<!-- <template v-slot="{ row }">-->
|
||||
<!-- <span>-->
|
||||
<!-- {{-->
|
||||
<!-- row.password &&-->
|
||||
<!-- row.password-->
|
||||
<!-- .split("")-->
|
||||
<!-- .fill("*", 1, -1)-->
|
||||
<!-- .join()-->
|
||||
<!-- .replace(/\,/g, "")-->
|
||||
<!-- }}-->
|
||||
<!-- </span>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- <el-table-column prop="host" label="host"></el-table-column>-->
|
||||
<!-- <el-table-column prop="port" label="端口"></el-table-column>-->
|
||||
<!-- <el-table-column prop="status" label="状态"></el-table-column>-->
|
||||
<!-- <el-table-column prop="sort" label="排序"></el-table-column>-->
|
||||
|
||||
<!-- <el-table-column fixed="right" label="操作">-->
|
||||
<!-- <template v-slot:default="{ row }">-->
|
||||
<!-- <el-button-->
|
||||
<!-- v-permission="['edit']"-->
|
||||
<!-- @click.prevent="handleEdit(buttons.edit.name, row)"-->
|
||||
<!-- type="primary"-->
|
||||
<!-- size="small"-->
|
||||
<!-- >-->
|
||||
<!-- {{ buttons.edit.name }}-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-button-->
|
||||
<!-- v-permission="['del']"-->
|
||||
<!-- @click.prevent="handleDel(row.id)"-->
|
||||
<!-- type="danger"-->
|
||||
<!-- size="small"-->
|
||||
<!-- >-->
|
||||
<!-- {{ buttons.del.name }}-->
|
||||
<!-- </el-button>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </ve-table>-->
|
||||
|
||||
<!-- 编辑实例组件 -->
|
||||
<redis-instance-edit
|
||||
v-if="showDialog.instanceEdit"
|
||||
:rowData="rowData"
|
||||
:title="dialogTitle"
|
||||
:showDialog="showDialog.instanceEdit"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
|
||||
<!-- 编辑key -->
|
||||
<el-dialog
|
||||
:title="新增或者修改key"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog.keyEdit"
|
||||
@close="handelKeyDialog($event)"
|
||||
>
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="redisKeyData"
|
||||
ref="formRef"
|
||||
label-width="120px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="数据库的key" prop="redisKeyData.key">
|
||||
<el-input
|
||||
v-model="redisKeyData.key"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="value" prop="redisKeyData.value">
|
||||
<el-input
|
||||
v-model="redisKeyData.value"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="handelKeyDialog(false)">取消</el-button>
|
||||
<el-button type="primary" @click="handelAddKey()"
|
||||
>确定</el-button
|
||||
>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "Redis实例管理",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
addInstance: { name: "添加Redis实例" },
|
||||
addKey: { name: "添加Redis key" },
|
||||
add: { name: "添加实例" },
|
||||
editInstance: { name: "编辑redis实例" },
|
||||
editKey: { name: "编辑Redis key" },
|
||||
delKey: { name: "删除Redis key" },
|
||||
delInstance: { name: "删除Redis实例" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Collection",
|
||||
name: "Redis实例管理",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import redisInstanceEdit from "./components/RedisInstanceEdit.vue";
|
||||
|
||||
import { reactive, toRefs, ref, onMounted, getCurrentInstance } from "vue";
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const rowData = ref(null);
|
||||
const dialogTitle = ref("");
|
||||
const showDialog = ref({});
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const redisKeyData = ref({});
|
||||
|
||||
// 当前node节点对应的数据
|
||||
const currentClickRowData = ref({});
|
||||
|
||||
const currentShowData = ref({}); // 当前展示的所有数据都在这里
|
||||
|
||||
const params = reactive({
|
||||
instanceName: "",
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { instanceName, size, current, total } = toRefs(params);
|
||||
|
||||
/**
|
||||
* 左侧服务器树
|
||||
* @type {Ref<UnwrapRef<*[]>>}
|
||||
*/
|
||||
const leftServerTree = ref([]);
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleEdit = (title, row = null) => {
|
||||
showDialog.value.instanceEdit = true;
|
||||
dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
};
|
||||
/**
|
||||
* 编辑key
|
||||
*/
|
||||
const handleKeyEdit = (row) => {
|
||||
showDialog.value.keyEdit = true;
|
||||
redisKeyData.value = row;
|
||||
};
|
||||
/**
|
||||
* 删除key
|
||||
*/
|
||||
const handleDelKey = (row) => {
|
||||
VE_API.system.redisInstanceConsoleRemoveKey(row);
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: dialog事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handelDialog = (e) => {
|
||||
showDialog.value.instanceEdit = e;
|
||||
getDataList();
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
const handelKeyDialog = (e) => {
|
||||
showDialog.value.keyEdit = e;
|
||||
getDataList();
|
||||
};
|
||||
/**
|
||||
* 添加key
|
||||
*/
|
||||
const handelAddKey = async () => {
|
||||
redisKeyData.value.instanceId = currentClickRowData.value.instanceId;
|
||||
redisKeyData.value.database = currentClickRowData.value.database;
|
||||
|
||||
const { code } = await VE_API.system.redisInstanceConsoleSetKey(
|
||||
redisKeyData.value,
|
||||
);
|
||||
if (code === 0) {
|
||||
handelKeyDialog(false);
|
||||
}
|
||||
};
|
||||
/**删除行数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleDel = (id) => {
|
||||
proxy
|
||||
.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
const { code } = await VE_API.system.redisInstanceDelete({ id });
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } = await VE_API.system.redisInstancePage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
|
||||
record.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.name = item.instanceName;
|
||||
item.value = item.id;
|
||||
item.instanceId = item.id;
|
||||
});
|
||||
tableData.value = record;
|
||||
leftServerTree.value = record;
|
||||
}
|
||||
};
|
||||
onMounted(async () => {
|
||||
await getDataList();
|
||||
// maxHeight(pagination, queryForm, toolBar, ve_max_height);
|
||||
});
|
||||
|
||||
const resourceProps = {
|
||||
label: "name",
|
||||
children: "children",
|
||||
isLeaf: "leaf",
|
||||
};
|
||||
|
||||
const loadNode = async (resourceNode, resolve) => {
|
||||
console.log(resourceNode);
|
||||
if (resourceNode.level === 0) {
|
||||
return resolve([]);
|
||||
}
|
||||
|
||||
resourceNode.loaded = true;
|
||||
const resourceNodeData = resourceNode.data;
|
||||
currentClickRowData.value = resourceNodeData.data;
|
||||
if (resourceNodeData.isFile) {
|
||||
return resolve([]);
|
||||
}
|
||||
console.log(resourceNodeData);
|
||||
|
||||
let res;
|
||||
if (resourceNodeData) {
|
||||
if (resourceNodeData && resourceNodeData.type === "instance") {
|
||||
// 查询database
|
||||
res = await VE_API.system.redisInstanceConsoleFindDataBases({
|
||||
instanceId: resourceNodeData.id,
|
||||
});
|
||||
if (res.code === 0) {
|
||||
res.data.record.map((item) => {
|
||||
item.name = item.database;
|
||||
});
|
||||
}
|
||||
} else if (resourceNodeData.type === "database") {
|
||||
// 查询key
|
||||
res = await VE_API.system.redisInstanceConsoleFindKeys({
|
||||
instanceId: resourceNodeData.instanceId,
|
||||
database: resourceNodeData.database,
|
||||
});
|
||||
if (res.code === 0) {
|
||||
res.data.record.map((item) => {
|
||||
item.name = item.key;
|
||||
});
|
||||
}
|
||||
} else if (resourceNodeData.type === "key") {
|
||||
// 查询数据
|
||||
}
|
||||
if (res) {
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
if (data == null) {
|
||||
return resolve([]);
|
||||
}
|
||||
// resourceNode.childNodes = data;
|
||||
console.log(resourceNode);
|
||||
return resolve(data.record);
|
||||
}
|
||||
} else {
|
||||
return resolve([]);
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 点击 node节点
|
||||
*/
|
||||
const checkNode = (node) => {
|
||||
currentClickRowData.value = node;
|
||||
if (currentClickRowData.value.type === "database") {
|
||||
findKeysValues(currentClickRowData.value);
|
||||
}
|
||||
findKeyValue(currentClickRowData.value);
|
||||
|
||||
console.log(currentClickRowData.value);
|
||||
};
|
||||
|
||||
/**
|
||||
* 过滤node
|
||||
* @param node
|
||||
*/
|
||||
const filterNode = (value, tree) => {
|
||||
if (!value) return true;
|
||||
return tree.label.includes(value);
|
||||
};
|
||||
/**
|
||||
* 获取所有的keys
|
||||
* @param currentClickRowData
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const findKeysValues = async (currentClickRowData) => {
|
||||
if (currentClickRowData.type === "database") {
|
||||
const res =
|
||||
await VE_API.system.redisInstanceConsoleFindKeysValues(
|
||||
currentClickRowData,
|
||||
);
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
currentShowData.value.redisInstanceConsoleFindKeysValues =
|
||||
data.record;
|
||||
console.log(currentShowData.value);
|
||||
} else {
|
||||
console.log(res);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取key对应的value
|
||||
* @param currentClickRowData
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const findKeyValue = async (currentClickRowData) => {
|
||||
if (currentClickRowData.type === "key") {
|
||||
const res =
|
||||
await VE_API.system.redisInstanceConsoleFindKeyValue(
|
||||
currentClickRowData,
|
||||
);
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
currentShowData.value.redisInstanceConsoleFindKeysValues =
|
||||
data.record;
|
||||
console.log(currentShowData.value);
|
||||
} else {
|
||||
console.log(res);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化加载数据
|
||||
*/
|
||||
onMounted(async () => {
|
||||
await getDataList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.prefix {
|
||||
color: var(--el-color-primary);
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.prefix.is-leaf {
|
||||
color: var(--el-color-success);
|
||||
}
|
||||
</style>
|
||||
327
wu-lazy-cloud-network-ui/src/views/layoutpages/acw/SQLAudit.vue
Normal file
@@ -0,0 +1,327 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form ref="queryForm" :inline="true" :model="params">
|
||||
<el-form-item label="数据库实例" property="instanceId">
|
||||
<el-select
|
||||
v-model="params.instanceId"
|
||||
@change="getSchemaList"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库名" prop="schemaNameId">
|
||||
<el-select
|
||||
clearable
|
||||
v-model="params.schemaNameId"
|
||||
placeholder="数据库名"
|
||||
@change="getDataList"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaNameList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="表名" prop="tableName">
|
||||
<el-input
|
||||
clearable
|
||||
v-model="tableName"
|
||||
placeholder="表名"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="sql类型" prop="sqlType">
|
||||
<el-select
|
||||
v-model="sqlType"
|
||||
placeholder="sql类型"
|
||||
@change="getDataList"
|
||||
>
|
||||
<el-option label="查询" value="SELECT" />
|
||||
<el-option label="更新" value="UPDATE" />
|
||||
<el-option label="插入" value="INSERT" />
|
||||
<el-option label="删除" value="DELETE" />
|
||||
<el-option label="创建" value="CREATE" />
|
||||
<el-option label="DDL" value="DDL" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="onSubmit(params, getDataList)"
|
||||
>
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm(queryForm, params, getDataList)">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
@selectionChange="handleSelectionChange"
|
||||
>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
v-permission="['batchDel']"
|
||||
size="small"
|
||||
type="danger"
|
||||
@click="batchDelSqlAudit"
|
||||
>
|
||||
{{ buttons.batchDel.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['batchExport']"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="batchExportSqlAudit"
|
||||
>
|
||||
{{ buttons.batchExport.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="id" label="sql执行ID" show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="applicationName"
|
||||
label="应用名称"
|
||||
></el-table-column>
|
||||
<el-table-column prop="instanceId" label="实例ID">
|
||||
<template v-slot="scope">
|
||||
<el-select
|
||||
v-model="scope.row.instanceId"
|
||||
placeholder="实例ID"
|
||||
filterable
|
||||
:disabled="true"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sqlType" label="执行类型"></el-table-column>
|
||||
<el-table-column prop="schema" label="数据库"> </el-table-column>
|
||||
<el-table-column prop="ip" label="ip"></el-table-column>
|
||||
<el-table-column
|
||||
prop="tableList"
|
||||
label="操作的表"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="executeSql"
|
||||
label="执行sql"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="requestId"
|
||||
label="请求ID"
|
||||
show-overflow-tooltip
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
label="创建时间"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
label="更新时间"
|
||||
></el-table-column>
|
||||
</ve-table>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import acwMenu from "@/views/layoutpages/acw/AcwMenu";
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "SQL审计",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
batchDel: { name: "批量删除SQL审计" },
|
||||
batchExport: { name: "批量导出" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "DataLine",
|
||||
name: "SQL审计",
|
||||
parentMenu: acwMenu,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import { reactive, toRefs, ref, onMounted, getCurrentInstance } from "vue";
|
||||
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
onSubmit,
|
||||
resetForm,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
const schemaNameList = ref(null);
|
||||
const serverList = ref(null);
|
||||
const batchSelectSQLAuditList = ref(null);
|
||||
const params = reactive({
|
||||
tableName: "",
|
||||
schemaNameId: "",
|
||||
instanceId: "",
|
||||
status: true,
|
||||
sqlType: "",
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { tableName, size, sqlType, current, total } = toRefs(params);
|
||||
|
||||
/**
|
||||
* 全选事件
|
||||
*
|
||||
*/
|
||||
const handleSelectionChange = (val) => {
|
||||
batchSelectSQLAuditList.value = val;
|
||||
console.log(batchSelectSQLAuditList.value);
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量导出
|
||||
*/
|
||||
const batchExportSqlAudit = async () => {
|
||||
let res = await VE_API.system.slqAuditExport(params, {
|
||||
responseType: "blob",
|
||||
});
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
};
|
||||
/**
|
||||
*
|
||||
* 批量删除
|
||||
*/
|
||||
const batchDelSqlAudit = () => {
|
||||
if (batchSelectSQLAuditList.value.length == 0) {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "请选择一个SQL记录",
|
||||
});
|
||||
return;
|
||||
}
|
||||
proxy
|
||||
.$confirm("此操作将批量永久删除该数据, 是否继续?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
let ids = batchSelectSQLAuditList.value.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
const { code } = await VE_API.system.batchDeleteSlqAudit(ids);
|
||||
if (code === 0) {
|
||||
getDataList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
proxy.$message({
|
||||
type: "info",
|
||||
message: "已取消删除",
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
const { code, data } = await VE_API.system.slqAuditPage(params);
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取 数据库
|
||||
* @param instanceId 数据库实例ID
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getSchemaList = async (instanceId) => {
|
||||
schemaNameList.value = [];
|
||||
let res;
|
||||
if (instanceId == null || instanceId === "") {
|
||||
return;
|
||||
} else {
|
||||
res = await VE_API.system.schemaList({
|
||||
instanceId,
|
||||
});
|
||||
}
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaNameList.value = data;
|
||||
}
|
||||
await getDataList();
|
||||
};
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getServerInstanceList();
|
||||
await getDataList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- <span>{{ rowData }}</span> -->
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select
|
||||
v-model="instanceId"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
@change="(val) => getSchemaList(val)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="数据库库名" prop="schemaName">
|
||||
<el-select
|
||||
v-model="schema"
|
||||
filterable
|
||||
placeholder="数据库实例"
|
||||
@change="findInstanceSchemaColumnList"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="忽略解析字段" prop="ignoreFieldList">
|
||||
<el-select
|
||||
v-model="ignoreFieldList"
|
||||
filterable
|
||||
multiple
|
||||
placeholder="忽略解析字段"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableColumnList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
<span style="float: left"
|
||||
>{{ item.label }}【{{ item.columnComment }}】</span
|
||||
>
|
||||
<span
|
||||
style="
|
||||
float: right;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 13px;
|
||||
"
|
||||
>{{ item.tableName }}</span
|
||||
></el-option
|
||||
>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="解析阀值" prop="relationThreshold">
|
||||
<el-input
|
||||
v-model="relationThreshold"
|
||||
placeholder="500"
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
onMounted,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
} from "vue";
|
||||
const rules = {
|
||||
databaseSchemaId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入数据库库名",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
instanceId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入数据库服务器",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
schema: "",
|
||||
instanceId: "",
|
||||
relationThreshold: 99,
|
||||
ignoreFieldList: [],
|
||||
});
|
||||
const { schema, instanceId, relationThreshold, ignoreFieldList } = toRefs(form);
|
||||
const serverList = ref(null);
|
||||
const schemaList = ref(null);
|
||||
|
||||
const tableColumnList = ref([]);
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((schema.value = rowData.value.schema),
|
||||
(instanceId.value = rowData.value.instanceId),
|
||||
(relationThreshold.value = rowData.value.relationThreshold));
|
||||
|
||||
onMounted(async () => {
|
||||
getInstanceList();
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取当前表对应的字段
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const findInstanceSchemaColumnList = async () => {
|
||||
// 设置表备注
|
||||
tableColumnList.value = [];
|
||||
let res = await VE_API.system.findInstanceSchemaColumnList({
|
||||
instanceId: instanceId.value,
|
||||
schemaName: schema.value,
|
||||
});
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.columnName;
|
||||
item.value = item.columnName;
|
||||
});
|
||||
tableColumnList.value = data ? data : [];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取数据库实例
|
||||
*/
|
||||
const getInstanceList = () => {
|
||||
// 查询数据库实例
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
const getSchemaList = (databaseInstance = null) => {
|
||||
console.log(databaseInstance);
|
||||
// 查询数据schema信息
|
||||
VE_API.system
|
||||
.schemaList({
|
||||
instanceId: instanceId.value,
|
||||
})
|
||||
.then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
console.log(form);
|
||||
res =
|
||||
await VE_API.system.acwTableAssociationRelationAnalysisSchema(
|
||||
form,
|
||||
);
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,358 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- <span>{{ rowData }}</span> -->
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="数据库实例ID" prop="instanceId">
|
||||
<el-select
|
||||
v-model="instanceId"
|
||||
@change="getSchemaList"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库实例schema" prop="schema">
|
||||
<el-select
|
||||
v-model="schema"
|
||||
placeholder="数据库名"
|
||||
@change="getTableList"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="原始表" prop="sourceTable">
|
||||
<el-select
|
||||
v-model="sourceTable"
|
||||
placeholder="数据库表名"
|
||||
@change="getDatabaseTablesColumnList(sourceTable)"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="原始表字段" prop="sourceColumn">
|
||||
<el-select
|
||||
v-model="sourceColumn"
|
||||
placeholder="原始表字段"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableColumnList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关系表" prop="relationTable">
|
||||
<el-select
|
||||
v-model="relationTable"
|
||||
placeholder="关系表"
|
||||
@change="getDatabaseTablesColumnList(relationTable)"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关系表字段" prop="relationTableColumn">
|
||||
<el-select
|
||||
v-model="relationTableColumn"
|
||||
placeholder="关系表字段"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableColumnList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型(1:自动产生的、2:手动添加的)" prop="type">
|
||||
<el-select
|
||||
v-model="type"
|
||||
placeholder="类型(1:自动产生的、2:手动添加的)"
|
||||
clearable
|
||||
>
|
||||
<el-option label="自动产生的" :value="1" />
|
||||
<el-option label="手动添加的" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
|
||||
const rules = {
|
||||
instanceId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入服务器名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
schema: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入账户",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
sourceTable: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入密码",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
sourceColumn: [
|
||||
{
|
||||
required: true,
|
||||
message: "host不能为空",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
relationTable: [
|
||||
{
|
||||
required: true,
|
||||
message: "端口不能为空",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
relationTableColumn: [
|
||||
{
|
||||
required: true,
|
||||
message: "driverClassName",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
instanceId: "",
|
||||
schema: "",
|
||||
sourceTable: "",
|
||||
sourceColumn: "",
|
||||
relationTable: "",
|
||||
relationTableColumn: "",
|
||||
type: 2,
|
||||
});
|
||||
const {
|
||||
instanceId,
|
||||
schema,
|
||||
sourceTable,
|
||||
sourceColumn,
|
||||
relationTable,
|
||||
relationTableColumn,
|
||||
type,
|
||||
} = toRefs(form);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((instanceId.value = rowData.value.instanceId),
|
||||
(schema.value = rowData.value.schema),
|
||||
(sourceTable.value = rowData.value.sourceTable),
|
||||
(sourceColumn.value = rowData.value.sourceColumn),
|
||||
(relationTable.value = rowData.value.relationTable),
|
||||
(relationTableColumn.value = rowData.value.relationTableColumn),
|
||||
(type.value = rowData.value.type));
|
||||
|
||||
const schemaList = ref(null);
|
||||
const tableList = ref(null);
|
||||
const tableColumnList = ref([]);
|
||||
|
||||
const serverList = ref(null);
|
||||
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 选择数据库实例
|
||||
* @param serverInstanceId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getSchemaList = async () => {
|
||||
// 查询数据库
|
||||
let res = await VE_API.system.schemaList({
|
||||
instanceId: instanceId.value,
|
||||
});
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
if (res.data) {
|
||||
res.data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaList.value = res.data ? res.data : [];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取 数据库表
|
||||
* @param instanceId 数据库实例ID
|
||||
* @param schemaName 数据库名称
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getTableList = async () => {
|
||||
let res;
|
||||
if (instanceId.value == null) {
|
||||
return;
|
||||
} else {
|
||||
res = await VE_API.system.tableList({
|
||||
instanceId: instanceId.value,
|
||||
schemaName: schema.value,
|
||||
});
|
||||
}
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
if (data) {
|
||||
data.map((item) => {
|
||||
item.label = item.tableName;
|
||||
item.value = item.tableName;
|
||||
});
|
||||
tableList.value = data;
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取当前表对应的字段
|
||||
* @param tableIds
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getDatabaseTablesColumnList = async (table) => {
|
||||
// 设置表备注
|
||||
tableColumnList.value = [];
|
||||
let res = await VE_API.system.findDatabaseTableColumnList({
|
||||
instanceId: instanceId.value,
|
||||
schemaName: schema.value,
|
||||
tableName: table,
|
||||
});
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.columnName;
|
||||
item.value = item.columnName;
|
||||
});
|
||||
tableColumnList.value = data ? data : [];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 页面初始化方法
|
||||
*/
|
||||
onMounted(async () => {
|
||||
await getServerInstanceList();
|
||||
});
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value === "添加") {
|
||||
res =
|
||||
await VE_API.system.acwTableAssociationRelationStory(form);
|
||||
} else {
|
||||
res = await VE_API.system.acwTableAssociationRelationStory({
|
||||
id: rowData.value.id,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,590 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
:width="'80%'"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- <span>{{ rowData }}</span> -->
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="应用名称" prop="applicationId">
|
||||
<el-select
|
||||
v-model="applicationId"
|
||||
placeholder="应用名称"
|
||||
@change="changeApplication"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in applicationList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="应用表" prop="tableNameList">
|
||||
<el-select
|
||||
v-model="tableNameList"
|
||||
placeholder="应用表"
|
||||
@change="changeTable"
|
||||
multiple
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="接口分组" prop="tag">
|
||||
<el-input v-model="tag" placeholder="" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="接口描述" prop="description">
|
||||
<el-input
|
||||
v-model="description"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="接口类型" prop="method">
|
||||
<el-select v-model="method" placeholder="" clearable>
|
||||
<el-option label="GET" value="GET" />
|
||||
<el-option label="HEAD" value="HEAD" />
|
||||
<el-option label="POST" value="POST" />
|
||||
<el-option label="PUT" value="PUT" />
|
||||
<el-option label="PATCH" value="PATCH" />
|
||||
<el-option label="DELETE" value="DELETE" />
|
||||
<el-option label="OPTIONS" value="OPTIONS" />
|
||||
<el-option label="TRACE" value="TRACE" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="接口地址" prop="path">
|
||||
<el-input v-model="path" placeholder="" clearable></el-input>
|
||||
</el-form-item>
|
||||
<div style="text-align: center" class="api_transfer_result">
|
||||
<el-transfer
|
||||
v-model="apiFactoryTransferData.leftValue"
|
||||
style="text-align: left; display: inline-block"
|
||||
filterable
|
||||
:left-default-checked="[2, 3]"
|
||||
:right-default-checked="[1]"
|
||||
:titles="['原始数据', '接口返回数据']"
|
||||
:button-texts="['移除返回数据', '添加返回数据']"
|
||||
:data="tableColumnList"
|
||||
:props="{ key: 'value', label: 'desc' }"
|
||||
:format="{
|
||||
noChecked: '${total}',
|
||||
hasChecked: '${checked}/${total}',
|
||||
}"
|
||||
@change="handleTransferChange"
|
||||
>
|
||||
<template #default="{ option }">
|
||||
<span style="float: left"
|
||||
>{{ option.label }} 【{{ option.columnComment }}】
|
||||
</span>
|
||||
<span style="float: right">
|
||||
{{ option.tableName }}
|
||||
</span>
|
||||
</template>
|
||||
<template #left-footer>
|
||||
<el-button class="transfer-footer" size="small"
|
||||
>Operation</el-button
|
||||
>
|
||||
</template>
|
||||
<template #right-footer>
|
||||
<el-button class="transfer-footer" size="small"
|
||||
>Operation</el-button
|
||||
>
|
||||
</template>
|
||||
</el-transfer>
|
||||
</div>
|
||||
<div>
|
||||
<span>路径参数</span>
|
||||
<el-button
|
||||
@click="addItem(pathParamColumnIdList, 'PATH_PARAM_TYPE')"
|
||||
type="primary"
|
||||
style="float: right"
|
||||
>增加
|
||||
</el-button>
|
||||
<el-empty v-show="pathParamColumnIdList.length === 0">
|
||||
</el-empty>
|
||||
<el-form-item
|
||||
v-for="(it, index) in pathParamColumnIdList"
|
||||
:key="index"
|
||||
>
|
||||
<el-select
|
||||
v-model="pathParamColumnIdList[index].columnName"
|
||||
placeholder="路径参数选择"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableColumnList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
<span style="float: left"
|
||||
>{{ item.label }}【{{
|
||||
item.columnComment
|
||||
}}】</span
|
||||
>
|
||||
<span
|
||||
style="
|
||||
float: right;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 13px;
|
||||
"
|
||||
>{{ item.tableName }}</span
|
||||
></el-option
|
||||
>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="pathParamColumnIdList[index].term"
|
||||
placeholder="条件(大于、等于、模糊)"
|
||||
>
|
||||
<el-option label="小等于" value="<" />
|
||||
<el-option label="等于" value="=" />
|
||||
<el-option label="大于等于" value=">=" />
|
||||
<el-option label="小于等于" value="<=" />
|
||||
<el-option label="不等于" value="!=" />
|
||||
<el-option label="模糊查询" value="like" />
|
||||
<el-option label="in" value="in" />
|
||||
</el-select>
|
||||
<el-button
|
||||
@click="removeItem(pathParamColumnIdList, index)"
|
||||
type="danger"
|
||||
style="float: right"
|
||||
>删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div>
|
||||
<span>请求参数</span>
|
||||
<el-button
|
||||
@click="
|
||||
addItem(requestParamColumnIdList, 'REQUEST_PARAM_TYPE')
|
||||
"
|
||||
style="float: right"
|
||||
type="primary"
|
||||
>增加
|
||||
</el-button>
|
||||
<el-empty
|
||||
v-show="requestParamColumnIdList.length === 0"
|
||||
></el-empty>
|
||||
<el-form-item
|
||||
v-for="(it, index) in requestParamColumnIdList"
|
||||
:key="index"
|
||||
>
|
||||
<el-select
|
||||
v-model="requestParamColumnIdList[index].columnName"
|
||||
placeholder="请求参数选择"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableColumnList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
<span style="float: left"
|
||||
>{{ item.label }}【{{
|
||||
item.columnComment
|
||||
}}】</span
|
||||
>
|
||||
<span
|
||||
style="
|
||||
float: right;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 13px;
|
||||
"
|
||||
>{{ item.tableName }}</span
|
||||
></el-option
|
||||
>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="requestParamColumnIdList[index].term"
|
||||
placeholder="条件(大于、等于、模糊)"
|
||||
>
|
||||
<el-option label="小等于" value="<" />
|
||||
<el-option label="等于" value="=" />
|
||||
<el-option label="大于等于" value=">=" />
|
||||
<el-option label="小于等于" value="<=" />
|
||||
<el-option label="不等于" value="!=" />
|
||||
<el-option label="模糊查询" value="like" />
|
||||
<el-option label="in" value="in" />
|
||||
</el-select>
|
||||
<el-button
|
||||
@click="removeItem(requestParamColumnIdList, index)"
|
||||
style="float: right"
|
||||
type="danger"
|
||||
>删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div>
|
||||
<span>请求体参数</span>
|
||||
<el-button
|
||||
@click="
|
||||
addItem(
|
||||
requestBodyParamColumnIdList,
|
||||
'REQUEST_BODY_PARAM_TYPE',
|
||||
)
|
||||
"
|
||||
style="float: right"
|
||||
type="primary"
|
||||
>增加
|
||||
</el-button>
|
||||
<el-empty
|
||||
v-show="requestBodyParamColumnIdList.length === 0"
|
||||
></el-empty>
|
||||
<el-form-item
|
||||
v-for="(it, index) in requestBodyParamColumnIdList"
|
||||
:key="index"
|
||||
>
|
||||
<el-select
|
||||
v-model="requestBodyParamColumnIdList[index].columnName"
|
||||
placeholder="请选择"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableColumnList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
<span style="float: left"
|
||||
>{{ item.label }}【{{
|
||||
item.columnComment
|
||||
}}】</span
|
||||
>
|
||||
<span
|
||||
style="
|
||||
float: right;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 13px;
|
||||
"
|
||||
>{{ item.tableName }}</span
|
||||
></el-option
|
||||
>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="requestBodyParamColumnIdList[index].term"
|
||||
placeholder="条件(大于、等于、模糊)"
|
||||
>
|
||||
<el-option label="大于" value=">" />
|
||||
<el-option label="小等于" value="<" />
|
||||
<el-option label="等于" value="=" />
|
||||
<el-option label="大于等于" value=">=" />
|
||||
<el-option label="小于等于" value="<=" />
|
||||
<el-option label="不等于" value="!=" />
|
||||
<el-option label="模糊查询" value="like" />
|
||||
<el-option label="in" value="in" />
|
||||
</el-select>
|
||||
<el-button
|
||||
@click="removeItem(requestBodyParamColumnIdList, index)"
|
||||
type="danger"
|
||||
style="float: right"
|
||||
>删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
|
||||
const rules = {
|
||||
applicationId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择应用名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
tableNameList: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择表",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
tag: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入接口分组",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
description: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入接口描述",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
method: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择接口类型",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
path: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择接口地址",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const applicationList = ref(null);
|
||||
const tableList = ref(null);
|
||||
const tableColumnList = ref([]);
|
||||
|
||||
// api 工厂穿梭数据
|
||||
const apiFactoryTransferData = ref({
|
||||
leftValue: [],
|
||||
});
|
||||
const requestBodyParamColumnIdList = ref([]);
|
||||
|
||||
const pathParamColumnIdList = ref([]);
|
||||
|
||||
const requestParamColumnIdList = ref([]);
|
||||
|
||||
const application = ref();
|
||||
|
||||
const form = reactive({
|
||||
applicationId: "",
|
||||
tableNameList: [],
|
||||
tag: "",
|
||||
description: "",
|
||||
method: "",
|
||||
path: "",
|
||||
apiParamQoList: [],
|
||||
});
|
||||
const {
|
||||
applicationId,
|
||||
tableNameList,
|
||||
tag,
|
||||
description,
|
||||
method,
|
||||
path,
|
||||
apiParamQoList,
|
||||
} = toRefs(form);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((applicationId.value = rowData.value.applicationId),
|
||||
(tag.value = rowData.value.tag),
|
||||
(description.value = rowData.value.description),
|
||||
(method.value = rowData.value.method),
|
||||
(path.value = rowData.value.path),
|
||||
(apiParamQoList.value = rowData.value.apiParamQoList),
|
||||
(tableNameList.value = rowData.value.tableNameList));
|
||||
|
||||
const handleTransferChange = (transferItem) => {
|
||||
console.log(transferItem);
|
||||
};
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
let apiParamQoList = [];
|
||||
apiParamQoList = apiParamQoList.concat(pathParamColumnIdList.value);
|
||||
apiParamQoList = apiParamQoList.concat(requestBodyParamColumnIdList.value);
|
||||
apiParamQoList = apiParamQoList.concat(requestParamColumnIdList.value);
|
||||
apiParamQoList = JSON.parse(JSON.stringify(apiParamQoList));
|
||||
form.apiParamQoList = apiParamQoList;
|
||||
form.apiResultList = apiFactoryTransferData.value.leftValue;
|
||||
console.log(apiFactoryTransferData);
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value === "添加") {
|
||||
res = await VE_API.system.apiAdd(form);
|
||||
} else {
|
||||
res = await VE_API.system.apiEdit({
|
||||
id: rowData.value.id,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
onMounted(async () => {
|
||||
VE_API.system.applicationList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.applicationName;
|
||||
item.value = item.applicationId;
|
||||
});
|
||||
applicationList.value = res.data ? res.data : [];
|
||||
|
||||
let application = res.data.find(
|
||||
(item) => item.applicationId === applicationId.value,
|
||||
);
|
||||
if (application) {
|
||||
findTable(application.applicationId);
|
||||
findTableColumn(form.tableNameList);
|
||||
}
|
||||
});
|
||||
if (apiParamQoList.value !== null && apiParamQoList.value.length > 0) {
|
||||
pathParamColumnIdList.value = apiParamQoList.value.filter(
|
||||
(item) => item.type === "PATH_PARAM_TYPE",
|
||||
);
|
||||
requestBodyParamColumnIdList.value = apiParamQoList.value.filter(
|
||||
(item) => item.type === "REQUEST_BODY_PARAM_TYPE",
|
||||
);
|
||||
requestParamColumnIdList.value = apiParamQoList.value.filter(
|
||||
(item) => item.type === "REQUEST_PARAM_TYPE",
|
||||
);
|
||||
}
|
||||
// 选择字段列
|
||||
await findTableColumn(tableNameList);
|
||||
});
|
||||
|
||||
const changeApplication = (applicationId) => {
|
||||
let applicationOne = applicationList.value.find(
|
||||
(item) => item.applicationId === applicationId,
|
||||
);
|
||||
application.value = applicationOne;
|
||||
console.log(applicationOne);
|
||||
findTable(applicationOne.applicationId);
|
||||
};
|
||||
|
||||
const changeTable = (tableNameList) => {
|
||||
if (tableNameList == null || tableNameList.length === 0) {
|
||||
return;
|
||||
}
|
||||
findTableColumn(tableNameList);
|
||||
};
|
||||
|
||||
const findTable = async (applicationId) => {
|
||||
if (null == applicationId) return;
|
||||
VE_API.system
|
||||
.applicationFindTables({ applicationId: applicationId })
|
||||
.then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.tableName;
|
||||
item.value = item.tableName;
|
||||
});
|
||||
tableList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
const findTableColumn = async (tableNameList) => {
|
||||
console.log(tableNameList);
|
||||
console.log(application.value);
|
||||
if (
|
||||
tableNameList === undefined ||
|
||||
tableNameList.length === 0 ||
|
||||
tableNameList.length === undefined ||
|
||||
application.value === undefined
|
||||
) {
|
||||
return;
|
||||
}
|
||||
let tableNames = tableNameList.join();
|
||||
VE_API.system
|
||||
.databaseTablesColumnList({
|
||||
instanceId: application.value.instanceId,
|
||||
schemaName: application.value.schemaName,
|
||||
tableNameList: tableNames,
|
||||
})
|
||||
.then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.columnName;
|
||||
item.value = item.columnName;
|
||||
});
|
||||
tableColumnList.value = res.data ? res.data : [];
|
||||
});
|
||||
tableNameList.value = tableNameList;
|
||||
console.log(tableColumnList);
|
||||
};
|
||||
|
||||
const addItem = (paramColumnList, type = null) => {
|
||||
// 1。这里为什么改变list的大小就能实现动态增加呢?因为 el-form-item 遍历的是 list,list 中的每一项都是一个 el-form-item
|
||||
// 也就是说因为刚开始 list:[{"oneId":''}] 中,只有一个对象,所以才会只出现一个 el-form-item
|
||||
// 不信可以自己在初始化时 list 中多加入几个对象进行尝试(一定要理解,这里 list 集合的大小与 el-form-item 之间的关系)
|
||||
// 2、第二个问题:el-form-item 是动态增加了,但是如果 el-select 那里写的是 v-model="oneId" 呢?会发生什么?结果你会发现,只要增加一项 el-form-item ,每一项绑定的值都是你所选中的那一个值.为什么呢?因为每一项的 el-option的 :value 值都绑定在 el-select 的 v-model 上,但这是一个全局唯一值,当下一个 el-form-item 产生后,它里面的 el-select 中绑定的 v-model 还是那个 oneId 的值,因此才会出现这样的问题.好了,我们既然找到了原因,那就要来解决一下了,怎么解决呢?很简单:因为我前面说了,每一个 list 的遍历对象,都是一项 el-form-item,即 el-form-item 项数是和 list 的下标(里面存的对象的索引下标)相关联的,而这个下标,在每一个 el-form-item 中肯定是不一样的,因此我们只需要将 oneId 与这个 下标(即此处的 index) 发生关系即可,因此我们这里将 oneId 声明为了一个数组,当你每选中一个 option 时,都将这个 option 的value放入 oneId[当前el-form-item项数下标] 数组中
|
||||
console.log(type);
|
||||
console.log(pathParamColumnIdList.value);
|
||||
console.log(requestBodyParamColumnIdList.value);
|
||||
console.log(requestParamColumnIdList.value);
|
||||
if ("PATH_PARAM_TYPE" === type) {
|
||||
pathParamColumnIdList.value.push({ type: type });
|
||||
} else if ("REQUEST_BODY_PARAM_TYPE" === type) {
|
||||
requestBodyParamColumnIdList.value.push({ type: type });
|
||||
} else if ("REQUEST_PARAM_TYPE" === type) {
|
||||
requestParamColumnIdList.value.push({ type: type });
|
||||
}
|
||||
|
||||
// paramColumnList.push({ type: type });
|
||||
};
|
||||
|
||||
const removeItem = (paramColumnList, index) => {
|
||||
// 删除时,我们带两个参数,这个 it 可用可不用,因为我当时只是想看到删除的这个对象的信息,故而带上了; index 是 list 中该对象对应的下标,也是 el-form-item 的项数
|
||||
// 根据这个 index 下标删除 list 中 的该对象
|
||||
paramColumnList.splice(index, 1);
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
/* 必需有scoped */
|
||||
.api_transfer_result >>> .el-transfer-panel {
|
||||
width: 450px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,202 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="项目名" prop="projectId">
|
||||
<el-select
|
||||
v-model="projectId"
|
||||
placeholder="项目名"
|
||||
@change="changeProject"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in projectList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
:serverId="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库" prop="schemaName">
|
||||
<el-select v-model="schemaName" placeholder="数据库" clearable>
|
||||
<el-option
|
||||
v-for="item in serverSchemaList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="应用名" prop="applicationName">
|
||||
<el-input
|
||||
v-model="applicationName"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
const rules = {
|
||||
projectId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入选择项目",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
schemaName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入选择数据库",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
applicationName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入应用名",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const projectList = ref(null);
|
||||
const serverSchemaList = ref(null);
|
||||
|
||||
const form = reactive({
|
||||
applicationName: "",
|
||||
projectId: "",
|
||||
applicationId: "",
|
||||
instanceId: "",
|
||||
schemaName: "",
|
||||
});
|
||||
const { projectId, applicationName, applicationId, instanceId, schemaName } =
|
||||
toRefs(form);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((projectId.value = rowData.value.projectId),
|
||||
(applicationId.value = rowData.value.applicationId),
|
||||
(instanceId.value = rowData.value.instanceId),
|
||||
(schemaName.value = rowData.value.schemaName),
|
||||
(applicationName.value = rowData.value.applicationName));
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value === "添加") {
|
||||
res = await VE_API.system.applicationAdd(form);
|
||||
} else {
|
||||
res = await VE_API.system.applicationEdit({
|
||||
applicationId: rowData.value.applicationId,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
onMounted(async () => {
|
||||
VE_API.system.projectList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.projectName;
|
||||
item.value = item.id;
|
||||
});
|
||||
projectList.value = res.data ? res.data : [];
|
||||
});
|
||||
});
|
||||
const findSchema = async (instanceId = null) => {
|
||||
if (instanceId == null) {
|
||||
return;
|
||||
}
|
||||
// 查询数据库
|
||||
let res = await VE_API.system.schemaList({
|
||||
instanceId,
|
||||
});
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
res.data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
serverSchemaList.value = res.data ? res.data : [];
|
||||
// databaseSchemaId.value = serverSchemaList.value[0].id;
|
||||
}
|
||||
};
|
||||
const changeProject = (projectId) => {
|
||||
console.log(projectId);
|
||||
if (projectId) {
|
||||
let project = projectList.value.find((item) => item.id === projectId);
|
||||
findSchema(project.instanceId);
|
||||
} else {
|
||||
serverSchemaList.value = [];
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- <span>{{ rowData }}</span> -->
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select
|
||||
v-model="instanceId"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
const rules = {
|
||||
instanceId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择数据库实例",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
|
||||
const serverList = ref(null);
|
||||
const form = reactive({
|
||||
instanceId: "",
|
||||
});
|
||||
const { instanceId } = toRefs(form);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value && (instanceId.value = rowData.value.instanceId);
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
res = await VE_API.system.databaseInstanceBackUp({
|
||||
instanceId: instanceId.value,
|
||||
});
|
||||
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
return serverList.value;
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getServerInstanceList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,254 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- <span>{{ rowData }}</span> -->
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="服务器名称" prop="instanceName">
|
||||
<el-input
|
||||
v-model="instanceName"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input
|
||||
v-model="username"
|
||||
placeholder="root"
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" prop="password">
|
||||
<el-input
|
||||
v-model="password"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="host" prop="host">
|
||||
<el-input
|
||||
v-model="host"
|
||||
placeholder="127.0.0.1"
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="端口" prop="port">
|
||||
<el-input
|
||||
v-model="port"
|
||||
placeholder="3306"
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="驱动程序类名" prop="driverClassName">
|
||||
<el-input
|
||||
v-model="driverClassName"
|
||||
placeholder="com.mysql.cj.jdbc.Driver"
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-input v-model="status" placeholder="" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据源类型" prop="lazyDataSourceType">
|
||||
<el-select
|
||||
v-model="lazyDataSourceType"
|
||||
placeholder="数据源类型"
|
||||
clearable
|
||||
>
|
||||
<el-option label="MySQL" value="MySQL" />
|
||||
<el-option label="H2" value="H2" />
|
||||
<el-option label="CLICK_HOUSE" value="CLICK_HOUSE" />
|
||||
<el-option label="POSTGRESQL" value="POSTGRESQL" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input v-model="sort" placeholder="" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="是否初始化数据库到本地"
|
||||
prop="initializeToLocal"
|
||||
>
|
||||
<el-select
|
||||
v-model="initializeToLocal"
|
||||
placeholder="是否初始化数据库到本地"
|
||||
clearable
|
||||
>
|
||||
<el-option label="初始化数据库到本地" :value="true" />
|
||||
<el-option label="不初始化数据库到本地" :value="false" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button style="float: left" @click="testConnection()"
|
||||
>测试连接</el-button
|
||||
>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, toRefs, ref, defineProps, defineEmits } from "vue";
|
||||
|
||||
const rules = {
|
||||
instanceName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入服务器名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入账户",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入密码",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
host: [
|
||||
{
|
||||
required: true,
|
||||
message: "host不能为空",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
port: [
|
||||
{
|
||||
required: true,
|
||||
message: "端口不能为空",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
driverClassName: [
|
||||
{
|
||||
required: true,
|
||||
message: "driverClassName",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
instanceName: "",
|
||||
driverClassName: "com.mysql.cj.jdbc.Driver",
|
||||
username: "root",
|
||||
password: "",
|
||||
host: "127.0.0.1",
|
||||
port: 3306,
|
||||
status: "",
|
||||
lazyDataSourceType: "MySQL",
|
||||
sort: 1,
|
||||
initializeToLocal: false,
|
||||
});
|
||||
const {
|
||||
instanceName,
|
||||
driverClassName,
|
||||
username,
|
||||
password,
|
||||
host,
|
||||
port,
|
||||
status,
|
||||
lazyDataSourceType,
|
||||
sort,
|
||||
initializeToLocal,
|
||||
} = toRefs(form);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((instanceName.value = rowData.value.instanceName),
|
||||
(username.value = rowData.value.username),
|
||||
(password.value = rowData.value.password),
|
||||
(driverClassName.value = rowData.value.driverClassName),
|
||||
(host.value = rowData.value.host),
|
||||
(port.value = rowData.value.port),
|
||||
(status.value = rowData.value.status),
|
||||
(lazyDataSourceType.value = rowData.value.lazyDataSourceType),
|
||||
(sort.value = rowData.value.sort),
|
||||
(initializeToLocal.value = rowData.value.initializeToLocal));
|
||||
|
||||
/**
|
||||
* 测试连接
|
||||
*/
|
||||
const testConnection = async () => {
|
||||
let res = await VE_API.system.databaseInstanceTest(form);
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
console.log("连接成功");
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value === "添加") {
|
||||
res = await VE_API.system.databaseInstanceAdd(form);
|
||||
} else {
|
||||
res = await VE_API.system.databaseInstanceEdit({
|
||||
id: rowData.value.id,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,392 @@
|
||||
<template>
|
||||
<div class="ve_container">
|
||||
<!-- 搜索 -->
|
||||
<el-form
|
||||
ref="queryForm"
|
||||
:inline="false"
|
||||
:model="params"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item>
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select
|
||||
v-model="params.instanceId"
|
||||
@change="getSchemaList"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库名" prop="schemaName">
|
||||
<el-select
|
||||
clearable
|
||||
filterable
|
||||
v-model="params.schemaName"
|
||||
@change="
|
||||
getTableList(params.instanceId, params.schemaName)
|
||||
"
|
||||
placeholder="数据库名"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="4">
|
||||
<el-card>
|
||||
<el-tree
|
||||
:props="{
|
||||
children: 'children',
|
||||
label: 'tableName',
|
||||
}"
|
||||
:data="schemaTableList"
|
||||
></el-tree>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<el-card>
|
||||
<div class="grid-content ep-bg-purple-light">
|
||||
<el-form-item label="执行的sql" prop="sql">
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="20"
|
||||
v-model="sql"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="sqlConsole()">
|
||||
{{ buttons.search.name }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="downLoad()" type="text">
|
||||
{{ buttons.downLoad.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="downLoadUpsert()"
|
||||
type="text"
|
||||
>
|
||||
{{ buttons.downLoadUpsert.name }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<template
|
||||
v-for="(tableData, index) in tableDataList"
|
||||
:key="index"
|
||||
>
|
||||
<el-check-tag
|
||||
:checked="tableData.checked"
|
||||
@change="changeResultDataTag(index)"
|
||||
>第{{ index + 1 }}个结果集合</el-check-tag
|
||||
>
|
||||
</template>
|
||||
<div
|
||||
v-for="(tableData, index) in tableDataList"
|
||||
:key="index"
|
||||
v-show="tableData.checked"
|
||||
>
|
||||
<!-- 列表 -->
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(
|
||||
val,
|
||||
params,
|
||||
getDataList,
|
||||
),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(
|
||||
val,
|
||||
params,
|
||||
getDataList,
|
||||
),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
>
|
||||
<el-table-column
|
||||
:prop="item"
|
||||
:label="item"
|
||||
v-for="(
|
||||
item, index
|
||||
) in tableData.tableHeader"
|
||||
:key="index"
|
||||
sortable
|
||||
>
|
||||
<template v-slot="scope">
|
||||
<el-input
|
||||
v-model="scope.row[item]"
|
||||
placeholder="数据"
|
||||
></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库查询控制台",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
downLoad: { name: "导出查询结果为Excel" },
|
||||
downLoadUpsert: { name: "Upsert下载查询结果" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "IceCream",
|
||||
name: "数据库查询管理",
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import { reactive, toRefs, ref, onMounted } from "vue";
|
||||
|
||||
const rules = {
|
||||
instanceId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择数据库实例",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
schemaName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择数据库",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
sql: [
|
||||
{
|
||||
required: true,
|
||||
message: "执行SQL不能为空",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
//?导入公共查询方法
|
||||
import {
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
const queryForm = ref(null);
|
||||
const tableDataList = ref([]);
|
||||
const schemaList = ref(null);
|
||||
const schemaTableList = ref(null);
|
||||
const serverList = ref(null);
|
||||
// 当前选择的表
|
||||
// const currentTableName = ref(null);
|
||||
const params = reactive({
|
||||
schemaName: "",
|
||||
instanceId: "",
|
||||
instanceName: "",
|
||||
sql: "show tables",
|
||||
size: 10,
|
||||
current: 1,
|
||||
total: 0,
|
||||
});
|
||||
const { size, current, total, sql } = toRefs(params);
|
||||
|
||||
/**
|
||||
* 点击结果集tag 事件
|
||||
*/
|
||||
const changeResultDataTag = async (index) => {
|
||||
tableDataList.value.forEach((item, itemIndex) => {
|
||||
if (index == itemIndex) {
|
||||
item.checked = true;
|
||||
} else {
|
||||
item.checked = false;
|
||||
}
|
||||
});
|
||||
console.log(index);
|
||||
};
|
||||
/**
|
||||
* 文件下载
|
||||
*/
|
||||
const downLoad = async () => {
|
||||
queryForm.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = await VE_API.system.sqlConsoleExport(params, {
|
||||
responseType: "blob",
|
||||
});
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 文件下载
|
||||
*/
|
||||
const downLoadUpsert = async () => {
|
||||
queryForm.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = await VE_API.system.sqlConsoleUpsertExport(params, {
|
||||
responseType: "blob",
|
||||
});
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 执行sql
|
||||
*/
|
||||
const sqlConsole = async () => {
|
||||
queryForm.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = await VE_API.system.sqlConsole(params);
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
tableDataList.value = res.data;
|
||||
if (res.data.length !== 0) {
|
||||
tableDataList.value.map((item) => {
|
||||
item.tableHeader = Object.keys(item[0]);
|
||||
item.checked = false;
|
||||
});
|
||||
tableDataList.value[0].checked = true;
|
||||
// tableHeader.value = Object.keys(res.data[0]);
|
||||
// tableHeaderList.value = Object.keys(res.data[0]);
|
||||
}
|
||||
console.log(res);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取 数据库表
|
||||
* @param instanceId 数据库实例ID
|
||||
* @param schemaName 数据库名称
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getTableList = async (instanceId, schemaName) => {
|
||||
let res;
|
||||
if (instanceId == null) {
|
||||
return;
|
||||
} else {
|
||||
res = await VE_API.system.tableList({
|
||||
instanceId: instanceId,
|
||||
schemaName: schemaName,
|
||||
});
|
||||
}
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaTableList.value = data;
|
||||
return schemaList.value;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取 数据库
|
||||
* @param instanceId 数据库实例ID
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getSchemaList = async (instanceId) => {
|
||||
let res;
|
||||
if (instanceId == null) {
|
||||
return;
|
||||
} else {
|
||||
res = await VE_API.system.schemaList({
|
||||
instanceId,
|
||||
});
|
||||
}
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaList.value = data;
|
||||
if (schemaList.value) {
|
||||
// 默认第一个实例的第一个数据库
|
||||
params.schemaName = schemaList.value[0].schemaName;
|
||||
await getTableList(instanceId, params.schemaName);
|
||||
}
|
||||
return schemaList.value;
|
||||
}
|
||||
};
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
// 默认第一个实例
|
||||
if (serverList.value && serverList.value.length > 0) {
|
||||
params.instanceId = serverList.value[0].id;
|
||||
getSchemaList(params.instanceId);
|
||||
}
|
||||
return serverList.value;
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getServerInstanceList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-tabs__content.el-tab-pane {
|
||||
display: block;
|
||||
background: #409eff;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,217 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- <span>{{ rowData }}</span> -->
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select
|
||||
v-model="instanceId"
|
||||
placeholder="数据库实例"
|
||||
@change="getSchemaList"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库名" prop="schemaName">
|
||||
<el-select
|
||||
clearable
|
||||
filterable
|
||||
v-model="schemaName"
|
||||
placeholder="数据库名"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-progress
|
||||
:text-inside="true"
|
||||
:stroke-width="24"
|
||||
:percentage="backUpsSchemaProgress.percentage"
|
||||
:hidden="backUpsSchemaProgress.hidden"
|
||||
:status="backUpsSchemaProgress.status"
|
||||
>
|
||||
<span>备份数据库</span>
|
||||
</el-progress>
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
const rules = {
|
||||
instanceId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择数据库实例",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
schemaName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择数据库",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "数据库备份",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
|
||||
const serverList = ref(null);
|
||||
const schemaList = ref(null);
|
||||
const instanceId = ref(null);
|
||||
const schemaName = ref(null);
|
||||
const backUpsSchemaProgress = reactive({
|
||||
hidden: true,
|
||||
percentage: 0,
|
||||
status: "success",
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
instanceId: "",
|
||||
schemaName: "",
|
||||
});
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value && (instanceId.value = rowData.value.instanceId);
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
form.schemaName = schemaName.value;
|
||||
form.instanceId = instanceId.value;
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
backUpsSchemaProgress.hidden = false;
|
||||
// 修改进度条
|
||||
setInterval(() => {
|
||||
backUpsSchemaProgress.percentage =
|
||||
(backUpsSchemaProgress.percentage % 100) + 10;
|
||||
}, 500);
|
||||
let res = await VE_API.system.databaseSchemaBackUp({
|
||||
instanceId: instanceId.value,
|
||||
schemaName: schemaName.value,
|
||||
});
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
backUpsSchemaProgress.status = "success";
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取 数据库
|
||||
* @param instanceId 数据库实例ID
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getSchemaList = async (instanceId) => {
|
||||
let res;
|
||||
if (instanceId == null) {
|
||||
return;
|
||||
} else {
|
||||
res = await VE_API.system.schemaList({
|
||||
instanceId,
|
||||
});
|
||||
}
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaList.value = data;
|
||||
if (schemaList.value) {
|
||||
// 默认第一个实例的第一个数据库
|
||||
schemaName.value = schemaList.value[0].schemaName;
|
||||
}
|
||||
return schemaList.value;
|
||||
}
|
||||
};
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
// 默认第一个实例
|
||||
if (serverList.value && serverList.value.length > 0) {
|
||||
instanceId.value = serverList.value[0].id;
|
||||
getSchemaList(instanceId.value);
|
||||
}
|
||||
return serverList.value;
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getServerInstanceList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,260 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- <span>{{ rowData }}</span> -->
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select
|
||||
v-model="instanceId"
|
||||
placeholder="数据库实例"
|
||||
@change="getSchemaList"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="数据库库名" prop="schemaName">
|
||||
<el-select
|
||||
clearable
|
||||
v-model="schemaName"
|
||||
placeholder="数据库名"
|
||||
@change="getTableList"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库表名" prop="sortingRules">
|
||||
<el-select
|
||||
clearable
|
||||
v-model="tableName"
|
||||
placeholder="数据库表名"
|
||||
@change="getDatabaseTablesColumnList"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="字段名称" prop="columnName">
|
||||
<el-select
|
||||
v-model="columnName"
|
||||
placeholder="字段名称"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableColumnList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
onMounted,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
} from "vue";
|
||||
const rules = {
|
||||
schemaName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入数据库库名",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
instanceId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入数据库服务器",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
tableName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入字符集",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
columnName: [
|
||||
{
|
||||
required: false,
|
||||
message: "请输入排序规则",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const tableColumnList = ref(null);
|
||||
|
||||
const form = reactive({
|
||||
schemaName: "",
|
||||
instanceId: "",
|
||||
tableName: "",
|
||||
columnName: "",
|
||||
});
|
||||
const { schemaName, instanceId, tableName, columnName } = toRefs(form);
|
||||
const serverList = ref(null);
|
||||
|
||||
const schemaList = ref(null);
|
||||
const tableList = ref(null);
|
||||
|
||||
/**
|
||||
* 获取当前表对应的字段
|
||||
* @param tableIds
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getDatabaseTablesColumnList = async () => {
|
||||
// 获取数据
|
||||
let res = await VE_API.system.findDatabaseTableColumnList({
|
||||
instanceId: form.instanceId,
|
||||
schemaName: form.schemaName,
|
||||
tableName: form.tableName,
|
||||
});
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.columnName;
|
||||
item.value = item.columnName;
|
||||
});
|
||||
tableColumnList.value = data ? data : [];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取 数据库表
|
||||
* @param instanceId 数据库实例ID
|
||||
* @param schemaName 数据库名称
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getTableList = async () => {
|
||||
let res;
|
||||
if (instanceId.value == null) {
|
||||
return;
|
||||
} else {
|
||||
res = await VE_API.system.tableList({
|
||||
instanceId: form.instanceId,
|
||||
schemaName: form.schemaName,
|
||||
});
|
||||
}
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.tableName;
|
||||
item.value = item.tableName;
|
||||
});
|
||||
tableList.value = data;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 选择数据库实例
|
||||
* @param serverInstanceId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getSchemaList = async () => {
|
||||
// 查询数据库
|
||||
let res = await VE_API.system.schemaList({
|
||||
instanceId: form.instanceId,
|
||||
});
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
res.data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaList.value = res.data ? res.data : [];
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
// 查询数据库实例
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
});
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = await VE_API.system.schemaDeriveView(form);
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,255 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- <span>{{ rowData }}</span> -->
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select v-model="instanceId" placeholder="数据库实例">
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="数据库库名" prop="schemaName">
|
||||
<el-input
|
||||
v-model="schemaName"
|
||||
placeholder="数据库库名"
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="字符集" prop="characterSet">
|
||||
<el-select
|
||||
v-model="characterSet"
|
||||
placeholder="字符集"
|
||||
filterable
|
||||
>
|
||||
<el-option label="armscii8" value="armscii8" />
|
||||
<el-option label="ascii" value="ascii" />
|
||||
<el-option label="big5" value="big5" />
|
||||
<el-option label="binary" value="binary" />
|
||||
<el-option label="cp850" value="cp850" />
|
||||
<el-option label="cp852" value="cp852" />
|
||||
<el-option label="cp866" value="cp866" />
|
||||
<el-option label="cp932" value="cp932" />
|
||||
<el-option label="cp1250" value="cp1250" />
|
||||
<el-option label="cp1251" value="cp1251" />
|
||||
<el-option label="cp1256" value="cp1256" />
|
||||
<el-option label="cp1257" value="cp1257" />
|
||||
<el-option label="dec8" value="dec8" />
|
||||
<el-option label="eucjpms" value="eucjpms" />
|
||||
<el-option label="euckr" value="euckr" />
|
||||
<el-option label="gb2312" value="gb2312" />
|
||||
<el-option label="gb18030" value="gb18030" />
|
||||
<el-option label="gbk" value="gbk" />
|
||||
<el-option label="geostd8" value="geostd8" />
|
||||
<el-option label="greek" value="greek" />
|
||||
<el-option label="hebrew" value="hebrew" />
|
||||
<el-option label="hp8" value="hp8" />
|
||||
<el-option label="keybcs2" value="keybcs2" />
|
||||
<el-option label="koi8r" value="koi8r" />
|
||||
<el-option label="koi8u" value="koi8u" />
|
||||
<el-option label="latin1" value="latin1" />
|
||||
<el-option label="latin2" value="latin2" />
|
||||
<el-option label="latin5" value="latin5" />
|
||||
<el-option label="latin7" value="latin7" />
|
||||
<el-option label="macce" value="macce" />
|
||||
<el-option label="macroman" value="macroman" />
|
||||
<el-option label="sjis" value="sjis" />
|
||||
<el-option label="swe7" value="swe7" />
|
||||
<el-option label="tis620" value="tis620" />
|
||||
<el-option label="ucs2" value="ucs2" />
|
||||
<el-option label="ujis" value="ujis" />
|
||||
<el-option label="utf8" value="utf8" />
|
||||
<el-option label="utf8mb4" value="utf8mb4" />
|
||||
<el-option label="utf16" value="utf16" />
|
||||
<el-option label="utf16le" value="utf16le" />
|
||||
<el-option label="utf32" value="utf32" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序规则" prop="sortingRules">
|
||||
<el-input
|
||||
v-model="sortingRules"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="ext" prop="ext">
|
||||
<el-input v-model="ext" placeholder="" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="是否初始化数据库到本地"
|
||||
prop="initializeToLocal"
|
||||
>
|
||||
<el-select
|
||||
v-model="initializeToLocal"
|
||||
placeholder="是否初始化数据库到本地"
|
||||
clearable
|
||||
>
|
||||
<el-option label="初始化数据库到本地" :value="true" />
|
||||
<el-option label="不初始化数据库到本地" :value="false" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
onMounted,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
} from "vue";
|
||||
const rules = {
|
||||
schemaName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入数据库库名",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
instanceId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入数据库服务器",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
characterSet: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入字符集",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
sortingRules: [
|
||||
{
|
||||
required: false,
|
||||
message: "请输入排序规则",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
ext: [
|
||||
{
|
||||
required: false,
|
||||
message: "ext",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
schemaName: "",
|
||||
instanceId: "",
|
||||
ext: "",
|
||||
characterSet: "",
|
||||
sortingRules: "",
|
||||
initializeToLocal: "",
|
||||
});
|
||||
const {
|
||||
schemaName,
|
||||
instanceId,
|
||||
ext,
|
||||
characterSet,
|
||||
sortingRules,
|
||||
initializeToLocal,
|
||||
} = toRefs(form);
|
||||
const serverList = ref(null);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((schemaName.value = rowData.value.schemaName),
|
||||
(instanceId.value = rowData.value.instanceId),
|
||||
(characterSet.value = rowData.value.characterSet),
|
||||
(sortingRules.value = rowData.value.sortingRules),
|
||||
(ext.value = rowData.value.ext),
|
||||
(initializeToLocal.value = rowData.value.initializeToLocal));
|
||||
|
||||
onMounted(async () => {
|
||||
// 查询数据库实例
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
});
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value == "添加") {
|
||||
res = await VE_API.system.schemaAdd(form);
|
||||
} else {
|
||||
res = await VE_API.system.schemaEdit({
|
||||
id: rowData.value.id,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,279 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- <span>{{ rowData }}</span> -->
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select
|
||||
v-model="instanceId"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
@change="(val) => getSchemaList(val)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="数据库库名" prop="schemaName">
|
||||
<el-select
|
||||
v-model="schemaName"
|
||||
filterable
|
||||
placeholder="数据库实例"
|
||||
@change="(val) => getTableList(val)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="表名称" prop="tableNameList">
|
||||
<el-select
|
||||
v-model="tableNameList"
|
||||
placeholder="表名称"
|
||||
@change="chooseTable"
|
||||
filterable
|
||||
multiple
|
||||
>
|
||||
<el-checkbox
|
||||
v-model="checked"
|
||||
:indeterminate="
|
||||
tableNameList.length !== tableList.length
|
||||
"
|
||||
@change="selectAll()"
|
||||
style="margin-left: 20px"
|
||||
>
|
||||
全选
|
||||
</el-checkbox>
|
||||
<el-option
|
||||
v-for="item in tableList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="自动填充数量" prop="autoStuffedNum">
|
||||
<el-input
|
||||
v-model="autoStuffedNum"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
onMounted,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
} from "vue";
|
||||
const rules = {
|
||||
databaseSchemaId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入数据库库名",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
instanceId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入数据库服务器",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
schemaName: "",
|
||||
databaseSchemaId: "",
|
||||
instanceId: "",
|
||||
instanceName: "",
|
||||
autoStuffedNum: "",
|
||||
status: false,
|
||||
tableNameList: [],
|
||||
id: "",
|
||||
});
|
||||
const {
|
||||
id,
|
||||
schemaName,
|
||||
databaseSchemaId,
|
||||
instanceId,
|
||||
instanceName,
|
||||
autoStuffedNum,
|
||||
status,
|
||||
tableNameList,
|
||||
} = toRefs(form);
|
||||
const serverList = ref(null);
|
||||
const schemaList = ref(null);
|
||||
const tableList = ref([]);
|
||||
const checked = ref(false);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((id.value = rowData.value.id),
|
||||
(schemaName.value = rowData.value.schemaName),
|
||||
(databaseSchemaId.value = rowData.value.databaseSchemaId),
|
||||
(instanceId.value = rowData.value.instanceId),
|
||||
(instanceName.value = rowData.value.instanceName),
|
||||
(autoStuffedNum.value = rowData.value.autoStuffedNum),
|
||||
(status.value = rowData.value.status),
|
||||
(tableNameList.value = [rowData.value.tableName]));
|
||||
|
||||
onMounted(async () => {
|
||||
getInstanceList();
|
||||
// getSchemaList();
|
||||
// getTableList();
|
||||
});
|
||||
const getInstanceList = () => {
|
||||
// 查询数据库实例
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
const getSchemaList = (databaseInstance = null) => {
|
||||
console.log(databaseInstance);
|
||||
// 查询数据schema信息
|
||||
VE_API.system
|
||||
.schemaList({
|
||||
instanceId: instanceId.value,
|
||||
})
|
||||
.then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
|
||||
const getTableList = () => {
|
||||
// 查询数据表信息
|
||||
VE_API.system
|
||||
.tableList({
|
||||
instanceId: instanceId.value,
|
||||
schemaName: schemaName.value,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.data) {
|
||||
res.data.map((item) => {
|
||||
item.label = item.tableName;
|
||||
item.value = item.tableName;
|
||||
});
|
||||
tableList.value = res.data ? res.data : [];
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 选择表事件
|
||||
*/
|
||||
const chooseTable = () => {
|
||||
let table = tableList.value.find(
|
||||
(item) => item.schemaNameId === databaseSchemaId.value,
|
||||
);
|
||||
console.log(table);
|
||||
if (table) {
|
||||
instanceName.value = table.instanceName;
|
||||
schemaName.value = table.schemaName;
|
||||
}
|
||||
};
|
||||
const selectAll = () => {
|
||||
console.log(checked.value);
|
||||
if (checked.value) {
|
||||
checked.value = false;
|
||||
tableNameList.value = [];
|
||||
} else {
|
||||
checked.value = true;
|
||||
tableNameList.value = tableList.value.map((d) => d.tableName);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value === "添加自动填充记录") {
|
||||
console.log(form);
|
||||
res = await VE_API.system.tableAutoStuffedRecordBatchAdd(form);
|
||||
} else {
|
||||
res = await VE_API.system.tableAutoStuffedRecordEdit({
|
||||
id: rowData.value.id,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,847 @@
|
||||
<template>
|
||||
<el-descriptions title="数据库表信息" :column="4" border>
|
||||
<el-descriptions-item
|
||||
label="数据库实例"
|
||||
label-align="right"
|
||||
align="center"
|
||||
property="instanceId"
|
||||
>
|
||||
<el-select
|
||||
v-model="params.instanceId"
|
||||
@change="getSchemaList"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item
|
||||
label="数据库名"
|
||||
label-align="right"
|
||||
align="center"
|
||||
width="150px"
|
||||
property="schemaName"
|
||||
>
|
||||
<el-select
|
||||
v-model="params.schemaName"
|
||||
placeholder="数据库名"
|
||||
@change="getTableList"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item
|
||||
label="数据库表名"
|
||||
label-align="right"
|
||||
align="center"
|
||||
>
|
||||
<el-select
|
||||
v-model="params.tableName"
|
||||
placeholder="数据库表名"
|
||||
@change="getDatabaseTablesColumnList"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
><el-row>
|
||||
<el-col :span="12">
|
||||
<span style="float: left">{{ item.label }}</span>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<span
|
||||
style="
|
||||
float: right;
|
||||
color: #8492a6;
|
||||
font-size: 13px;
|
||||
"
|
||||
>{{ item.tableComment }}
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row></el-option
|
||||
>
|
||||
</el-select>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="表引擎" label-align="right" align="center">
|
||||
<el-select
|
||||
v-model="params.engine"
|
||||
placeholder="表引擎"
|
||||
filterable
|
||||
:disabled="true"
|
||||
>
|
||||
<el-option label="ARCHIVE" value="ARCHIVE" />
|
||||
<el-option label="BLACKHOLE" value="BLACKHOLE" />
|
||||
<el-option label="CSV" value="CSV" />
|
||||
<el-option label="InnoDB" value="InnoDB" />
|
||||
<el-option label="MEMORY" value="MEMORY" />
|
||||
<el-option label="MRG_MYISAM" value="MRG_MYISAM" />
|
||||
<el-option label="MyISAM" value="MyISAM" />
|
||||
<el-option
|
||||
label="PERFORMANCE_SCHEMA"
|
||||
value="PERFORMANCE_SCHEMA"
|
||||
/>
|
||||
</el-select>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="表描述" label-align="right" align="center">
|
||||
<el-input
|
||||
v-model="tableComment"
|
||||
placeholder="tableComment"
|
||||
:disabled="true"
|
||||
></el-input>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item
|
||||
label="查询字段"
|
||||
label-align="right"
|
||||
align="center"
|
||||
>
|
||||
<el-select
|
||||
v-model="selectColumnList"
|
||||
value-key="columnName"
|
||||
placeholder="查询字段"
|
||||
filterable
|
||||
multiple
|
||||
collapse-tags
|
||||
style="width: 240px"
|
||||
@change="selectColumnOnChange"
|
||||
>
|
||||
<el-checkbox
|
||||
v-model="params.checked"
|
||||
:indeterminate="
|
||||
selectColumnList.length !== tableColumnList.length
|
||||
"
|
||||
@change="selectAllFields()"
|
||||
style="margin-left: 20px"
|
||||
>
|
||||
全选
|
||||
</el-checkbox>
|
||||
<el-option
|
||||
v-for="item in tableColumnList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<span style="float: left">{{ item.label }}</span>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<span
|
||||
style="
|
||||
float: right;
|
||||
color: #8492a6;
|
||||
font-size: 13px;
|
||||
"
|
||||
>{{ item.columnComment }}
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="表头展示模式" prop="status">
|
||||
<el-radio-group v-model="params.showTitleMode">
|
||||
<el-radio-button label="columnName">字段名称</el-radio-button>
|
||||
<el-radio-button label="columnComment"
|
||||
>字段描述</el-radio-button
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-row>
|
||||
<el-button @click="addColumnItem()" style="float: left" type="primary"
|
||||
>添加搜索参数
|
||||
</el-button>
|
||||
<el-button @click="getDataList" style="float: left" type="primary"
|
||||
>执行
|
||||
</el-button>
|
||||
<!-- <el-button-->
|
||||
<!-- v-permission="['batchDel']"-->
|
||||
<!-- type="danger"-->
|
||||
<!-- @click="batchDelRow"-->
|
||||
<!-- style="float: left"-->
|
||||
<!-- >-->
|
||||
<!-- {{ buttons.batchDel.name }}-->
|
||||
<!-- </el-button>-->
|
||||
<el-button type="danger" @click="batchDelRow" style="float: left">
|
||||
{{ buttons.batchDel.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="addRowData"
|
||||
style="float: left"
|
||||
type="primary"
|
||||
:hidden="!params.checked"
|
||||
>添加数据
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="handleExportUpsertSql"
|
||||
style="float: left"
|
||||
type="primary"
|
||||
>导出查询的upsert语句
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="handleExportResult2Md"
|
||||
style="float: left"
|
||||
type="primary"
|
||||
>导出查询结果为.MD
|
||||
</el-button>
|
||||
</el-row>
|
||||
<div style="padding: 10px">
|
||||
<el-row
|
||||
v-for="(it, index) in params.queryCriteriaColumnList"
|
||||
:key="index"
|
||||
>
|
||||
<el-col span="3">
|
||||
<el-checkbox v-model="it.checked" label=" " size="large" />
|
||||
</el-col>
|
||||
<el-col span="6">
|
||||
<el-select
|
||||
v-model="it.columnName"
|
||||
placeholder="字段名称"
|
||||
filterable
|
||||
@change="getOnlyColumnValue(it)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tableColumnList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<span style="float: left">{{
|
||||
item.label
|
||||
}}</span>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<span
|
||||
style="
|
||||
float: right;
|
||||
color: #8492a6;
|
||||
font-size: 13px;
|
||||
"
|
||||
>{{ item.columnComment }}
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col span="6">
|
||||
<el-select
|
||||
v-model="it.condition"
|
||||
placeholder="条件(大于、等于、模糊)"
|
||||
filterable
|
||||
>
|
||||
<el-option label="小等于" value="<" />
|
||||
<el-option label="等于" value="=" />
|
||||
<el-option label="大于等于" value=">=" />
|
||||
<el-option label="小于等于" value="<=" />
|
||||
<el-option label="不等于" value="!=" />
|
||||
<el-option label="模糊查询" value="like" />
|
||||
<el-option label="in" value="in" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col span="6">
|
||||
<el-select
|
||||
v-model="it.data"
|
||||
style="width: 230px"
|
||||
placeholder="数据"
|
||||
filterable
|
||||
clearable
|
||||
allow-create
|
||||
>
|
||||
<el-option
|
||||
v-for="columnUnitValue in it.columnUnitValueList"
|
||||
:key="columnUnitValue"
|
||||
:label="columnUnitValue"
|
||||
:value="columnUnitValue"
|
||||
/>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col span="6">
|
||||
<el-button
|
||||
@click="removeColumnItem(index)"
|
||||
style="float: right"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 列表 -->
|
||||
<div style="height: 120%">
|
||||
<ve-table
|
||||
:table="{
|
||||
data: tableData,
|
||||
}"
|
||||
:pagination="{
|
||||
onSizeChange: (val) =>
|
||||
handleSizeChange(val, params, getDataList),
|
||||
onCurrentChange: (val) =>
|
||||
handleCurrentChange(val, params, getDataList),
|
||||
currentPage: current,
|
||||
pageSize: size,
|
||||
total: total,
|
||||
}"
|
||||
@selectionChange="handleSelectionChange"
|
||||
:key="tableKey"
|
||||
>
|
||||
<!-- 复选框 -->
|
||||
<el-table-column
|
||||
v-if="tableData.length !== 0"
|
||||
type="selection"
|
||||
width="55"
|
||||
/>
|
||||
<!-- 所有的数据列表 -->
|
||||
<!-- <el-table-column-->
|
||||
<!-- v-for="(item, index) in tableColumnList"-->
|
||||
<!-- :prop="item.columnName"-->
|
||||
<!-- :label="item.columnName"-->
|
||||
<!-- :key="index"-->
|
||||
<!-- sortable-->
|
||||
<!-- >-->
|
||||
<!-- <template v-slot="scope">-->
|
||||
<!-- <el-input-->
|
||||
<!-- v-model="scope.row[item.columnName]"-->
|
||||
<!-- placeholder="数据"-->
|
||||
<!-- @change="changeRow(scope.row)"-->
|
||||
<!-- ></el-input>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
|
||||
<!-- 选取的返回结果 -->
|
||||
|
||||
<!-- 展示字段描述 -->
|
||||
<el-table-column
|
||||
v-for="(item, index) in selectColumnList"
|
||||
:prop="dynamicColumnList[index].columnName"
|
||||
:label="
|
||||
params.showTitleMode === 'columnName'
|
||||
? item.columnName
|
||||
: item.columnComment === ''
|
||||
? item.columnName
|
||||
: item.columnComment
|
||||
"
|
||||
:key="`col_${index}`"
|
||||
sortable
|
||||
>
|
||||
<template v-slot="scope">
|
||||
<el-input
|
||||
v-model="scope.row[item.columnName]"
|
||||
placeholder="数据"
|
||||
@change="changeRow(scope.row)"
|
||||
></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
|
||||
<div style="position: relative">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="tableData.sql"
|
||||
readonly
|
||||
></el-input>
|
||||
<el-icon
|
||||
@click="copyAnswer(tableData.sql)"
|
||||
style="float: right; position: absolute; right: 10px; top: 10px"
|
||||
>
|
||||
<DocumentCopy
|
||||
/></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <el-button @click="closeDialog()">取消</el-button>-->
|
||||
<!-- <el-button type="primary" @click="onSubmit()">确定</el-button>-->
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库表快捷查询",
|
||||
buttons: {
|
||||
del: { name: "删除字段" },
|
||||
batchDel: { name: "批量删除数据" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Finished",
|
||||
name: "数据库表快捷查询",
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
<script setup>
|
||||
//导入公共查询方法
|
||||
import {
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
import { reactive, toRefs, ref, defineProps, onMounted } from "vue";
|
||||
import { DocumentCopy } from "@element-plus/icons-vue";
|
||||
import useClipboard from "vue-clipboard3";
|
||||
const { toClipboard } = useClipboard();
|
||||
import Sortable from "sortablejs";
|
||||
import { useRoute } from "vue-router";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const { rowData } = toRefs(props);
|
||||
// 表字段
|
||||
const tableColumnList = ref([]);
|
||||
// 返回结果
|
||||
const selectColumnList = ref([]);
|
||||
const tableKey = ref(1);
|
||||
|
||||
const params = reactive({
|
||||
schemaName: "",
|
||||
instanceId: "",
|
||||
tableComment: "",
|
||||
tableName: "",
|
||||
engine: "",
|
||||
tableCatalog: "",
|
||||
checked: true,
|
||||
showTitleMode: "columnName",
|
||||
// 查询条件字段
|
||||
queryCriteriaColumnList: [],
|
||||
//返回结果
|
||||
selectColumnList: [],
|
||||
current: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
});
|
||||
const {
|
||||
schemaName,
|
||||
instanceId,
|
||||
tableComment,
|
||||
tableName,
|
||||
engine,
|
||||
size,
|
||||
current,
|
||||
total,
|
||||
} = toRefs(params);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((schemaName.value = rowData.value.schemaName),
|
||||
(instanceId.value = rowData.value.instanceId),
|
||||
(tableName.value = rowData.value.tableName));
|
||||
|
||||
const schemaList = ref(null);
|
||||
const tableList = ref(null);
|
||||
const tableData = ref([]);
|
||||
|
||||
const serverList = ref(null);
|
||||
|
||||
const batchSelectRowList = ref(null);
|
||||
|
||||
// const oldList = ref(JSON.parse(JSON.stringify(selectColumnList.value)));
|
||||
// 动态列
|
||||
const dynamicColumnList = ref([]);
|
||||
//
|
||||
// /**
|
||||
// * 表头预览
|
||||
// * @param h
|
||||
// * @param column
|
||||
// * @returns {*}
|
||||
// */
|
||||
// const renderColumnHeader = (h) => {
|
||||
// // // h即为cerateElement的简写,具体可看vue官方文档
|
||||
// // return h("div", [
|
||||
// // h("span", "column.label"),
|
||||
// // h("i", {
|
||||
// // class: "el-icon-question",
|
||||
// // }),
|
||||
// // ]);
|
||||
// };
|
||||
/**
|
||||
* 选择行改变事件
|
||||
*/
|
||||
const selectColumnOnChange = () => {
|
||||
console.log("selectColumnList: " + selectColumnList.value);
|
||||
console.log("dynamicColumnList: " + dynamicColumnList.value);
|
||||
dynamicColumnList.value = selectColumnList.value;
|
||||
};
|
||||
/**
|
||||
* 全选字段
|
||||
*
|
||||
*/
|
||||
const selectAllFields = () => {
|
||||
console.log(params.checked);
|
||||
if (params.checked) {
|
||||
params.checked = true;
|
||||
// selectColumnList.value = tableColumnList.value;
|
||||
initColumnList(tableColumnList.value);
|
||||
} else {
|
||||
params.checked = false;
|
||||
// selectColumnList.value = [];
|
||||
initColumnList([]);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取惟一数据
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getOnlyColumnValue = async (rowColumn) => {
|
||||
const columnName = rowColumn.columnName;
|
||||
console.log(rowColumn);
|
||||
let res = await VE_API.system.tableColumnSqlConsole({
|
||||
instanceId: params.instanceId,
|
||||
schemaName: params.schemaName,
|
||||
tableName: params.tableName,
|
||||
column: columnName,
|
||||
current: 1,
|
||||
size: 100,
|
||||
});
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
rowColumn.columnUnitValueList = data.record ? data.record : [];
|
||||
// console.log(res);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 批量删除数据
|
||||
*/
|
||||
const batchDelRow = async () => {
|
||||
console.log(batchSelectRowList.value);
|
||||
let deleteBatchRow = {
|
||||
schemaName: params.schemaName,
|
||||
instanceId: params.instanceId,
|
||||
tableName: params.tableName,
|
||||
tableRowList: [],
|
||||
};
|
||||
for (let row of batchSelectRowList.value) {
|
||||
deleteBatchRow.tableRowList.push(row);
|
||||
}
|
||||
console.log(deleteBatchRow);
|
||||
|
||||
let res = await VE_API.system.tableRowBatchDelete(deleteBatchRow);
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
console.log(data); //
|
||||
}
|
||||
await getDataList();
|
||||
};
|
||||
/**
|
||||
* 全选事件
|
||||
*
|
||||
*/
|
||||
const handleSelectionChange = (val) => {
|
||||
batchSelectRowList.value = val;
|
||||
console.log(batchSelectRowList.value);
|
||||
};
|
||||
/**
|
||||
* 行数据变更
|
||||
* @param row 行数据
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const changeRow = async (row) => {
|
||||
let storyRow = {
|
||||
schemaName: params.schemaName,
|
||||
instanceId: params.instanceId,
|
||||
tableName: params.tableName,
|
||||
tableRow: row,
|
||||
};
|
||||
console.log(storyRow);
|
||||
let res = await VE_API.system.tableRowStory(storyRow);
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
console.log(data); //
|
||||
await getDataList();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 新增一行数据
|
||||
*/
|
||||
const addRowData = () => {
|
||||
tableData.value.push({});
|
||||
};
|
||||
/**
|
||||
* 获取当前表数据
|
||||
*/
|
||||
const getDataList = async () => {
|
||||
console.log(selectColumnList.value);
|
||||
console.log(selectColumnList.value.length);
|
||||
params.selectColumnList = selectColumnList.value.map((d) => d.columnName);
|
||||
let res = await VE_API.system.tableSqlConsole(params);
|
||||
const { code, data, ext } = res;
|
||||
if (code === 0) {
|
||||
const { size, current, total, record } = data;
|
||||
params.size = size;
|
||||
params.current = current;
|
||||
params.total = total;
|
||||
tableData.value = record;
|
||||
tableData.value.tableHeader = ext.tableHeader;
|
||||
tableData.value.sql = ext.sql;
|
||||
if (record.length === 0) {
|
||||
return;
|
||||
}
|
||||
console.log(ext);
|
||||
// tableData.value.tableHeader = Object.keys(tableData.value[0]);
|
||||
|
||||
// console.log(tableData.value);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 导出查询的 upsert 数据
|
||||
*/
|
||||
const handleExportUpsertSql = async () => {
|
||||
params.selectColumnList = selectColumnList.value.map((d) => d.columnName);
|
||||
let res = await VE_API.system.tableSqlConsoleUpsertExport(params, {
|
||||
responseType: "blob",
|
||||
});
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
};
|
||||
/**
|
||||
* 导出结果为md
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const handleExportResult2Md = async () => {
|
||||
params.selectColumnList = selectColumnList.value.map((d) => d.columnName);
|
||||
let res = await VE_API.system.tableSqlConsoleMdExport(params, {
|
||||
responseType: "blob",
|
||||
});
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
};
|
||||
// 添加表字段
|
||||
const addColumnItem = () => {
|
||||
params.queryCriteriaColumnList.push({
|
||||
condition: "=",
|
||||
checked: true,
|
||||
});
|
||||
};
|
||||
// 删除字段
|
||||
const removeColumnItem = (index) => {
|
||||
// 删除时,我们带两个参数,这个 it 可用可不用,因为我当时只是想看到删除的这个对象的信息,故而带上了; index 是 list 中该对象对应的下标,也是 el-form-item 的项数
|
||||
// 根据这个 index 下标删除 list 中 的该对象
|
||||
params.queryCriteriaColumnList.splice(index, 1);
|
||||
};
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 选择数据库实例
|
||||
* @param serverInstanceId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getSchemaList = async () => {
|
||||
// 查询数据库
|
||||
let res = await VE_API.system.schemaList({
|
||||
instanceId: params.instanceId,
|
||||
});
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
if (res.data) {
|
||||
res.data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaList.value = res.data ? res.data : [];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取 数据库表
|
||||
* @param instanceId 数据库实例ID
|
||||
* @param schemaName 数据库名称
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getTableList = async () => {
|
||||
tableName.value = null;
|
||||
tableComment.value = null;
|
||||
let res;
|
||||
if (instanceId.value == null) {
|
||||
return;
|
||||
} else {
|
||||
res = await VE_API.system.tableList({
|
||||
instanceId: instanceId.value,
|
||||
schemaName: schemaName.value,
|
||||
});
|
||||
}
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
if (data) {
|
||||
data.map((item) => {
|
||||
item.label = item.tableName;
|
||||
item.value = item.tableName;
|
||||
});
|
||||
tableList.value = data;
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取当前表对应的字段
|
||||
* @param tableIds
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getDatabaseTablesColumnList = async () => {
|
||||
// 设置表备注
|
||||
let table = tableList.value.find(
|
||||
(item) => item.tableName === tableName.value,
|
||||
);
|
||||
|
||||
tableColumnList.value = [];
|
||||
params.queryCriteriaColumnList = [];
|
||||
if (table != null) {
|
||||
tableComment.value = table.tableComment;
|
||||
engine.value = table.engine;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
let res = await VE_API.system.findDatabaseTableColumnList({
|
||||
instanceId: instanceId.value,
|
||||
schemaName: schemaName.value,
|
||||
tableName: tableName.value,
|
||||
});
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.label = item.columnName;
|
||||
item.value = item.columnName;
|
||||
});
|
||||
tableColumnList.value = data ? data : [];
|
||||
// 默认全选数据
|
||||
initColumnList(tableColumnList.value);
|
||||
}
|
||||
// 获取数据
|
||||
await getDataList();
|
||||
};
|
||||
/**
|
||||
* 初始化列、动态列
|
||||
*/
|
||||
const initColumnList = (tableColumnList) => {
|
||||
selectColumnList.value = tableColumnList;
|
||||
dynamicColumnList.value = JSON.parse(JSON.stringify(tableColumnList));
|
||||
//
|
||||
rowDrop();
|
||||
colDrop();
|
||||
};
|
||||
|
||||
// 列表 **行拖拽
|
||||
const rowDrop = async () => {
|
||||
// 此时找到的元素是要拖拽元素的父容器
|
||||
const tbody = document.querySelector(".el-table__body-wrapper tbody");
|
||||
|
||||
Sortable.create(tbody, {
|
||||
// 指定父元素下可被拖拽的子元素
|
||||
draggable: ".el-table__row",
|
||||
onEnd({ newIndex, oldIndex }) {
|
||||
const currRow = tableData.value.splice(oldIndex, 1)[0];
|
||||
tableData.value.splice(newIndex, 0, currRow);
|
||||
},
|
||||
});
|
||||
};
|
||||
// 列表 **列拖拽
|
||||
const colDrop = async () => {
|
||||
const wrapperTr = document.querySelector(".el-table__header-wrapper tr");
|
||||
Sortable.create(wrapperTr, {
|
||||
animation: 180,
|
||||
delay: 0,
|
||||
onEnd: (evt) => {
|
||||
const empty = 1;
|
||||
// 跳过显示的列数量,如开头我们用了一个多选框,h和序号
|
||||
const oldItem = dynamicColumnList.value[evt.oldIndex - empty];
|
||||
dynamicColumnList.value.splice(evt.oldIndex - empty, 1);
|
||||
dynamicColumnList.value.splice(evt.newIndex - empty, 0, oldItem);
|
||||
// 每一次拖拽后都要重绘一次
|
||||
reDrawTable();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const copyAnswer = async (copyData) => {
|
||||
console.log("copyData", copyData);
|
||||
if (copyData === "") {
|
||||
ElMessage.warning("请输入文本再复制");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await toClipboard(copyData);
|
||||
ElMessage.success(`复制: ${copyData} 成功!`);
|
||||
} catch (error) {
|
||||
ElMessage.warning(`复制失败: ${error} !`);
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 触发表格重绘
|
||||
*/
|
||||
const reDrawTable = () => {
|
||||
tableKey.value = Math.random();
|
||||
};
|
||||
/**
|
||||
* 页面初始化方法
|
||||
*/
|
||||
onMounted(async () => {
|
||||
let route = useRoute();
|
||||
let row = route.query;
|
||||
// await initTableData(row);
|
||||
await getServerInstanceList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,128 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<el-table ref="filterTable" :data="tableData" style="width: 100%">
|
||||
<el-table-column
|
||||
prop="date"
|
||||
label="日期"
|
||||
sortable
|
||||
width="180"
|
||||
column-key="date"
|
||||
:filters="[
|
||||
{ text: '2016-05-01', value: '2016-05-01' },
|
||||
{ text: '2016-05-02', value: '2016-05-02' },
|
||||
{ text: '2016-05-03', value: '2016-05-03' },
|
||||
{ text: '2016-05-04', value: '2016-05-04' },
|
||||
]"
|
||||
:filter-method="filterHandler"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="姓名" width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="address" label="地址" :formatter="formatter">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="tag"
|
||||
label="标签"
|
||||
width="100"
|
||||
:filters="[
|
||||
{ text: '家', value: '家' },
|
||||
{ text: '公司', value: '公司' },
|
||||
]"
|
||||
:filter-method="filterTag"
|
||||
filter-placement="bottom-end"
|
||||
>
|
||||
<template v-slot="scope">
|
||||
<el-tag
|
||||
:type="scope.row.tag === '家' ? 'primary' : 'success'"
|
||||
disable-transitions
|
||||
>{{ scope.row.tag }}</el-tag
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tableData: [
|
||||
{
|
||||
date: "2016-05-02",
|
||||
name: "王小虎",
|
||||
address: "上海市普陀区金沙江路 1518 弄",
|
||||
tag: "家",
|
||||
},
|
||||
{
|
||||
date: "2016-05-04",
|
||||
name: "王小虎",
|
||||
address: "上海市普陀区金沙江路 1517 弄",
|
||||
tag: "公司",
|
||||
},
|
||||
{
|
||||
date: "2016-05-01",
|
||||
name: "王小虎",
|
||||
address: "上海市普陀区金沙江路 1519 弄",
|
||||
tag: "家",
|
||||
},
|
||||
{
|
||||
date: "2016-05-03",
|
||||
name: "王小虎",
|
||||
address: "上海市普陀区金沙江路 1516 弄",
|
||||
tag: "公司",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
resetDateFilter() {
|
||||
this.$refs.filterTable.clearFilter("date");
|
||||
},
|
||||
clearFilter() {
|
||||
this.$refs.filterTable.clearFilter();
|
||||
},
|
||||
formatter(row, column) {
|
||||
console.log(column);
|
||||
return row.address;
|
||||
},
|
||||
filterTag(value, row) {
|
||||
return row.tag === value;
|
||||
},
|
||||
filterHandler(value, row, column) {
|
||||
const property = column["property"];
|
||||
return row[property] === value;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<script setup>
|
||||
import { defineEmits, defineProps, onMounted, toRefs } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "数据库表文档",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
onMounted(async () => {});
|
||||
</script>
|
||||
@@ -0,0 +1,737 @@
|
||||
<template>
|
||||
<el-descriptions title="数据库表信息" :column="4" border>
|
||||
<el-descriptions-item
|
||||
label="数据库实例"
|
||||
label-align="right"
|
||||
align="center"
|
||||
property="instanceId"
|
||||
>
|
||||
<el-select
|
||||
v-model="instanceId"
|
||||
@change="changedatabaseInstance"
|
||||
placeholder="数据库实例"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/> </el-select
|
||||
></el-descriptions-item>
|
||||
<el-descriptions-item
|
||||
label="数据库名"
|
||||
label-align="right"
|
||||
align="center"
|
||||
label-class-name="my-label"
|
||||
class-name="my-content"
|
||||
width="150px"
|
||||
>
|
||||
<el-select
|
||||
clearable
|
||||
v-model="schemaName"
|
||||
placeholder="数据库名"
|
||||
@change="getDataList"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in schemaNameList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item label="表名称" label-align="right" align="center">
|
||||
<el-input
|
||||
v-model="tableName"
|
||||
placeholder="tableName"
|
||||
clearable
|
||||
></el-input>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="表引擎" label-align="right" align="center">
|
||||
<el-select v-model="engine" placeholder="表引擎" filterable>
|
||||
<el-option label="ARCHIVE" value="ARCHIVE" />
|
||||
<el-option label="BLACKHOLE" value="BLACKHOLE" />
|
||||
<el-option label="CSV" value="CSV" />
|
||||
<el-option label="InnoDB" value="InnoDB" />
|
||||
<el-option label="MEMORY" value="MEMORY" />
|
||||
<el-option label="MRG_MYISAM" value="MRG_MYISAM" />
|
||||
<el-option label="MyISAM" value="MyISAM" />
|
||||
<el-option
|
||||
label="PERFORMANCE_SCHEMA"
|
||||
value="PERFORMANCE_SCHEMA"
|
||||
/>
|
||||
</el-select>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="表描述" label-align="right" align="center">
|
||||
<el-input
|
||||
v-model="tableComment"
|
||||
placeholder="tableComment"
|
||||
clearable
|
||||
></el-input
|
||||
></el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-tabs
|
||||
v-model="activeName"
|
||||
type="card"
|
||||
class="demo-tabs"
|
||||
@tab-click="handleClick"
|
||||
>
|
||||
<el-tab-pane label="字段" name="first">
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
:inline="false"
|
||||
>
|
||||
<ve-table
|
||||
:table="{
|
||||
data: form.tableColumnList,
|
||||
}"
|
||||
:rules="rules"
|
||||
style="width: 100%"
|
||||
:row-class-name="tableRowClassName"
|
||||
>
|
||||
<el-table-column
|
||||
prop="columnName"
|
||||
label="字段名称"
|
||||
sortable
|
||||
>
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input
|
||||
v-model="row.columnName"
|
||||
placeholder="columnName"
|
||||
clearable
|
||||
></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="dataType" label="类型">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-select
|
||||
v-model="row.dataType"
|
||||
placeholder="字段类型"
|
||||
filterable
|
||||
>
|
||||
<el-option label="bigint" value="bigint" />
|
||||
<el-option label="binary" value="binary" />
|
||||
<el-option label="bit" value="bit" />
|
||||
<el-option label="blob" value="blob" />
|
||||
<el-option label="char" value="char" />
|
||||
<el-option label="date" value="date" />
|
||||
<el-option label="datetime" value="datetime" />
|
||||
<el-option label="decimal" value="decimal" />
|
||||
<el-option label="double" value="double" />
|
||||
<el-option label="enum" value="enum" />
|
||||
<el-option label="float" value="float" />
|
||||
<el-option label="geometry" value="geometry" />
|
||||
<el-option
|
||||
label="geometrycollection"
|
||||
value="geometrycollection"
|
||||
/>
|
||||
<el-option label="int" value="int" />
|
||||
<el-option label="integer" value="integer" />
|
||||
<el-option label="json" value="json" />
|
||||
<el-option
|
||||
label="linestring"
|
||||
value="linestring"
|
||||
/>
|
||||
<el-option label="longblob" value="longblob" />
|
||||
<el-option label="longtext" value="longtext" />
|
||||
<el-option
|
||||
label="mediumblob"
|
||||
value="mediumblob"
|
||||
/>
|
||||
<el-option
|
||||
label="mediumint"
|
||||
value="mediumint"
|
||||
/>
|
||||
<el-option
|
||||
label="mediumtext"
|
||||
value="mediumtext"
|
||||
/>
|
||||
<el-option
|
||||
label="multilinestring"
|
||||
value="multilinestring"
|
||||
/>
|
||||
<el-option
|
||||
label="multipoint"
|
||||
value="multipoint"
|
||||
/>
|
||||
<el-option
|
||||
label="multipolygon"
|
||||
value="multipolygon"
|
||||
/>
|
||||
<el-option label="numeric" value="numeric" />
|
||||
<el-option label="point" value="point" />
|
||||
<el-option label="polygon" value="polygon" />
|
||||
<el-option label="real" value="real" />
|
||||
<el-option label="set" value="set" />
|
||||
<el-option label="smallint" value="smallint" />
|
||||
<el-option label="text" value="text" />
|
||||
<el-option label="time" value="time" />
|
||||
<el-option
|
||||
label="timestamp"
|
||||
value="timestamp"
|
||||
/>
|
||||
<el-option label="tinyblob" value="tinyblob" />
|
||||
<el-option label="tinyint" value="tinyint" />
|
||||
<el-option label="tinytext" value="tinytext" />
|
||||
<el-option
|
||||
label="varbinary"
|
||||
value="varbinary"
|
||||
/>
|
||||
<el-option label="varchar" value="varchar" />
|
||||
<el-option label="year" value="year" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="characterMaximumLength"
|
||||
label="字段长度"
|
||||
>
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input
|
||||
v-model="row.characterMaximumLength"
|
||||
placeholder="characterMaximumLength"
|
||||
clearable
|
||||
></el-input
|
||||
></template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="columnType"
|
||||
label="字段类型"
|
||||
sortable
|
||||
>
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input
|
||||
v-model="row.columnType"
|
||||
placeholder="columnType"
|
||||
clearable
|
||||
></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="generationExpression" label="小数点">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input
|
||||
v-model="row.generationExpression"
|
||||
placeholder="generationExpression"
|
||||
clearable
|
||||
></el-input
|
||||
></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isNullable" label="不是null">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-select
|
||||
v-model="row.isNullable"
|
||||
placeholder="不是null"
|
||||
>
|
||||
<el-option label="YES" value="YES" />
|
||||
<el-option label="NO" value="NO" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="numericPrecision" label="虚拟">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input
|
||||
v-model="row.numericPrecision"
|
||||
placeholder="numericPrecision"
|
||||
clearable
|
||||
></el-input
|
||||
></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="numericScale" label="键">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input
|
||||
v-model="row.numericScale"
|
||||
placeholder="numericScale"
|
||||
clearable
|
||||
></el-input
|
||||
></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="columnComment" label="描述">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input
|
||||
v-model="row.columnComment"
|
||||
placeholder="columnComment"
|
||||
clearable
|
||||
></el-input
|
||||
></template>
|
||||
</el-table-column>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
@click="addColumnItem()"
|
||||
style="float: right"
|
||||
type="primary"
|
||||
>增加</el-button
|
||||
>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()"
|
||||
>确定</el-button
|
||||
>
|
||||
</template>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot="{ $index }">
|
||||
<el-button
|
||||
@click="removeColumnItem($index)"
|
||||
style="float: right"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button></template
|
||||
>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="索引" name="second">
|
||||
<ve-table
|
||||
:table="{
|
||||
data: form.tableColumnIndexList,
|
||||
}"
|
||||
:rules="rules"
|
||||
style="width: 100%"
|
||||
:row-class-name="tableRowClassName"
|
||||
>
|
||||
<el-table-column prop="indexName" label="索引名称" sortable>
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input
|
||||
v-model="row.indexName"
|
||||
placeholder="indexName"
|
||||
clearable
|
||||
></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="columnNameList" label="索引字段">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-select
|
||||
v-model="row.columnNameList"
|
||||
placeholder="索引字段"
|
||||
filterable
|
||||
multiple
|
||||
>
|
||||
<el-option
|
||||
v-for="item in form.tableColumnList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="indexType" label="索引类型">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-select
|
||||
v-model="row.indexType"
|
||||
placeholder="索引类型"
|
||||
filterable
|
||||
>
|
||||
<el-option label="FULLTEXT" value="FULLTEXT" />
|
||||
<el-option label="NORMAL" value="NORMAL" />
|
||||
<el-option label="SPATIAL" value="SPATIAL" />
|
||||
<el-option
|
||||
label="UNIQUE"
|
||||
value="UNIQUE"
|
||||
/> </el-select
|
||||
></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="indexType" label="索引方法">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-select
|
||||
v-model="row.indexType"
|
||||
placeholder="索引方法"
|
||||
filterable
|
||||
>
|
||||
<el-option label="BTREE" value="BTREE " />
|
||||
<el-option label="HASH" value="HASH" /> </el-select
|
||||
></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="indexComment" label="注释">
|
||||
<template v-slot:default="{ row }">
|
||||
<el-input
|
||||
v-model="row.indexComment"
|
||||
placeholder="索引注释"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #tool_bar>
|
||||
<el-button
|
||||
@click="addColumnIndexItem()"
|
||||
style="float: right"
|
||||
type="primary"
|
||||
>增加</el-button
|
||||
>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()"
|
||||
>确定</el-button
|
||||
>
|
||||
</template>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot="{ $index }">
|
||||
<el-button
|
||||
@click="removeColumnIndexItem($index)"
|
||||
style="float: right"
|
||||
type="danger"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button></template
|
||||
>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="外键" name="third">外键</el-tab-pane>-->
|
||||
<!-- <el-tab-pane label="触发器" name="fourth">触发器</el-tab-pane>-->
|
||||
<!-- <el-tab-pane label="选项" name="five">选项</el-tab-pane>-->
|
||||
<!-- <el-tab-pane label="注释" name="six">注释</el-tab-pane>-->
|
||||
<!-- <el-tab-pane label="SQL预览" name="seven">SQL预览</el-tab-pane>-->
|
||||
</el-tabs>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库表字段设置",
|
||||
buttons: {
|
||||
del: { name: "删除字段" },
|
||||
},
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
<script setup>
|
||||
import { reactive, toRefs, ref, defineProps, onMounted } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
const rules = {
|
||||
instanceId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择数据库实例",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
characterSet: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入字符集",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
sortingRules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入排序规则",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
ext: [
|
||||
{
|
||||
required: true,
|
||||
message: "ext",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const { title, rowData } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
// router.go(-1);
|
||||
router.back();
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
id: "",
|
||||
schemaName: "",
|
||||
instanceName: "",
|
||||
instanceId: "",
|
||||
engine: "InnoDB",
|
||||
autoIncrement: "",
|
||||
tableComment: "",
|
||||
tableName: "",
|
||||
tableCatalog: "",
|
||||
tableRows: "",
|
||||
tableCollation: "",
|
||||
maxDataLength: "",
|
||||
indexLength: "",
|
||||
dataLength: "",
|
||||
avgRowLength: "",
|
||||
createOptions: "",
|
||||
checkTime: "",
|
||||
checksum: "",
|
||||
dataFree: "",
|
||||
rowFormat: "",
|
||||
tableType: "",
|
||||
createTime: "",
|
||||
updateTime: "",
|
||||
version: "",
|
||||
tableColumnList: ref([]),
|
||||
tableColumnIndexList: ref([]),
|
||||
});
|
||||
const {
|
||||
id,
|
||||
schemaName,
|
||||
instanceName,
|
||||
instanceId,
|
||||
engine,
|
||||
autoIncrement,
|
||||
tableComment,
|
||||
tableName,
|
||||
tableCatalog,
|
||||
tableRows,
|
||||
tableCollation,
|
||||
maxDataLength,
|
||||
indexLength,
|
||||
dataLength,
|
||||
avgRowLength,
|
||||
createOptions,
|
||||
checkTime,
|
||||
checksum,
|
||||
dataFree,
|
||||
rowFormat,
|
||||
tableType,
|
||||
createTime,
|
||||
updateTime,
|
||||
version,
|
||||
} = toRefs(form);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((schemaName.value = rowData.value.schemaName),
|
||||
(id.value = rowData.value.id),
|
||||
(instanceName.value = rowData.value.instanceName),
|
||||
(instanceId.value = rowData.value.instanceId),
|
||||
(engine.value = rowData.value.engine),
|
||||
(autoIncrement.value = rowData.value.autoIncrement),
|
||||
(tableComment.value = rowData.value.tableComment),
|
||||
(tableName.value = rowData.value.tableName),
|
||||
(tableCatalog.value = rowData.value.tableCatalog),
|
||||
(tableRows.value = rowData.value.tableRows),
|
||||
(tableCollation.value = rowData.value.tableCollation),
|
||||
(maxDataLength.value = rowData.value.maxDataLength),
|
||||
(indexLength.value = rowData.value.indexLength),
|
||||
(dataLength.value = rowData.value.dataLength),
|
||||
(avgRowLength.value = rowData.value.avgRowLength),
|
||||
(createOptions.value = rowData.value.createOptions),
|
||||
(checkTime.value = rowData.value.checkTime),
|
||||
(checksum.value = rowData.value.checksum),
|
||||
(dataFree.value = rowData.value.dataFree),
|
||||
(rowFormat.value = rowData.value.rowFormat),
|
||||
(tableType.value = rowData.value.tableType),
|
||||
(createTime.value = rowData.value.createTime),
|
||||
(updateTime.value = rowData.value.updateTime),
|
||||
(version.value = rowData.value.version));
|
||||
|
||||
const schemaNameList = ref(null);
|
||||
const serverList = ref(null);
|
||||
const router = useRouter();
|
||||
|
||||
const activeName = ref("first");
|
||||
|
||||
/**
|
||||
* 点标签
|
||||
* @param tab 标签
|
||||
* @param event 事件
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const handleClick = async (tab, event) => {
|
||||
console.log(tab, event);
|
||||
};
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
let databaseInstance = serverList.value.find(
|
||||
(item) => item.id === form.instanceId,
|
||||
);
|
||||
|
||||
form.instanceName = databaseInstance.instanceName;
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value === "添加") {
|
||||
res = await VE_API.system.tableAdd(form);
|
||||
} else {
|
||||
res = await VE_API.system.tableAdd({
|
||||
id: rowData.value.id,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
router.go(-1);
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 添加表字段
|
||||
const addColumnItem = () => {
|
||||
form.tableColumnList.push({});
|
||||
};
|
||||
// 删除字段
|
||||
const removeColumnItem = (index) => {
|
||||
// 删除时,我们带两个参数,这个 it 可用可不用,因为我当时只是想看到删除的这个对象的信息,故而带上了; index 是 list 中该对象对应的下标,也是 el-form-item 的项数
|
||||
// 根据这个 index 下标删除 list 中 的该对象
|
||||
form.tableColumnList.splice(index, 1);
|
||||
};
|
||||
// 添加表索引
|
||||
const addColumnIndexItem = () => {
|
||||
form.tableColumnIndexList.push({});
|
||||
};
|
||||
// 删除索引
|
||||
const removeColumnIndexItem = (index) => {
|
||||
// 删除时,我们带两个参数,这个 it 可用可不用,因为我当时只是想看到删除的这个对象的信息,故而带上了; index 是 list 中该对象对应的下标,也是 el-form-item 的项数
|
||||
// 根据这个 index 下标删除 list 中 的该对象
|
||||
form.tableColumnIndexList.splice(index, 1);
|
||||
};
|
||||
// 查询数据库实例
|
||||
const getServerInstanceList = async () => {
|
||||
VE_API.system.databaseInstanceList().then((res) => {
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
});
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 选择数据库实例
|
||||
* @param serverInstanceId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const changedatabaseInstance = async (instanceId) => {
|
||||
if (instanceId == null) {
|
||||
return;
|
||||
}
|
||||
// 查询数据库
|
||||
let res = await VE_API.system.schemaList({
|
||||
instanceId,
|
||||
});
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
res.data.map((item) => {
|
||||
item.label = item.schemaName;
|
||||
item.value = item.schemaName;
|
||||
});
|
||||
schemaNameList.value = res.data ? res.data : [];
|
||||
}
|
||||
};
|
||||
|
||||
const initTableData = async (row) => {
|
||||
let instanceId = row.instanceId;
|
||||
if (instanceId !== "" && instanceId !== undefined) {
|
||||
form.schemaName = row.schemaName;
|
||||
form.instanceId = row.instanceId;
|
||||
form.instanceName = row.instanceName;
|
||||
form.engine = row.engine;
|
||||
form.autoIncrement = row.autoIncrement;
|
||||
form.tableComment = row.tableComment;
|
||||
form.tableName = row.tableName;
|
||||
form.tableCatalog = row.tableCatalog;
|
||||
form.tableRows = row.tableRows;
|
||||
form.tableCollation = row.tableCollation;
|
||||
form.maxDataLength = row.maxDataLength;
|
||||
form.indexLength = row.indexLength;
|
||||
form.dataLength = row.dataLength;
|
||||
form.avgRowLength = row.avgRowLength;
|
||||
form.createOptions = row.createOptions;
|
||||
form.checkTime = row.checkTime;
|
||||
form.checksum = row.checksum;
|
||||
form.dataFree = row.dataFree;
|
||||
form.rowFormat = row.rowFormat;
|
||||
form.tableType = row.tableType;
|
||||
form.createTime = row.createTime;
|
||||
form.updateTime = row.updateTime;
|
||||
form.version = row.version;
|
||||
// 判断数据库实例
|
||||
|
||||
form.instanceId = instanceId;
|
||||
// 获取当前表选择的数据库实例数据库列表
|
||||
if (
|
||||
form.instanceId !== null &&
|
||||
form.instanceId !== "" &&
|
||||
form.instanceId !== undefined &&
|
||||
!isNaN(form.instanceId)
|
||||
) {
|
||||
await changedatabaseInstance(form.instanceId);
|
||||
}
|
||||
// 查询当前表字段
|
||||
if (
|
||||
form.tableName !== null &&
|
||||
form.tableName !== "" &&
|
||||
form.tableName !== undefined
|
||||
) {
|
||||
await getDatabaseTablesColumnList(
|
||||
form.instanceId,
|
||||
form.schemaName,
|
||||
form.tableName,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取当前表对应的字段
|
||||
* @param tableIds
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getDatabaseTablesColumnList = async (
|
||||
instanceId,
|
||||
schemaName,
|
||||
tableName,
|
||||
) => {
|
||||
let res = await VE_API.system.databaseTableColumnList({
|
||||
instanceId: instanceId,
|
||||
schemaName: schemaName,
|
||||
tableName: tableName,
|
||||
});
|
||||
const { code, data } = res;
|
||||
if (code === 0) {
|
||||
const { acwTableColumnDTOList, acwTableColumnIndexDTOList } = data;
|
||||
if (acwTableColumnDTOList && acwTableColumnDTOList.length > 0) {
|
||||
acwTableColumnDTOList.map((item) => {
|
||||
item.label = item.columnName;
|
||||
item.value = item.columnName;
|
||||
});
|
||||
form.tableColumnList = acwTableColumnDTOList
|
||||
? acwTableColumnDTOList
|
||||
: [];
|
||||
form.tableColumnIndexList = acwTableColumnIndexDTOList;
|
||||
}
|
||||
}
|
||||
};
|
||||
const tableRowClassName = async ({ row, rowIndex }) => {
|
||||
// 把每一行的索引放进row
|
||||
row.index = rowIndex;
|
||||
};
|
||||
onMounted(async () => {
|
||||
let route = useRoute();
|
||||
let row = route.query;
|
||||
await initTableData(row);
|
||||
await getServerInstanceList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,293 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<el-descriptions class="margin-top" :column="3" border title="表详情">
|
||||
<el-descriptions-item
|
||||
label="id"
|
||||
property="id"
|
||||
class="contentClassName"
|
||||
>
|
||||
{{ this.rowData.id }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="数据库服务器ID">
|
||||
<el-tag size="small"> {{ this.rowData.instanceId }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="数据库服务器名称">
|
||||
<el-tag size="small"> {{ this.rowData.instanceName }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item label="数据库名称">
|
||||
{{ this.rowData.schemaName }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="数据库ID">
|
||||
{{ this.rowData.schemaNameId }}</el-descriptions-item
|
||||
>
|
||||
|
||||
<el-descriptions-item label="表引擎">
|
||||
{{ this.rowData.engine }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="表名称">
|
||||
{{ this.rowData.tableName }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="表名描述">
|
||||
{{ this.rowData.tableComment }}</el-descriptions-item
|
||||
>
|
||||
</el-descriptions>
|
||||
|
||||
<el-descriptions border>
|
||||
<el-descriptions-item label="表字段">
|
||||
<span v-for="(item, index) in tableColumnList" :key="index"
|
||||
>{{ item.columnName }} <el-divider direction="vertical"
|
||||
/></span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-checkbox-group v-model="checkedCities" :min="1" :max="2">
|
||||
<el-checkbox v-for="city in cities" :key="city" :label="city">{{
|
||||
city
|
||||
}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
|
||||
<el-timeline>
|
||||
<el-timeline-item timestamp="实体" placement="top">
|
||||
<el-card>
|
||||
<h4>表对应的实体</h4>
|
||||
<p style="white-space: pre-wrap">
|
||||
{{ javaModel.javaEntity }}
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item timestamp="实体对应xml" placement="top">
|
||||
<el-card>
|
||||
<h4>实体对应xml</h4>
|
||||
<p style="white-space: pre-wrap">
|
||||
{{ javaModel.javaMapperXml }}
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item timestamp="控制层" placement="top">
|
||||
<el-card>
|
||||
<h4>表对应的控制层</h4>
|
||||
<p style="white-space: pre-wrap">
|
||||
{{ javaModel.javaController }}
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item timestamp="业务接口" placement="top">
|
||||
<el-card>
|
||||
<h4>表对应的业务接口</h4>
|
||||
<p style="white-space: pre-wrap">
|
||||
{{ javaModel.javaService }}
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item timestamp="业务接口实现" placement="top">
|
||||
<el-card>
|
||||
<h4>表对应的业务接口实现</h4>
|
||||
<p style="white-space: pre-wrap">
|
||||
{{ javaModel.javaServiceImpl }}
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
const checkedCities = ref(["swagger"]);
|
||||
const cities = ["swagger", "mybatis", "lazy", "Shenzhen"];
|
||||
/**
|
||||
* private StringBuilder javaController;
|
||||
private StringBuilder javaEntity;
|
||||
private StringBuilder javaService;
|
||||
private StringBuilder javaServiceImpl;
|
||||
private StringBuilder javaMapper;
|
||||
private StringBuilder javaMapperXml;
|
||||
*/
|
||||
const javaModel = ref({});
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
id: "",
|
||||
schemaName: "",
|
||||
schemaNameId: "",
|
||||
instanceName: "",
|
||||
instanceId: "",
|
||||
engine: "",
|
||||
autoIncrement: "",
|
||||
tableComment: "",
|
||||
tableName: "",
|
||||
tableCatalog: "",
|
||||
tableRows: "",
|
||||
tableCollation: "",
|
||||
maxDataLength: "",
|
||||
indexLength: "",
|
||||
dataLength: "",
|
||||
avgRowLength: "",
|
||||
createOptions: "",
|
||||
checkTime: "",
|
||||
checksum: "",
|
||||
dataFree: "",
|
||||
rowFormat: "",
|
||||
tableType: "",
|
||||
createTime: "",
|
||||
updateTime: "",
|
||||
version: "",
|
||||
});
|
||||
const {
|
||||
id,
|
||||
schemaName,
|
||||
schemaNameId,
|
||||
instanceName,
|
||||
instanceId,
|
||||
engine,
|
||||
autoIncrement,
|
||||
tableComment,
|
||||
tableName,
|
||||
tableCatalog,
|
||||
tableRows,
|
||||
tableCollation,
|
||||
maxDataLength,
|
||||
indexLength,
|
||||
dataLength,
|
||||
avgRowLength,
|
||||
createOptions,
|
||||
checkTime,
|
||||
checksum,
|
||||
dataFree,
|
||||
rowFormat,
|
||||
tableType,
|
||||
createTime,
|
||||
updateTime,
|
||||
version,
|
||||
} = toRefs(form);
|
||||
const tableColumnList = ref(null);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((schemaName.value = rowData.value.schemaName),
|
||||
(id.value = rowData.value.id),
|
||||
(schemaNameId.value = rowData.value.schemaNameId),
|
||||
(instanceName.value = rowData.value.instanceName),
|
||||
(instanceId.value = rowData.value.instanceId),
|
||||
(engine.value = rowData.value.engine),
|
||||
(autoIncrement.value = rowData.value.autoIncrement),
|
||||
(tableComment.value = rowData.value.tableComment),
|
||||
(tableName.value = rowData.value.tableName),
|
||||
(tableCatalog.value = rowData.value.tableCatalog),
|
||||
(tableRows.value = rowData.value.tableRows),
|
||||
(tableCollation.value = rowData.value.tableCollation),
|
||||
(maxDataLength.value = rowData.value.maxDataLength),
|
||||
(indexLength.value = rowData.value.indexLength),
|
||||
(dataLength.value = rowData.value.dataLength),
|
||||
(avgRowLength.value = rowData.value.avgRowLength),
|
||||
(createOptions.value = rowData.value.createOptions),
|
||||
(checkTime.value = rowData.value.checkTime),
|
||||
(checksum.value = rowData.value.checksum),
|
||||
(dataFree.value = rowData.value.dataFree),
|
||||
(rowFormat.value = rowData.value.rowFormat),
|
||||
(tableType.value = rowData.value.tableType),
|
||||
(createTime.value = rowData.value.createTime),
|
||||
(updateTime.value = rowData.value.updateTime),
|
||||
(version.value = rowData.value.version));
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value === "添加") {
|
||||
res = await VE_API.system.schemaAdd(form);
|
||||
} else {
|
||||
res = await VE_API.system.schemaEdit({
|
||||
id: rowData.value.id,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code === "00") {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 获取表字段
|
||||
* @param tableIds
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getDatabaseTablesColumnList = async (tableIds) => {
|
||||
let res = await VE_API.system.databaseTablesColumnList({
|
||||
tableIds,
|
||||
});
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
res.data.map((item) => {
|
||||
item.label = item.columnName;
|
||||
item.value = item.columnName;
|
||||
});
|
||||
tableColumnList.value = res.data ? res.data : [];
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
VE_API.system.generateJavaModel({ id: rowData.value.id }).then((res) => {
|
||||
const { code } = res;
|
||||
console.log(code);
|
||||
if (code === 0) {
|
||||
javaModel.value = res.data;
|
||||
}
|
||||
});
|
||||
await getDatabaseTablesColumnList(rowData.value.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,526 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<el-form ref="form">
|
||||
<el-descriptions
|
||||
class="margin-top"
|
||||
:column="3"
|
||||
border
|
||||
title="表详情"
|
||||
>
|
||||
<!-- <el-descriptions-item-->
|
||||
<!-- label="id"-->
|
||||
<!-- property="id"-->
|
||||
<!-- class="contentClassName"-->
|
||||
<!-- >-->
|
||||
<!-- {{ this.rowData.id }}-->
|
||||
<!-- </el-descriptions-item>-->
|
||||
<el-descriptions-item label="数据库服务器ID">
|
||||
<el-tag size="small"> {{ this.rowData.instanceId }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="数据库服务器名称">
|
||||
<el-tag size="small">
|
||||
{{ this.rowData.instanceName }}</el-tag
|
||||
>
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item label="数据库名称">
|
||||
{{ this.rowData.schemaName }}</el-descriptions-item
|
||||
>
|
||||
<!-- <el-descriptions-item label="数据库ID">-->
|
||||
<!-- {{ this.rowData.schemaNameId }}</el-descriptions-item-->
|
||||
<!-- >-->
|
||||
|
||||
<el-descriptions-item label="表引擎">
|
||||
{{ this.rowData.engine }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="表名称">
|
||||
{{ this.rowData.tableName }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="表名描述">
|
||||
{{ this.rowData.tableComment }}</el-descriptions-item
|
||||
>
|
||||
</el-descriptions>
|
||||
|
||||
<el-descriptions border>
|
||||
<el-descriptions-item label="表字段">
|
||||
<span v-for="(item, index) in tableColumnList" :key="index"
|
||||
>{{ item.columnName }} <el-divider direction="vertical"
|
||||
/></span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="生成本地Java代码地址">
|
||||
<el-tree-select
|
||||
v-model="javaLocalPath"
|
||||
:data="resourceData"
|
||||
lazy
|
||||
:load="loadNode"
|
||||
:props="resourceProps"
|
||||
filterable
|
||||
check-strictly
|
||||
:render-after-expand="false"
|
||||
show-checkbox
|
||||
check-on-click-node
|
||||
/>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-form-item>
|
||||
<el-button
|
||||
v-permission="['java_code']"
|
||||
@click.prevent="handleJavaCode(buttons.java_code.name, row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.java_code.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['export_insert_sql']"
|
||||
@click.prevent="
|
||||
exportInsertSql(buttons.export_insert_sql.name, row)
|
||||
"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.export_insert_sql.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['export_upsert_sql']"
|
||||
@click.prevent="
|
||||
exportUpsertSql(buttons.export_upsert_sql.name, row)
|
||||
"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.export_upsert_sql.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['export_table_excel']"
|
||||
@click.prevent="
|
||||
exporTableExcel(buttons.export_table_excel.name, row)
|
||||
"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.export_table_excel.name }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-timeline>
|
||||
<el-timeline-item timestamp="实体" placement="top">
|
||||
<el-card>
|
||||
<h4>表对应的实体</h4>
|
||||
<p style="white-space: pre-wrap">
|
||||
{{ javaModel.javaEntity }}
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item timestamp="实体对应xml" placement="top">
|
||||
<el-card>
|
||||
<h4>实体对应xml</h4>
|
||||
<p style="white-space: pre-wrap">
|
||||
{{ javaModel.javaMapperXml }}
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item timestamp="控制层" placement="top">
|
||||
<el-card>
|
||||
<h4>表对应的控制层</h4>
|
||||
<p style="white-space: pre-wrap">
|
||||
{{ javaModel.javaController }}
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item timestamp="业务接口" placement="top">
|
||||
<el-card>
|
||||
<h4>表对应的业务接口</h4>
|
||||
<p style="white-space: pre-wrap">
|
||||
{{ javaModel.javaService }}
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item timestamp="业务接口实现" placement="top">
|
||||
<el-card>
|
||||
<h4>表对应的业务接口实现</h4>
|
||||
<p style="white-space: pre-wrap">
|
||||
{{ javaModel.javaServiceImpl }}
|
||||
</p>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()"
|
||||
>确定</el-button
|
||||
>
|
||||
</span>
|
||||
</template>
|
||||
</el-form>
|
||||
</el-drawer>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data: () => ({
|
||||
description: "数据库表查询与设置",
|
||||
buttons: {
|
||||
search: { name: "查询" },
|
||||
add: { name: "添加表" },
|
||||
java_code: { name: "Java代码生成" },
|
||||
edit: { name: "编辑" },
|
||||
del: { name: "删除" },
|
||||
more: { name: "更多" },
|
||||
export_insert_sql: { name: "导出insert-sql" },
|
||||
export_upsert_sql: { name: "导出upsert-sql" },
|
||||
export_table_excel: { name: "导出表结构.excel" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "CopyDocument",
|
||||
name: "数据库表查询与设置更多",
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
|
||||
const javaLocalPath = ref();
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
/**
|
||||
*
|
||||
private StringBuilder javaController;
|
||||
private StringBuilder javaEntity;
|
||||
private StringBuilder javaService;
|
||||
private StringBuilder javaServiceImpl;
|
||||
private StringBuilder javaMapper;
|
||||
private StringBuilder javaMapperXml;
|
||||
*/
|
||||
const javaModel = ref({});
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
id: "",
|
||||
schemaName: "",
|
||||
schemaNameId: "",
|
||||
instanceName: "",
|
||||
instanceId: "",
|
||||
engine: "",
|
||||
autoIncrement: "",
|
||||
tableComment: "",
|
||||
tableName: "",
|
||||
tableCatalog: "",
|
||||
tableRows: "",
|
||||
tableCollation: "",
|
||||
maxDataLength: "",
|
||||
indexLength: "",
|
||||
dataLength: "",
|
||||
avgRowLength: "",
|
||||
createOptions: "",
|
||||
checkTime: "",
|
||||
checksum: "",
|
||||
dataFree: "",
|
||||
rowFormat: "",
|
||||
tableType: "",
|
||||
createTime: "",
|
||||
updateTime: "",
|
||||
version: "",
|
||||
});
|
||||
const {
|
||||
id,
|
||||
schemaName,
|
||||
schemaNameId,
|
||||
instanceName,
|
||||
instanceId,
|
||||
engine,
|
||||
autoIncrement,
|
||||
tableComment,
|
||||
tableName,
|
||||
tableCatalog,
|
||||
tableRows,
|
||||
tableCollation,
|
||||
maxDataLength,
|
||||
indexLength,
|
||||
dataLength,
|
||||
avgRowLength,
|
||||
createOptions,
|
||||
checkTime,
|
||||
checksum,
|
||||
dataFree,
|
||||
rowFormat,
|
||||
tableType,
|
||||
createTime,
|
||||
updateTime,
|
||||
version,
|
||||
} = toRefs(form);
|
||||
const tableColumnList = ref(null);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((schemaName.value = rowData.value.schemaName),
|
||||
(id.value = rowData.value.id),
|
||||
(schemaNameId.value = rowData.value.schemaNameId),
|
||||
(instanceName.value = rowData.value.instanceName),
|
||||
(instanceId.value = rowData.value.instanceId),
|
||||
(engine.value = rowData.value.engine),
|
||||
(autoIncrement.value = rowData.value.autoIncrement),
|
||||
(tableComment.value = rowData.value.tableComment),
|
||||
(tableName.value = rowData.value.tableName),
|
||||
(tableCatalog.value = rowData.value.tableCatalog),
|
||||
(tableRows.value = rowData.value.tableRows),
|
||||
(tableCollation.value = rowData.value.tableCollation),
|
||||
(maxDataLength.value = rowData.value.maxDataLength),
|
||||
(indexLength.value = rowData.value.indexLength),
|
||||
(dataLength.value = rowData.value.dataLength),
|
||||
(avgRowLength.value = rowData.value.avgRowLength),
|
||||
(createOptions.value = rowData.value.createOptions),
|
||||
(checkTime.value = rowData.value.checkTime),
|
||||
(checksum.value = rowData.value.checksum),
|
||||
(dataFree.value = rowData.value.dataFree),
|
||||
(rowFormat.value = rowData.value.rowFormat),
|
||||
(tableType.value = rowData.value.tableType),
|
||||
(createTime.value = rowData.value.createTime),
|
||||
(updateTime.value = rowData.value.updateTime),
|
||||
(version.value = rowData.value.version));
|
||||
|
||||
/**
|
||||
* handleJavaCode 事件
|
||||
* @param title
|
||||
* @param row
|
||||
*/
|
||||
const handleJavaCode = (title, row = rowData.value) => {
|
||||
// showJavaCodeDialog.value = true;
|
||||
// dialogTitle.value = title;
|
||||
rowData.value = row;
|
||||
VE_API.system
|
||||
.generateLocalJava({
|
||||
instanceId: rowData.value.instanceId,
|
||||
schemaName: rowData.value.schemaName,
|
||||
tableList: [rowData.value.tableName],
|
||||
absolutePath: javaLocalPath.value,
|
||||
})
|
||||
.then((res) => {
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
console.log(code);
|
||||
}
|
||||
});
|
||||
};
|
||||
/***
|
||||
* 导出insert sql
|
||||
* */
|
||||
const exportInsertSql = async (title, row = rowData.value) => {
|
||||
let res = await VE_API.system.tableExportInsertSql(row, {
|
||||
responseType: "blob",
|
||||
});
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
};
|
||||
/***
|
||||
* 导出 upsert sql
|
||||
* */
|
||||
const exportUpsertSql = async (title, row = rowData.value) => {
|
||||
let res = await VE_API.system.tableExportUpsertSql(row, {
|
||||
responseType: "blob",
|
||||
});
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
};
|
||||
/**
|
||||
* 导出表结构
|
||||
* */
|
||||
const exporTableExcel = async (title, row = rowData.value) => {
|
||||
let res = await VE_API.system.exportTableStructureExcel(row, {
|
||||
responseType: "blob",
|
||||
});
|
||||
let fileName = res.headers["file-name"];
|
||||
// 获取文件名
|
||||
fileName = decodeURIComponent(fileName);
|
||||
let url = window.URL.createObjectURL(new Blob([res.data]));
|
||||
let link = document.createElement("a");
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
// eslint-disable-next-line no-undef
|
||||
link.setAttribute("download", fileName); //指定下载后的文件名,防跳转
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 释放内存
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
};
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value === "添加") {
|
||||
res = await VE_API.system.schemaAdd(form);
|
||||
} else {
|
||||
res = await VE_API.system.schemaEdit({
|
||||
id: rowData.value.id,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 获取表字段
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const getDatabaseTablesColumnList = async () => {
|
||||
let res = await VE_API.system.databaseTablesColumnList({
|
||||
instanceId: rowData.value.instanceId,
|
||||
schemaName: rowData.value.schemaName,
|
||||
tableName: rowData.value.tableName,
|
||||
});
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
res.data.map((item) => {
|
||||
item.label = item.columnName;
|
||||
item.value = item.columnName;
|
||||
});
|
||||
tableColumnList.value = res.data ? res.data : [];
|
||||
}
|
||||
};
|
||||
|
||||
const resourceData = ref([]);
|
||||
const params = reactive({
|
||||
path: "/",
|
||||
});
|
||||
|
||||
const resourceProps = {
|
||||
label: "name",
|
||||
children: "children",
|
||||
isLeaf: "leaf",
|
||||
};
|
||||
|
||||
const loadNode = async (resourceNode, resolve) => {
|
||||
if (resourceNode.level === 0) {
|
||||
return resolve([]);
|
||||
}
|
||||
|
||||
resourceNode.loaded = true;
|
||||
var resourceNodeData = resourceNode.data;
|
||||
if (resourceNodeData.isFile) {
|
||||
return resolve([]);
|
||||
}
|
||||
console.log(resourceNodeData);
|
||||
const { code, data } = await VE_API.system.playFileResourceList({
|
||||
path:
|
||||
"/" === resourceNodeData.rootPath
|
||||
? "/" + resourceNodeData.name
|
||||
: resourceNodeData.rootPath + "/" + resourceNodeData.name,
|
||||
});
|
||||
if (code === 0) {
|
||||
if (data == null) {
|
||||
return resolve([]);
|
||||
}
|
||||
data.map((item) => {
|
||||
item.value = item.absolutePath;
|
||||
});
|
||||
// resourceNode.childNodes = data;
|
||||
console.log(resourceNode);
|
||||
return resolve(data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: 获取列表数据
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const getFileList = async () => {
|
||||
const { code, data } = await VE_API.system.playFileResourceList(params);
|
||||
if (code === 0) {
|
||||
data.map((item) => {
|
||||
item.value = item.absolutePath;
|
||||
});
|
||||
resourceData.value = data;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getFileList();
|
||||
VE_API.system
|
||||
.generateJavaModel({
|
||||
instanceId: rowData.value.instanceId,
|
||||
schemaName: rowData.value.schemaName,
|
||||
tableName: rowData.value.tableName,
|
||||
})
|
||||
.then((res) => {
|
||||
const { code } = res;
|
||||
console.log(code);
|
||||
if (code === 0) {
|
||||
javaModel.value = res.data;
|
||||
}
|
||||
});
|
||||
await getDatabaseTablesColumnList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,214 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- <span>{{ rowData }}</span> -->
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input
|
||||
v-model="projectName"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库实例" prop="instanceId">
|
||||
<el-select
|
||||
v-model="instanceId"
|
||||
placeholder="数据库实例"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in serverList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="项目拥有者" prop="owner">
|
||||
<el-input v-model="owner" placeholder="" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="项目版本" prop="version">
|
||||
<el-input v-model="version" placeholder="" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="ORM框架" prop="ormFrameEnums">
|
||||
<el-select
|
||||
v-model="ormFrameEnums"
|
||||
placeholder="ORM框架"
|
||||
clearable
|
||||
>
|
||||
<el-option label="Lazy" value="UPSERT" />
|
||||
<el-option label="mybatis" value="MYBATIS" />
|
||||
<el-option label="JPA" value="JPA" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="UI框架" prop="uiFrameEnums">
|
||||
<el-select
|
||||
v-model="uiFrameEnums"
|
||||
placeholder="UI框架"
|
||||
clearable
|
||||
>
|
||||
<el-option label="VUE" value="VUE" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
const rules = {
|
||||
projectName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入服务器名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
instanceId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择数据库服务器",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
version: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入项目版本",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
ormFrameEnums: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择ORM框架",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
owner: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入项目拥有者",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
uiFrameEnums: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入项目UI框架",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
projectName: "",
|
||||
instanceId: "",
|
||||
version: "",
|
||||
ormFrameEnums: "",
|
||||
uiFrameEnums: "",
|
||||
owner: "",
|
||||
});
|
||||
const { projectName, instanceId, version, ormFrameEnums, uiFrameEnums, owner } =
|
||||
toRefs(form);
|
||||
const serverList = ref(null);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((projectName.value = rowData.value.projectName),
|
||||
(instanceId.value = rowData.value.instanceId),
|
||||
(version.value = rowData.value.version),
|
||||
(ormFrameEnums.value = rowData.value.ormFrameEnums),
|
||||
(owner.value = rowData.value.owner),
|
||||
(uiFrameEnums.value = rowData.value.uiFrameEnums));
|
||||
|
||||
onMounted(async () => {
|
||||
// 查询数据库实例
|
||||
let res = await VE_API.system.databaseInstanceList();
|
||||
res.data.map((item) => {
|
||||
item.label = item.instanceName;
|
||||
item.value = item.id;
|
||||
serverList.value = res.data ? res.data : [];
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value == "添加") {
|
||||
res = await VE_API.system.projectAdd(form);
|
||||
} else {
|
||||
res = await VE_API.system.projectEdit({
|
||||
id: rowData.value.id,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code == "00") {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="服务器名称" prop="instanceName">
|
||||
<el-input
|
||||
v-model="instanceName"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input
|
||||
v-model="username"
|
||||
placeholder="root"
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" prop="password">
|
||||
<el-input
|
||||
v-model="password"
|
||||
placeholder=""
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="host" prop="host">
|
||||
<el-input
|
||||
v-model="host"
|
||||
placeholder="127.0.0.1"
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="端口" prop="port">
|
||||
<el-input
|
||||
v-model="port"
|
||||
placeholder="6379"
|
||||
clearable
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-input v-model="status" placeholder="" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input v-model="sort" placeholder="" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button style="float: left" @click="testConnection()"
|
||||
>测试连接</el-button
|
||||
>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, toRefs, ref, defineProps, defineEmits } from "vue";
|
||||
|
||||
const rules = {
|
||||
instanceName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入服务器名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入账户",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
host: [
|
||||
{
|
||||
required: true,
|
||||
message: "host不能为空",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
port: [
|
||||
{
|
||||
required: true,
|
||||
message: "端口不能为空",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
driverClassName: [
|
||||
{
|
||||
required: true,
|
||||
message: "driverClassName",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
const form = reactive({
|
||||
instanceName: "",
|
||||
username: "root",
|
||||
password: "",
|
||||
host: "127.0.0.1",
|
||||
port: 6379,
|
||||
status: "",
|
||||
sort: 1,
|
||||
});
|
||||
const { instanceName, username, password, host, port, status, sort } =
|
||||
toRefs(form);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value &&
|
||||
((instanceName.value = rowData.value.instanceName),
|
||||
(username.value = rowData.value.username),
|
||||
(password.value = rowData.value.password),
|
||||
(host.value = rowData.value.host),
|
||||
(port.value = rowData.value.port),
|
||||
(status.value = rowData.value.status),
|
||||
(sort.value = rowData.value.sort));
|
||||
|
||||
/**
|
||||
* 测试连接
|
||||
*/
|
||||
const testConnection = async () => {
|
||||
let res = await VE_API.system.redisInstanceTest(form);
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
console.log("连接成功");
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res;
|
||||
if (title.value === "添加Redis实例") {
|
||||
res = await VE_API.system.redisInstanceStory(form);
|
||||
} else {
|
||||
res = await VE_API.system.redisInstanceStory({
|
||||
id: rowData.value.id,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,8 @@
|
||||
const acwClientMenu = {
|
||||
description: "自动生成代码客户端管理",
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
type: "1",
|
||||
icon: "Lollipop",
|
||||
name: "自动生成代码客户端管理",
|
||||
};
|
||||
export default acwClientMenu;
|
||||