diff --git a/.docker-compose/nginx/conf.d/my.conf b/.docker-compose/nginx/conf.d/my.conf
new file mode 100644
index 0000000..9a1685d
--- /dev/null
+++ b/.docker-compose/nginx/conf.d/my.conf
@@ -0,0 +1,26 @@
+server {
+ listen 8080;
+ server_name localhost;
+
+ #charset koi8-r;
+ #access_log logs/host.access.log main;
+
+ location / {
+ root /usr/share/nginx/html;
+ add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
+ try_files $uri $uri/ /index.html;
+ }
+
+ location /api {
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ rewrite ^/api/(.*)$ /$1 break; #重写
+ proxy_pass http://177.7.0.12:8888; # 设置代理服务器的协议和地址
+ }
+
+ location /api/swagger/index.html {
+ proxy_pass http://127.0.0.1:8888/swagger/index.html;
+ }
+ }
\ No newline at end of file
diff --git a/.docker-compose/nginx/conf.d/nginx.conf b/.docker-compose/nginx/conf.d/nginx.conf
new file mode 100644
index 0000000..29f68b8
--- /dev/null
+++ b/.docker-compose/nginx/conf.d/nginx.conf
@@ -0,0 +1,32 @@
+server {
+ listen 80;
+ server_name localhost;
+
+ #charset koi8-r;
+ #access_log logs/host.access.log main;
+
+ location / {
+ root /usr/share/nginx/html/dist;
+ add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
+ try_files $uri $uri/ /index.html;
+ }
+
+ location /api {
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ rewrite ^/api/(.*)$ /$1 break; #重写
+ proxy_pass http://127.0.0.1:8888; # 设置代理服务器的协议和地址
+ }
+ location /form-generator {
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_pass http://127.0.0.1:8888;
+ }
+ location /api/swagger/index.html {
+ proxy_pass http://127.0.0.1:8888/swagger/index.html;
+ }
+ }
\ No newline at end of file
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..40b878d
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+node_modules/
\ No newline at end of file
diff --git a/.env.development b/.env.development
new file mode 100644
index 0000000..1a8757f
--- /dev/null
+++ b/.env.development
@@ -0,0 +1,10 @@
+ENV = 'development'
+VITE_CLI_PORT = 8080
+VITE_SERVER_PORT = 8888
+VITE_BASE_API = /api
+VITE_BASE_PATH = http://127.0.0.1
+VITE_EDITOR = vscode
+// VITE_EDITOR = webstorm 如果使用webstorm开发且要使用dom定位到代码行功能 请先自定添加 webstorm到环境变量 再将VITE_EDITOR值修改为webstorm
+// 如果使用docker-compose开发模式,设置为下面的地址或本机主机IP
+//VITE_BASE_PATH = http://177.7.0.12
+
diff --git a/.env.production b/.env.production
new file mode 100644
index 0000000..2e3d72d
--- /dev/null
+++ b/.env.production
@@ -0,0 +1,7 @@
+ENV = 'production'
+
+VITE_CLI_PORT = 8080
+VITE_SERVER_PORT = 8888
+VITE_BASE_API = /api
+#下方修改为你的线上ip
+VITE_BASE_PATH = https://demo.gin-vue-admin.com
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..e6529fc
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,4 @@
+build/*.js
+src/assets
+public
+dist
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..4d39f36
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,273 @@
+//@author: [bstdn](https://github.com/bstdn)
+//@description: ESlint 语法检测
+module.exports = {
+ root: true,
+ parserOptions: {
+ parser: 'babel-eslint',
+ sourceType: 'module'
+ },
+ env: {
+ browser: true,
+ node: true,
+ es6: true
+ },
+ extends: ['plugin:vue/recommended', 'eslint:recommended'],
+ globals: {
+ defineProps: "readonly",
+ defineEmits: "readonly",
+ defineExpose: "readonly",
+ withDefaults: "readonly",
+ },
+ rules: {
+ 'vue/no-v-model-argument':'off',
+ 'vue/max-attributes-per-line': [
+ 2,
+ {
+ singleline: 10,
+ multiline: {
+ max: 1,
+ allowFirstLine: false
+ }
+ }
+ ],
+ 'vue/singleline-html-element-content-newline': 'off',
+ 'vue/multiline-html-element-content-newline': 'off',
+ 'vue/name-property-casing': ['error', 'PascalCase'],
+ 'vue/no-v-html': 'off',
+ 'accessor-pairs': 2,
+ 'arrow-spacing': [
+ 2,
+ {
+ before: true,
+ after: true
+ }
+ ],
+ 'block-spacing': [2, 'always'],
+ 'brace-style': [
+ 2,
+ '1tbs',
+ {
+ allowSingleLine: true
+ }
+ ],
+ camelcase: [
+ 0,
+ {
+ properties: 'always'
+ }
+ ],
+ 'comma-dangle': [2, 'only-multiline'],
+ 'comma-spacing': [
+ 2,
+ {
+ before: false,
+ after: true
+ }
+ ],
+ 'comma-style': [2, 'last'],
+ 'constructor-super': 2,
+ curly: [2, 'multi-line'],
+ 'dot-location': [2, 'property'],
+ 'eol-last': 2,
+ eqeqeq: ['error', 'always', { null: 'ignore' }],
+ 'generator-star-spacing': [
+ 2,
+ {
+ before: true,
+ after: true
+ }
+ ],
+ 'handle-callback-err': [2, '^(err|error)$'],
+ indent: [
+ 2,
+ 2,
+ {
+ SwitchCase: 1
+ }
+ ],
+ 'jsx-quotes': [2, 'prefer-single'],
+ 'key-spacing': [
+ 2,
+ {
+ beforeColon: false,
+ afterColon: true
+ }
+ ],
+ 'keyword-spacing': [
+ 2,
+ {
+ before: true,
+ after: true
+ }
+ ],
+ 'new-cap': [
+ 2,
+ {
+ newIsCap: true,
+ capIsNew: false
+ }
+ ],
+ 'new-parens': 2,
+ 'no-array-constructor': 2,
+ 'no-caller': 2,
+ 'no-console': 'off',
+ 'no-class-assign': 2,
+ 'no-cond-assign': 2,
+ 'no-const-assign': 2,
+ 'no-control-regex': 0,
+ 'no-delete-var': 2,
+ 'no-dupe-args': 2,
+ 'no-dupe-class-members': 2,
+ 'no-dupe-keys': 2,
+ 'no-duplicate-case': 2,
+ 'no-empty-character-class': 2,
+ 'no-empty-pattern': 2,
+ 'no-eval': 2,
+ 'no-ex-assign': 2,
+ 'no-extend-native': 2,
+ 'no-extra-bind': 2,
+ 'no-extra-boolean-cast': 2,
+ 'no-extra-parens': [2, 'functions'],
+ 'no-fallthrough': 2,
+ 'no-floating-decimal': 2,
+ 'no-func-assign': 2,
+ 'no-implied-eval': 2,
+ 'no-inner-declarations': [2, 'functions'],
+ 'no-invalid-regexp': 2,
+ 'no-irregular-whitespace': 2,
+ 'no-iterator': 2,
+ 'no-label-var': 2,
+ 'no-labels': [
+ 2,
+ {
+ allowLoop: false,
+ allowSwitch: false
+ }
+ ],
+ 'no-lone-blocks': 2,
+ 'no-mixed-spaces-and-tabs': 2,
+ 'no-multi-spaces': 2,
+ 'no-multi-str': 2,
+ 'no-multiple-empty-lines': [
+ 2,
+ {
+ max: 1
+ }
+ ],
+ 'no-native-reassign': 2,
+ 'no-negated-in-lhs': 2,
+ 'no-new-object': 2,
+ 'no-new-require': 2,
+ 'no-new-symbol': 2,
+ 'no-new-wrappers': 2,
+ 'no-obj-calls': 2,
+ 'no-octal': 2,
+ 'no-octal-escape': 2,
+ 'no-path-concat': 2,
+ 'no-proto': 2,
+ 'no-redeclare': 2,
+ 'no-regex-spaces': 2,
+ 'no-return-assign': [2, 'except-parens'],
+ 'no-self-assign': 2,
+ 'no-self-compare': 2,
+ 'no-sequences': 2,
+ 'no-shadow-restricted-names': 2,
+ 'no-spaced-func': 2,
+ 'no-sparse-arrays': 2,
+ 'no-this-before-super': 2,
+ 'no-throw-literal': 2,
+ 'no-trailing-spaces': 2,
+ 'no-undef': 'off',
+ 'no-undef-init': 2,
+ 'no-unexpected-multiline': 2,
+ 'no-unmodified-loop-condition': 2,
+ 'no-unneeded-ternary': [
+ 2,
+ {
+ defaultAssignment: false
+ }
+ ],
+ 'no-unreachable': 2,
+ 'no-unsafe-finally': 2,
+ 'no-unused-vars': [
+ 2,
+ {
+ vars: 'all',
+ args: 'none'
+ }
+ ],
+ 'no-useless-call': 2,
+ 'no-useless-computed-key': 2,
+ 'no-useless-constructor': 2,
+ 'no-useless-escape': 0,
+ 'no-whitespace-before-property': 2,
+ 'no-with': 2,
+ 'one-var': [
+ 2,
+ {
+ initialized: 'never'
+ }
+ ],
+ 'operator-linebreak': [
+ 2,
+ 'after',
+ {
+ overrides: {
+ '?': 'before',
+ ':': 'before'
+ }
+ }
+ ],
+ 'padded-blocks': [2, 'never'],
+ quotes: [
+ 2,
+ 'single',
+ {
+ avoidEscape: true,
+ allowTemplateLiterals: true
+ }
+ ],
+ semi: [2, 'never'],
+ 'semi-spacing': [
+ 2,
+ {
+ before: false,
+ after: true
+ }
+ ],
+ 'space-before-blocks': [2, 'always'],
+ 'space-before-function-paren': [2, 'never'],
+ 'space-in-parens': [2, 'never'],
+ 'space-infix-ops': 2,
+ 'space-unary-ops': [
+ 2,
+ {
+ words: true,
+ nonwords: false
+ }
+ ],
+ 'spaced-comment': [
+ 2,
+ 'always',
+ {
+ markers: ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
+ }
+ ],
+ 'template-curly-spacing': [2, 'never'],
+ 'use-isnan': 2,
+ 'valid-typeof': 2,
+ 'wrap-iife': [2, 'any'],
+ 'yield-star-spacing': [2, 'both'],
+ yoda: [2, 'never'],
+ 'prefer-const': 2,
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
+ 'object-curly-spacing': [
+ 2,
+ 'always',
+ {
+ objectsInObjects: false
+ }
+ ],
+ 'array-bracket-spacing': [2, 'never']
+ }
+}
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..31f329c
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,15 @@
+FROM node:16
+
+WORKDIR /gva_web/
+COPY . .
+
+RUN yarn && yarn build
+
+FROM nginx:alpine
+LABEL MAINTAINER="SliverHorn@sliver_horn@qq.com"
+
+COPY .docker-compose/nginx/conf.d/my.conf /etc/nginx/conf.d/my.conf
+COPY --from=0 /gva_web/dist /usr/share/nginx/html
+RUN cat /etc/nginx/nginx.conf
+RUN cat /etc/nginx/conf.d/my.conf
+RUN ls -al /usr/share/nginx/html
diff --git a/README-CN.md b/README-CN.md
new file mode 100644
index 0000000..c947159
--- /dev/null
+++ b/README-CN.md
@@ -0,0 +1,104 @@
+# qm-plus-vue-page
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Run your tests
+```
+npm run test
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).
+
+整理代码结构
+``` lua
+web
+ ├── babel.config.js
+ ├── Dockerfile
+ ├── favicon.ico
+ ├── index.html -- 主页面
+ ├── limit.js -- 助手代码
+ ├── package.json -- 包管理器代码
+ ├── src -- 源代码
+ │ ├── api -- api 组
+ │ ├── App.vue -- 主页面
+ │ ├── assets -- 静态资源
+ │ ├── components -- 全局组件
+ │ ├── core -- gva 组件包
+ │ │ ├── config.js -- gva网站配置文件
+ │ │ ├── gin-vue-admin.js -- 注册欢迎文件
+ │ │ └── global.js -- 统一导入文件
+ │ ├── directive -- v-auth 注册文件
+ │ ├── main.js -- 主文件
+ │ ├── permission.js -- 路由中间件
+ │ ├── pinia -- pinia 状态管理器,取代vuex
+ │ │ ├── index.js -- 入口文件
+ │ │ └── modules -- modules
+ │ │ ├── dictionary.js
+ │ │ ├── router.js
+ │ │ └── user.js
+ │ ├── router -- 路由声明文件
+ │ │ └── index.js
+ │ ├── style -- 全局样式
+ │ │ ├── base.scss
+ │ │ ├── basics.scss
+ │ │ ├── element_visiable.scss -- 此处可以全局覆盖 element-plus 样式
+ │ │ ├── iconfont.css -- 顶部几个icon的样式文件
+ │ │ ├── main.scss
+ │ │ ├── mobile.scss
+ │ │ └── newLogin.scss
+ │ ├── utils -- 方法包库
+ │ │ ├── asyncRouter.js -- 动态路由相关
+ │ │ ├── btnAuth.js -- 动态权限按钮相关
+ │ │ ├── bus.js -- 全局mitt声明文件
+ │ │ ├── date.js -- 日期相关
+ │ │ ├── dictionary.js -- 获取字典方法
+ │ │ ├── downloadImg.js -- 下载图片方法
+ │ │ ├── format.js -- 格式整理相关
+ │ │ ├── image.js -- 图片相关方法
+ │ │ ├── page.js -- 设置页面标题
+ │ │ ├── request.js -- 请求
+ │ │ └── stringFun.js -- 字符串文件
+ | ├── view -- 主要view代码
+ | | ├── about -- 关于我们
+ | | ├── dashboard -- 面板
+ | | ├── error -- 错误
+ | | ├── example --上传案例
+ | | ├── iconList -- icon列表
+ | | ├── init -- 初始化数据
+ | | | ├── index -- 新版本
+ | | | ├── init -- 旧版本
+ | | ├── layout -- layout约束页面
+ | | | ├── aside
+ | | | ├── bottomInfo -- bottomInfo
+ | | | ├── screenfull -- 全屏设置
+ | | | ├── setting -- 系统设置
+ | | | └── index.vue -- base 约束
+ | | ├── login --登录
+ | | ├── person --个人中心
+ | | ├── superAdmin -- 超级管理员操作
+ | | ├── system -- 系统检测页面
+ | | ├── systemTools -- 系统配置相关页面
+ | | └── routerHolder.vue -- page 入口页面
+ ├── vite.config.js -- vite 配置文件
+ └── yarn.lock
+
+```
\ No newline at end of file
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 0000000..f064a5a
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,8 @@
+module.exports = {
+ presets: [
+ '@vue/cli-plugin-babel/preset'
+ ],
+ 'plugins': [
+
+ ]
+}
diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 0000000..ee520ce
Binary files /dev/null and b/favicon.ico differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..2b92c29
--- /dev/null
+++ b/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/limit.js b/limit.js
new file mode 100644
index 0000000..d857ee3
--- /dev/null
+++ b/limit.js
@@ -0,0 +1,37 @@
+// 运行项目前通过node执行此脚本 (此脚本与 node_modules 目录同级)
+const fs = require('fs')
+const path = require('path')
+const wfPath = path.resolve(__dirname, './node_modules/.bin')
+
+fs.readdir(wfPath, (err, files) => {
+ if (err) {
+ console.log(err)
+ } else {
+ if (files.length != 0) {
+ files.forEach((item) => {
+ if (item.split('.')[1] === 'cmd') {
+ replaceStr(`${wfPath}/${item}`, /"%_prog%"/, '%_prog%')
+ }
+ })
+ }
+ }
+})
+
+// 参数:[文件路径、 需要修改的字符串、修改后的字符串] (替换对应文件内字符串的公共函数)
+function replaceStr(filePath, sourceRegx, targetSrt) {
+ fs.readFile(filePath, (err, data) => {
+ if (err) {
+ console.log(err)
+ } else {
+ let str = data.toString()
+ str = str.replace(sourceRegx, targetSrt)
+ fs.writeFile(filePath, str, (err) => {
+ if(err){
+ console.log(err)
+ }else{
+ console.log("\x1B[42m%s\x1B[0m","文件修改成功")
+ }
+ })
+ }
+ })
+}
\ No newline at end of file
diff --git a/openDocument.js b/openDocument.js
new file mode 100644
index 0000000..2d52541
--- /dev/null
+++ b/openDocument.js
@@ -0,0 +1,23 @@
+/*
+ 商用代码公司自用产品无需授权
+ 若作为代码出售的产品(任何涉及代码交付第三方作为后续开发)必须保留此脚本
+ 或标注原作者信息
+ 否则将依法维权
+*/
+
+var child_process = require('child_process')
+
+var url = 'https://www.gin-vue-admin.com'
+var cmd = ''
+console.log(process.platform)
+switch (process.platform) {
+ case 'win32':
+ cmd = 'start'
+ child_process.exec(cmd + ' ' + url)
+ break
+
+ case 'darwin':
+ cmd = 'open'
+ child_process.exec(cmd + ' ' + url)
+ break
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..b90138c
--- /dev/null
+++ b/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "gin-vue-admin",
+ "version": "2.5.5",
+ "private": true,
+ "scripts": {
+ "serve": "node openDocument.js && vite --host --mode development",
+ "build": "vite build --mode production",
+ "limit-build": "npm install increase-memory-limit-fixbug cross-env -g && npm run fix-memory-limit && node ./limit && npm run build",
+ "preview": "vite preview",
+ "fix-memory-limit": "cross-env LIMIT=4096 increase-memory-limit"
+ },
+ "dependencies": {
+ "@element-plus/icons-vue": "^0.2.7",
+ "axios": "^0.19.2",
+ "core-js": "^3.6.5",
+ "echarts": "5.3.2",
+ "element-plus": "2.2.9",
+ "highlight.js": "^10.6.0",
+ "marked": "^2.0.0",
+ "mitt": "^3.0.0",
+ "nprogress": "^0.2.0",
+ "path": "^0.12.7",
+ "pinia": "^2.0.9",
+ "qs": "^6.8.0",
+ "quill": "^1.3.7",
+ "screenfull": "^5.0.2",
+ "spark-md5": "^3.0.1",
+ "vue": "^3.2.25",
+ "vue-router": "^4.0.0-0"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-legacy": "^2.0.0",
+ "@vitejs/plugin-vue": "^3.0.1",
+ "@vue/cli-plugin-babel": "~4.5.0",
+ "@vue/cli-plugin-eslint": "~4.5.0",
+ "@vue/cli-plugin-router": "~4.5.0",
+ "@vue/cli-plugin-vuex": "~4.5.0",
+ "@vue/cli-service": "~4.5.0",
+ "@vue/compiler-sfc": "^3.1.5",
+ "babel-eslint": "^10.1.0",
+ "babel-plugin-import": "^1.13.3",
+ "chalk": "^4.1.2",
+ "dotenv": "^10.0.0",
+ "eslint": "^6.7.2",
+ "eslint-plugin-vue": "^7.0.0",
+ "sass": "^1.54.0",
+ "terser": "^5.4.0",
+ "vite": "^3.0.1",
+ "vite-plugin-banner": "^0.1.3",
+ "vite-plugin-importer": "^0.2.5"
+ }
+}
\ No newline at end of file
diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 0000000..9eaaf40
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/api/api.js b/src/api/api.js
new file mode 100644
index 0000000..78554ac
--- /dev/null
+++ b/src/api/api.js
@@ -0,0 +1,132 @@
+import service from '@/utils/request'
+
+// @Tags api
+// @Summary 分页获取角色列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body modelInterface.PageInfo true "分页获取用户列表"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /api/getApiList [post]
+// {
+// page int
+// pageSize int
+// }
+export const getApiList = (data) => {
+ return service({
+ url: '/api/getApiList',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags Api
+// @Summary 创建基础api
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.CreateApiParams true "创建api"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /api/createApi [post]
+export const createApi = (data) => {
+ return service({
+ url: '/api/createApi',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags menu
+// @Summary 根据id获取菜单
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.GetById true "根据id获取菜单"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /menu/getApiById [post]
+export const getApiById = (data) => {
+ return service({
+ url: '/api/getApiById',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags Api
+// @Summary 更新api
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.CreateApiParams true "更新api"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"更新成功"}"
+// @Router /api/updateApi [post]
+export const updateApi = (data) => {
+ return service({
+ url: '/api/updateApi',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags Api
+// @Summary 更新api
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.CreateApiParams true "更新api"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"更新成功"}"
+// @Router /api/setAuthApi [post]
+export const setAuthApi = (data) => {
+ return service({
+ url: '/api/setAuthApi',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags Api
+// @Summary 获取所有的Api 不分页
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /api/getAllApis [post]
+export const getAllApis = (data) => {
+ return service({
+ url: '/api/getAllApis',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags Api
+// @Summary 删除指定api
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body dbModel.Api true "删除api"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /api/deleteApi [post]
+export const deleteApi = (data) => {
+ return service({
+ url: '/api/deleteApi',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags SysApi
+// @Summary 删除选中Api
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.IdsReq true "ID"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /api/deleteApisByIds [delete]
+export const deleteApisByIds = (data) => {
+ return service({
+ url: '/api/deleteApisByIds',
+ method: 'delete',
+ data
+ })
+}
diff --git a/src/api/authority.js b/src/api/authority.js
new file mode 100644
index 0000000..0401273
--- /dev/null
+++ b/src/api/authority.js
@@ -0,0 +1,85 @@
+import service from '@/utils/request'
+// @Router /authority/getAuthorityList [post]
+export const getAuthorityList = (data) => {
+ return service({
+ url: '/authority/getAuthorityList',
+ method: 'post',
+ data
+ })
+}
+
+// @Summary 删除角色
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body {authorityId uint} true "删除角色"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /authority/deleteAuthority [post]
+export const deleteAuthority = (data) => {
+ return service({
+ url: '/authority/deleteAuthority',
+ method: 'post',
+ data
+ })
+}
+
+// @Summary 创建角色
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.CreateAuthorityPatams true "创建角色"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /authority/createAuthority [post]
+export const createAuthority = (data) => {
+ return service({
+ url: '/authority/createAuthority',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags authority
+// @Summary 拷贝角色
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.CreateAuthorityPatams true "拷贝角色"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"拷贝成功"}"
+// @Router /authority/copyAuthority [post]
+export const copyAuthority = (data) => {
+ return service({
+ url: '/authority/copyAuthority',
+ method: 'post',
+ data
+ })
+}
+
+// @Summary 设置角色资源权限
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body sysModel.SysAuthority true "设置角色资源权限"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"设置成功"}"
+// @Router /authority/setDataAuthority [post]
+export const setDataAuthority = (data) => {
+ return service({
+ url: '/authority/setDataAuthority',
+ method: 'post',
+ data
+ })
+}
+
+// @Summary 修改角色
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysAuthority true "修改角色"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"设置成功"}"
+// @Router /authority/setDataAuthority [post]
+export const updateAuthority = (data) => {
+ return service({
+ url: '/authority/updateAuthority',
+ method: 'put',
+ data
+ })
+}
diff --git a/src/api/authorityBtn.js b/src/api/authorityBtn.js
new file mode 100644
index 0000000..9fe73bf
--- /dev/null
+++ b/src/api/authorityBtn.js
@@ -0,0 +1,27 @@
+
+import service from '@/utils/request'
+
+export const getAuthorityBtnApi = (data) => {
+ return service({
+ url: '/authorityBtn/getAuthorityBtn',
+ method: 'post',
+ data
+ })
+}
+
+export const setAuthorityBtnApi = (data) => {
+ return service({
+ url: '/authorityBtn/setAuthorityBtn',
+ method: 'post',
+ data
+ })
+}
+
+export const canRemoveAuthorityBtnApi = (params) => {
+ return service({
+ url: '/authorityBtn/canRemoveAuthorityBtn',
+ method: 'post',
+ params
+ })
+}
+
diff --git a/src/api/autoCode.js b/src/api/autoCode.js
new file mode 100644
index 0000000..08f456a
--- /dev/null
+++ b/src/api/autoCode.js
@@ -0,0 +1,134 @@
+import service from '@/utils/request'
+
+export const preview = (data) => {
+ return service({
+ url: '/autoCode/preview',
+ method: 'post',
+ data
+ })
+}
+
+export const createTemp = (data) => {
+ return service({
+ url: '/autoCode/createTemp',
+ method: 'post',
+ data,
+ responseType: 'blob'
+ })
+}
+
+// @Tags SysApi
+// @Summary 获取当前所有数据库
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
+// @Router /autoCode/getDatabase [get]
+export const getDB = (params) => {
+ return service({
+ url: '/autoCode/getDB',
+ method: 'get',
+ params
+ })
+}
+
+// @Tags SysApi
+// @Summary 获取当前数据库所有表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
+// @Router /autoCode/getTables [get]
+export const getTable = (params) => {
+ return service({
+ url: '/autoCode/getTables',
+ method: 'get',
+ params
+ })
+}
+
+// @Tags SysApi
+// @Summary 获取当前数据库所有表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
+// @Router /autoCode/getColumn [get]
+export const getColumn = (params) => {
+ return service({
+ url: '/autoCode/getColumn',
+ method: 'get',
+ params
+ })
+}
+
+export const getSysHistory = (data) => {
+ return service({
+ url: '/autoCode/getSysHistory',
+ method: 'post',
+ data
+ })
+}
+
+export const rollback = (data) => {
+ return service({
+ url: '/autoCode/rollback',
+ method: 'post',
+ data
+ })
+}
+
+export const getMeta = (data) => {
+ return service({
+ url: '/autoCode/getMeta',
+ method: 'post',
+ data
+ })
+}
+
+export const delSysHistory = (data) => {
+ return service({
+ url: '/autoCode/delSysHistory',
+ method: 'post',
+ data
+ })
+}
+
+export const createPackageApi = (data) => {
+ return service({
+ url: '/autoCode/createPackage',
+ method: 'post',
+ data
+ })
+}
+
+export const getPackageApi = () => {
+ return service({
+ url: '/autoCode/getPackage',
+ method: 'post'
+ })
+}
+
+export const deletePackageApi = (data) => {
+ return service({
+ url: '/autoCode/delPackage',
+ method: 'post',
+ data
+ })
+}
+
+export const createPlugApi = (data) => {
+ return service({
+ url: '/autoCode/createPlug',
+ method: 'post',
+ data
+ })
+}
+
+export const installPlug = (data) => {
+ return service({
+ url: '/autoCode/installPlug',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/api/breakpoint.js b/src/api/breakpoint.js
new file mode 100644
index 0000000..1dbfba2
--- /dev/null
+++ b/src/api/breakpoint.js
@@ -0,0 +1,43 @@
+import service from '@/utils/request'
+// @Summary 设置角色资源权限
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body sysModel.SysAuthority true "设置角色资源权限"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"设置成功"}"
+// @Router /authority/setDataAuthority [post]
+
+export const findFile = (params) => {
+ return service({
+ url: '/fileUploadAndDownload/findFile',
+ method: 'get',
+ params
+ })
+}
+
+export const breakpointContinue = (data) => {
+ return service({
+ url: '/fileUploadAndDownload/breakpointContinue',
+ method: 'post',
+ donNotShowLoading: true,
+ headers: { 'Content-Type': 'multipart/form-data' },
+ data
+ })
+}
+
+export const breakpointContinueFinish = (params) => {
+ return service({
+ url: '/fileUploadAndDownload/breakpointContinueFinish',
+ method: 'post',
+ params
+ })
+}
+
+export const removeChunk = (data, params) => {
+ return service({
+ url: '/fileUploadAndDownload/removeChunk',
+ method: 'post',
+ data,
+ params
+ })
+}
diff --git a/src/api/casbin.js b/src/api/casbin.js
new file mode 100644
index 0000000..802e130
--- /dev/null
+++ b/src/api/casbin.js
@@ -0,0 +1,32 @@
+import service from '@/utils/request'
+// @Tags authority
+// @Summary 更改角色api权限
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.CreateAuthorityPatams true "更改角色api权限"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /casbin/UpdateCasbin [post]
+export const UpdateCasbin = (data) => {
+ return service({
+ url: '/casbin/updateCasbin',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags casbin
+// @Summary 获取权限列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.CreateAuthorityPatams true "获取权限列表"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /casbin/getPolicyPathByAuthorityId [post]
+export const getPolicyPathByAuthorityId = (data) => {
+ return service({
+ url: '/casbin/getPolicyPathByAuthorityId',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/api/customer.js b/src/api/customer.js
new file mode 100644
index 0000000..4776f1c
--- /dev/null
+++ b/src/api/customer.js
@@ -0,0 +1,80 @@
+import service from '@/utils/request'
+// @Tags SysApi
+// @Summary 删除客户
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body dbModel.ExaCustomer true "删除客户"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /customer/customer [post]
+export const createExaCustomer = (data) => {
+ return service({
+ url: '/customer/customer',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags SysApi
+// @Summary 更新客户信息
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body dbModel.ExaCustomer true "更新客户信息"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /customer/customer [put]
+export const updateExaCustomer = (data) => {
+ return service({
+ url: '/customer/customer',
+ method: 'put',
+ data
+ })
+}
+
+// @Tags SysApi
+// @Summary 创建客户
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body dbModel.ExaCustomer true "创建客户"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /customer/customer [delete]
+export const deleteExaCustomer = (data) => {
+ return service({
+ url: '/customer/customer',
+ method: 'delete',
+ data
+ })
+}
+
+// @Tags SysApi
+// @Summary 获取单一客户信息
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body dbModel.ExaCustomer true "获取单一客户信息"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /customer/customer [get]
+export const getExaCustomer = (params) => {
+ return service({
+ url: '/customer/customer',
+ method: 'get',
+ params
+ })
+}
+
+// @Tags SysApi
+// @Summary 获取权限客户列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body modelInterface.PageInfo true "获取权限客户列表"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /customer/customerList [get]
+export const getExaCustomerList = (params) => {
+ return service({
+ url: '/customer/customerList',
+ method: 'get',
+ params
+ })
+}
diff --git a/src/api/email.js b/src/api/email.js
new file mode 100644
index 0000000..c2f16f4
--- /dev/null
+++ b/src/api/email.js
@@ -0,0 +1,14 @@
+import service from '@/utils/request'
+// @Tags email
+// @Summary 发送测试邮件
+// @Security ApiKeyAuth
+// @Produce application/json
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
+// @Router /email/emailTest [post]
+export const emailTest = (data) => {
+ return service({
+ url: '/email/emailTest',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/api/fileUploadAndDownload.js b/src/api/fileUploadAndDownload.js
new file mode 100644
index 0000000..0a5d021
--- /dev/null
+++ b/src/api/fileUploadAndDownload.js
@@ -0,0 +1,44 @@
+import service from '@/utils/request'
+// @Tags FileUploadAndDownload
+// @Summary 分页文件列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body modelInterface.PageInfo true "分页获取文件户列表"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /fileUploadAndDownload/getFileList [post]
+export const getFileList = (data) => {
+ return service({
+ url: '/fileUploadAndDownload/getFileList',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags FileUploadAndDownload
+// @Summary 删除文件
+// @Security ApiKeyAuth
+// @Produce application/json
+// @Param data body dbModel.FileUploadAndDownload true "传入文件里面id即可"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"返回成功"}"
+// @Router /fileUploadAndDownload/deleteFile [post]
+export const deleteFile = (data) => {
+ return service({
+ url: '/fileUploadAndDownload/deleteFile',
+ method: 'post',
+ data
+ })
+}
+
+/**
+ * 编辑文件名或者备注
+ * @param data
+ * @returns {*}
+ */
+export const editFileName = (data) => {
+ return service({
+ url: '/fileUploadAndDownload/editFileName',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/api/github.js b/src/api/github.js
new file mode 100644
index 0000000..4dc4eed
--- /dev/null
+++ b/src/api/github.js
@@ -0,0 +1,17 @@
+import axios from 'axios'
+
+const service = axios.create()
+
+export function Commits(page) {
+ return service({
+ url: 'https://api.github.com/repos/flipped-aurora/gin-vue-admin/commits?page=' + page,
+ method: 'get'
+ })
+}
+
+export function Members() {
+ return service({
+ url: 'https://api.github.com/orgs/FLIPPED-AURORA/members',
+ method: 'get'
+ })
+}
diff --git a/src/api/initdb.js b/src/api/initdb.js
new file mode 100644
index 0000000..ff009c7
--- /dev/null
+++ b/src/api/initdb.js
@@ -0,0 +1,26 @@
+import service from '@/utils/request'
+// @Tags InitDB
+// @Summary 初始化用户数据库
+// @Produce application/json
+// @Param data body request.InitDB true "初始化数据库参数"
+// @Success 200 {string} string "{"code":0,"data":{},"msg":"自动创建数据库成功"}"
+// @Router /init/initdb [post]
+export const initDB = (data) => {
+ return service({
+ url: '/init/initdb',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags CheckDB
+// @Summary 初始化用户数据库
+// @Produce application/json
+// @Success 200 {string} string "{"code":0,"data":{},"msg":"探测完成"}"
+// @Router /init/checkdb [post]
+export const checkDB = () => {
+ return service({
+ url: '/init/checkdb',
+ method: 'post'
+ })
+}
diff --git a/src/api/jwt.js b/src/api/jwt.js
new file mode 100644
index 0000000..811ffc4
--- /dev/null
+++ b/src/api/jwt.js
@@ -0,0 +1,14 @@
+import service from '@/utils/request'
+// @Tags jwt
+// @Summary jwt加入黑名单
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"拉黑成功"}"
+// @Router /jwt/jsonInBlacklist [post]
+export const jsonInBlacklist = () => {
+ return service({
+ url: '/jwt/jsonInBlacklist',
+ method: 'post'
+ })
+}
diff --git a/src/api/menu.js b/src/api/menu.js
new file mode 100644
index 0000000..163b5a6
--- /dev/null
+++ b/src/api/menu.js
@@ -0,0 +1,113 @@
+import service from '@/utils/request'
+// @Summary 用户登录 获取动态路由
+// @Produce application/json
+// @Param 可以什么都不填 调一下即可
+// @Router /menu/getMenu [post]
+export const asyncMenu = () => {
+ return service({
+ url: '/menu/getMenu',
+ method: 'post'
+ })
+}
+
+// @Summary 获取menu列表
+// @Produce application/json
+// @Param {
+// page int
+// pageSize int
+// }
+// @Router /menu/getMenuList [post]
+export const getMenuList = (data) => {
+ return service({
+ url: '/menu/getMenuList',
+ method: 'post',
+ data
+ })
+}
+
+// @Summary 新增基础menu
+// @Produce application/json
+// @Param menu Object
+// @Router /menu/getMenuList [post]
+export const addBaseMenu = (data) => {
+ return service({
+ url: '/menu/addBaseMenu',
+ method: 'post',
+ data
+ })
+}
+
+// @Summary 获取基础路由列表
+// @Produce application/json
+// @Param 可以什么都不填 调一下即可
+// @Router /menu/getBaseMenuTree [post]
+export const getBaseMenuTree = () => {
+ return service({
+ url: '/menu/getBaseMenuTree',
+ method: 'post'
+ })
+}
+
+// @Summary 添加用户menu关联关系
+// @Produce application/json
+// @Param menus Object authorityId string
+// @Router /menu/getMenuList [post]
+export const addMenuAuthority = (data) => {
+ return service({
+ url: '/menu/addMenuAuthority',
+ method: 'post',
+ data
+ })
+}
+
+// @Summary 获取用户menu关联关系
+// @Produce application/json
+// @Param authorityId string
+// @Router /menu/getMenuAuthority [post]
+export const getMenuAuthority = (data) => {
+ return service({
+ url: '/menu/getMenuAuthority',
+ method: 'post',
+ data
+ })
+}
+
+// @Summary 删除menu
+// @Produce application/json
+// @Param ID float64
+// @Router /menu/deleteBaseMenu [post]
+export const deleteBaseMenu = (data) => {
+ return service({
+ url: '/menu/deleteBaseMenu',
+ method: 'post',
+ data
+ })
+}
+
+// @Summary 修改menu列表
+// @Produce application/json
+// @Param menu Object
+// @Router /menu/updateBaseMenu [post]
+export const updateBaseMenu = (data) => {
+ return service({
+ url: '/menu/updateBaseMenu',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags menu
+// @Summary 根据id获取菜单
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.GetById true "根据id获取菜单"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /menu/getBaseMenuById [post]
+export const getBaseMenuById = (data) => {
+ return service({
+ url: '/menu/getBaseMenuById',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/api/sysDictionary.js b/src/api/sysDictionary.js
new file mode 100644
index 0000000..f5d6c86
--- /dev/null
+++ b/src/api/sysDictionary.js
@@ -0,0 +1,80 @@
+import service from '@/utils/request'
+// @Tags SysDictionary
+// @Summary 创建SysDictionary
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysDictionary true "创建SysDictionary"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /sysDictionary/createSysDictionary [post]
+export const createSysDictionary = (data) => {
+ return service({
+ url: '/sysDictionary/createSysDictionary',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags SysDictionary
+// @Summary 删除SysDictionary
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysDictionary true "删除SysDictionary"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /sysDictionary/deleteSysDictionary [delete]
+export const deleteSysDictionary = (data) => {
+ return service({
+ url: '/sysDictionary/deleteSysDictionary',
+ method: 'delete',
+ data
+ })
+}
+
+// @Tags SysDictionary
+// @Summary 更新SysDictionary
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysDictionary true "更新SysDictionary"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
+// @Router /sysDictionary/updateSysDictionary [put]
+export const updateSysDictionary = (data) => {
+ return service({
+ url: '/sysDictionary/updateSysDictionary',
+ method: 'put',
+ data
+ })
+}
+
+// @Tags SysDictionary
+// @Summary 用id查询SysDictionary
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysDictionary true "用id查询SysDictionary"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
+// @Router /sysDictionary/findSysDictionary [get]
+export const findSysDictionary = (params) => {
+ return service({
+ url: '/sysDictionary/findSysDictionary',
+ method: 'get',
+ params
+ })
+}
+
+// @Tags SysDictionary
+// @Summary 分页获取SysDictionary列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.PageInfo true "分页获取SysDictionary列表"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /sysDictionary/getSysDictionaryList [get]
+export const getSysDictionaryList = (params) => {
+ return service({
+ url: '/sysDictionary/getSysDictionaryList',
+ method: 'get',
+ params
+ })
+}
diff --git a/src/api/sysDictionaryDetail.js b/src/api/sysDictionaryDetail.js
new file mode 100644
index 0000000..d4f8772
--- /dev/null
+++ b/src/api/sysDictionaryDetail.js
@@ -0,0 +1,80 @@
+import service from '@/utils/request'
+// @Tags SysDictionaryDetail
+// @Summary 创建SysDictionaryDetail
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysDictionaryDetail true "创建SysDictionaryDetail"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /sysDictionaryDetail/createSysDictionaryDetail [post]
+export const createSysDictionaryDetail = (data) => {
+ return service({
+ url: '/sysDictionaryDetail/createSysDictionaryDetail',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags SysDictionaryDetail
+// @Summary 删除SysDictionaryDetail
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysDictionaryDetail true "删除SysDictionaryDetail"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /sysDictionaryDetail/deleteSysDictionaryDetail [delete]
+export const deleteSysDictionaryDetail = (data) => {
+ return service({
+ url: '/sysDictionaryDetail/deleteSysDictionaryDetail',
+ method: 'delete',
+ data
+ })
+}
+
+// @Tags SysDictionaryDetail
+// @Summary 更新SysDictionaryDetail
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysDictionaryDetail true "更新SysDictionaryDetail"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
+// @Router /sysDictionaryDetail/updateSysDictionaryDetail [put]
+export const updateSysDictionaryDetail = (data) => {
+ return service({
+ url: '/sysDictionaryDetail/updateSysDictionaryDetail',
+ method: 'put',
+ data
+ })
+}
+
+// @Tags SysDictionaryDetail
+// @Summary 用id查询SysDictionaryDetail
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysDictionaryDetail true "用id查询SysDictionaryDetail"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
+// @Router /sysDictionaryDetail/findSysDictionaryDetail [get]
+export const findSysDictionaryDetail = (params) => {
+ return service({
+ url: '/sysDictionaryDetail/findSysDictionaryDetail',
+ method: 'get',
+ params
+ })
+}
+
+// @Tags SysDictionaryDetail
+// @Summary 分页获取SysDictionaryDetail列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.PageInfo true "分页获取SysDictionaryDetail列表"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /sysDictionaryDetail/getSysDictionaryDetailList [get]
+export const getSysDictionaryDetailList = (params) => {
+ return service({
+ url: '/sysDictionaryDetail/getSysDictionaryDetailList',
+ method: 'get',
+ params
+ })
+}
diff --git a/src/api/sysOperationRecord.js b/src/api/sysOperationRecord.js
new file mode 100644
index 0000000..4428c03
--- /dev/null
+++ b/src/api/sysOperationRecord.js
@@ -0,0 +1,48 @@
+import service from '@/utils/request'
+// @Tags SysOperationRecord
+// @Summary 删除SysOperationRecord
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysOperationRecord true "删除SysOperationRecord"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /sysOperationRecord/deleteSysOperationRecord [delete]
+export const deleteSysOperationRecord = (data) => {
+ return service({
+ url: '/sysOperationRecord/deleteSysOperationRecord',
+ method: 'delete',
+ data
+ })
+}
+
+// @Tags SysOperationRecord
+// @Summary 删除SysOperationRecord
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.IdsReq true "删除SysOperationRecord"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /sysOperationRecord/deleteSysOperationRecord [delete]
+export const deleteSysOperationRecordByIds = (data) => {
+ return service({
+ url: '/sysOperationRecord/deleteSysOperationRecordByIds',
+ method: 'delete',
+ data
+ })
+}
+
+// @Tags SysOperationRecord
+// @Summary 分页获取SysOperationRecord列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.PageInfo true "分页获取SysOperationRecord列表"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /sysOperationRecord/getSysOperationRecordList [get]
+export const getSysOperationRecordList = (params) => {
+ return service({
+ url: '/sysOperationRecord/getSysOperationRecordList',
+ method: 'get',
+ params
+ })
+}
diff --git a/src/api/system.js b/src/api/system.js
new file mode 100644
index 0000000..27b715e
--- /dev/null
+++ b/src/api/system.js
@@ -0,0 +1,42 @@
+import service from '@/utils/request'
+// @Tags systrm
+// @Summary 获取配置文件内容
+// @Security ApiKeyAuth
+// @Produce application/json
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
+// @Router /system/getSystemConfig [post]
+export const getSystemConfig = () => {
+ return service({
+ url: '/system/getSystemConfig',
+ method: 'post'
+ })
+}
+
+// @Tags system
+// @Summary 设置配置文件内容
+// @Security ApiKeyAuth
+// @Produce application/json
+// @Param data body sysModel.System true
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
+// @Router /system/setSystemConfig [post]
+export const setSystemConfig = (data) => {
+ return service({
+ url: '/system/setSystemConfig',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags system
+// @Summary 获取服务器运行状态
+// @Security ApiKeyAuth
+// @Produce application/json
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
+// @Router /system/getServerInfo [post]
+export const getSystemState = () => {
+ return service({
+ url: '/system/getServerInfo',
+ method: 'post',
+ donNotShowLoading: true
+ })
+}
diff --git a/src/api/user.js b/src/api/user.js
new file mode 100644
index 0000000..befd20e
--- /dev/null
+++ b/src/api/user.js
@@ -0,0 +1,166 @@
+import service from '@/utils/request'
+// @Summary 用户登录
+// @Produce application/json
+// @Param data body {username:"string",password:"string"}
+// @Router /base/login [post]
+export const login = (data) => {
+ return service({
+ url: '/base/login',
+ method: 'post',
+ data: data
+ })
+}
+
+// @Summary 获取验证码
+// @Produce application/json
+// @Param data body {username:"string",password:"string"}
+// @Router /base/captcha [post]
+export const captcha = (data) => {
+ return service({
+ url: '/base/captcha',
+ method: 'post',
+ data: data
+ })
+}
+
+// @Summary 用户注册
+// @Produce application/json
+// @Param data body {username:"string",password:"string"}
+// @Router /base/resige [post]
+export const register = (data) => {
+ return service({
+ url: '/user/admin_register',
+ method: 'post',
+ data: data
+ })
+}
+
+// @Summary 修改密码
+// @Produce application/json
+// @Param data body {username:"string",password:"string",newPassword:"string"}
+// @Router /user/changePassword [post]
+export const changePassword = (data) => {
+ return service({
+ url: '/user/changePassword',
+ method: 'post',
+ data: data
+ })
+}
+
+// @Tags User
+// @Summary 分页获取用户列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body modelInterface.PageInfo true "分页获取用户列表"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /user/getUserList [post]
+export const getUserList = (data) => {
+ return service({
+ url: '/user/getUserList',
+ method: 'post',
+ data: data
+ })
+}
+
+// @Tags User
+// @Summary 设置用户权限
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.SetUserAuth true "设置用户权限"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"修改成功"}"
+// @Router /user/setUserAuthority [post]
+export const setUserAuthority = (data) => {
+ return service({
+ url: '/user/setUserAuthority',
+ method: 'post',
+ data: data
+ })
+}
+
+// @Tags SysUser
+// @Summary 删除用户
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.SetUserAuth true "删除用户"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"修改成功"}"
+// @Router /user/deleteUser [delete]
+export const deleteUser = (data) => {
+ return service({
+ url: '/user/deleteUser',
+ method: 'delete',
+ data: data
+ })
+}
+
+// @Tags SysUser
+// @Summary 设置用户信息
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysUser true "设置用户信息"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"修改成功"}"
+// @Router /user/setUserInfo [put]
+export const setUserInfo = (data) => {
+ return service({
+ url: '/user/setUserInfo',
+ method: 'put',
+ data: data
+ })
+}
+
+// @Tags SysUser
+// @Summary 设置用户信息
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.SysUser true "设置用户信息"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"修改成功"}"
+// @Router /user/setSelfInfo [put]
+export const setSelfInfo = (data) => {
+ return service({
+ url: '/user/setSelfInfo',
+ method: 'put',
+ data: data
+ })
+}
+
+// @Tags User
+// @Summary 设置用户权限
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body api.setUserAuthorities true "设置用户权限"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"修改成功"}"
+// @Router /user/setUserAuthorities [post]
+export const setUserAuthorities = (data) => {
+ return service({
+ url: '/user/setUserAuthorities',
+ method: 'post',
+ data: data
+ })
+}
+
+// @Tags User
+// @Summary 获取用户信息
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /user/getUserInfo [get]
+export const getUserInfo = () => {
+ return service({
+ url: '/user/getUserInfo',
+ method: 'get'
+ })
+}
+
+export const resetPassword = (data) => {
+ return service({
+ url: '/user/resetPassword',
+ method: 'post',
+ data: data
+ })
+}
diff --git a/src/assets/background.svg b/src/assets/background.svg
new file mode 100644
index 0000000..7375bb5
--- /dev/null
+++ b/src/assets/background.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/dashboard.png b/src/assets/dashboard.png
new file mode 100644
index 0000000..64981d0
Binary files /dev/null and b/src/assets/dashboard.png differ
diff --git a/src/assets/docs.png b/src/assets/docs.png
new file mode 100644
index 0000000..bb98d6e
Binary files /dev/null and b/src/assets/docs.png differ
diff --git a/src/assets/flipped-aurora.png b/src/assets/flipped-aurora.png
new file mode 100644
index 0000000..c94033b
Binary files /dev/null and b/src/assets/flipped-aurora.png differ
diff --git a/src/assets/github.png b/src/assets/github.png
new file mode 100644
index 0000000..d1d200e
Binary files /dev/null and b/src/assets/github.png differ
diff --git a/src/assets/kefu.png b/src/assets/kefu.png
new file mode 100644
index 0000000..47cab15
Binary files /dev/null and b/src/assets/kefu.png differ
diff --git a/src/assets/login_background.jpg b/src/assets/login_background.jpg
new file mode 100644
index 0000000..e601f24
Binary files /dev/null and b/src/assets/login_background.jpg differ
diff --git a/src/assets/login_background.svg b/src/assets/login_background.svg
new file mode 100644
index 0000000..0a9514b
--- /dev/null
+++ b/src/assets/login_background.svg
@@ -0,0 +1,33 @@
+
\ No newline at end of file
diff --git a/src/assets/login_left.svg b/src/assets/login_left.svg
new file mode 100644
index 0000000..9c48b0b
--- /dev/null
+++ b/src/assets/login_left.svg
@@ -0,0 +1,123 @@
+
+
\ No newline at end of file
diff --git a/src/assets/logo.jpg b/src/assets/logo.jpg
new file mode 100644
index 0000000..09502d5
Binary files /dev/null and b/src/assets/logo.jpg differ
diff --git a/src/assets/logo.png b/src/assets/logo.png
new file mode 100644
index 0000000..b497ee0
Binary files /dev/null and b/src/assets/logo.png differ
diff --git a/src/assets/logo_login.png b/src/assets/logo_login.png
new file mode 100644
index 0000000..e330458
Binary files /dev/null and b/src/assets/logo_login.png differ
diff --git a/src/assets/nav_logo.png b/src/assets/nav_logo.png
new file mode 100644
index 0000000..468cdab
Binary files /dev/null and b/src/assets/nav_logo.png differ
diff --git a/src/assets/noBody.png b/src/assets/noBody.png
new file mode 100644
index 0000000..e16488e
Binary files /dev/null and b/src/assets/noBody.png differ
diff --git a/src/assets/notFound.png b/src/assets/notFound.png
new file mode 100644
index 0000000..59ca9f0
Binary files /dev/null and b/src/assets/notFound.png differ
diff --git a/src/assets/qm.png b/src/assets/qm.png
new file mode 100644
index 0000000..9f598ca
Binary files /dev/null and b/src/assets/qm.png differ
diff --git a/src/assets/video.png b/src/assets/video.png
new file mode 100644
index 0000000..af4d35f
Binary files /dev/null and b/src/assets/video.png differ
diff --git a/src/components/chooseImg/index.vue b/src/components/chooseImg/index.vue
new file mode 100644
index 0000000..c3b4163
--- /dev/null
+++ b/src/components/chooseImg/index.vue
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/customPic/index.vue b/src/components/customPic/index.vue
new file mode 100644
index 0000000..3952e7a
--- /dev/null
+++ b/src/components/customPic/index.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/upload/common.vue b/src/components/upload/common.vue
new file mode 100644
index 0000000..e6e20fd
--- /dev/null
+++ b/src/components/upload/common.vue
@@ -0,0 +1,70 @@
+
+
+
+ 普通上传
+
+
+
+
+
+
+
diff --git a/src/components/upload/image.vue b/src/components/upload/image.vue
new file mode 100644
index 0000000..d36e1aa
--- /dev/null
+++ b/src/components/upload/image.vue
@@ -0,0 +1,104 @@
+
+
+
+
+ 压缩上传
+
+
+
+
+
+
+
+
+
diff --git a/src/components/warningBar/warningBar.vue b/src/components/warningBar/warningBar.vue
new file mode 100644
index 0000000..8d0ee7e
--- /dev/null
+++ b/src/components/warningBar/warningBar.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
diff --git a/src/core/config.js b/src/core/config.js
new file mode 100644
index 0000000..9afbdb6
--- /dev/null
+++ b/src/core/config.js
@@ -0,0 +1,58 @@
+/**
+ * 网站配置文件
+ */
+
+const config = {
+ appName: 'Gin-Vue-Admin',
+ appLogo: 'https://www.gin-vue-admin.com/img/logo.png',
+ showViteLogo: true
+}
+
+export const viteLogo = (env) => {
+ if (config.showViteLogo) {
+ const chalk = require('chalk')
+ console.log(
+ chalk.green(
+ `> 欢迎使用Gin-Vue-Admin,开源地址:https://github.com/flipped-aurora/gin-vue-admin`
+ )
+ )
+ console.log(
+ chalk.green(
+ `> 当前版本:v2.5.5`
+ )
+ )
+ console.log(
+ chalk.green(
+ `> 加群方式:微信:shouzi_1994 QQ群:622360840`
+ )
+ )
+ console.log(
+ chalk.green(
+ `> GVA讨论社区:https://support.qq.com/products/371961`
+ )
+ )
+ console.log(
+ chalk.green(
+ `> 插件市场:https://plugin.gin-vue-admin.com`
+ )
+ )
+ console.log(
+ chalk.green(
+ `> 默认自动化文档地址:http://127.0.0.1:${env.VITE_SERVER_PORT}/swagger/index.html`
+ )
+ )
+ console.log(
+ chalk.green(
+ `> 默认前端文件运行地址:http://127.0.0.1:${env.VITE_CLI_PORT}`
+ )
+ )
+ console.log(
+ chalk.green(
+ `> 如果项目让您获得了收益,希望您能请团队喝杯可乐:https://www.gin-vue-admin.com/coffee/index.html`
+ )
+ )
+ console.log('\n')
+ }
+}
+
+export default config
\ No newline at end of file
diff --git a/src/core/gin-vue-admin.js b/src/core/gin-vue-admin.js
new file mode 100644
index 0000000..1b07731
--- /dev/null
+++ b/src/core/gin-vue-admin.js
@@ -0,0 +1,22 @@
+/*
+ * gin-vue-admin web框架组
+ *
+ * */
+// 加载网站配置文件夹
+import { register } from './global'
+
+export default {
+ install: (app) => {
+ register(app)
+ console.log(`
+ 欢迎使用 Gin-Vue-Admin
+ 当前版本:v2.5.5
+ 加群方式:微信:shouzi_1994 QQ群:622360840
+ GVA讨论社区:https://support.qq.com/products/371961
+ 插件市场:https://plugin.gin-vue-admin.com
+ 默认自动化文档地址:http://127.0.0.1:${import.meta.env.VITE_SERVER_PORT}/swagger/index.html
+ 默认前端文件运行地址:http://127.0.0.1:${import.meta.env.VITE_CLI_PORT}
+ 如果项目让您获得了收益,希望您能请团队喝杯可乐:https://www.gin-vue-admin.com/coffee/index.html
+ `)
+ }
+}
\ No newline at end of file
diff --git a/src/core/global.js b/src/core/global.js
new file mode 100644
index 0000000..0d9c19e
--- /dev/null
+++ b/src/core/global.js
@@ -0,0 +1,13 @@
+import config from './config'
+
+// 统一导入el-icon图标
+import * as ElIconModules from '@element-plus/icons-vue'
+// 导入转换图标名称的函数
+
+export const register = (app) => {
+ // 统一注册el-icon图标
+ for (const iconName in ElIconModules) {
+ app.component(iconName, ElIconModules[iconName])
+ }
+ app.config.globalProperties.$GIN_VUE_ADMIN = config
+}
diff --git a/src/directive/auth.js b/src/directive/auth.js
new file mode 100644
index 0000000..50594d4
--- /dev/null
+++ b/src/directive/auth.js
@@ -0,0 +1,41 @@
+// 权限按钮展示指令
+import { useUserStore } from '@/pinia/modules/user'
+export default {
+ install: (app) => {
+ const userStore = useUserStore()
+ app.directive('auth', {
+ // 当被绑定的元素插入到 DOM 中时……
+ mounted: function(el, binding) {
+ const userInfo = userStore.userInfo
+ let type = ''
+ switch (Object.prototype.toString.call(binding.value)) {
+ case '[object Array]':
+ type = 'Array'
+ break
+ case '[object String]':
+ type = 'String'
+ break
+ case '[object Number]':
+ type = 'Number'
+ break
+ default:
+ type = ''
+ break
+ }
+ if (type === '') {
+ el.parentNode.removeChild(el)
+ return
+ }
+ const waitUse = binding.value.toString().split(',')
+ let flag = waitUse.some(item => Number(item) === userInfo.authorityId)
+ if (binding.modifiers.not) {
+ flag = !flag
+ }
+ if (!flag) {
+ el.parentNode.removeChild(el)
+ }
+ }
+ })
+ }
+}
+
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 0000000..a4a02a8
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,41 @@
+import { createApp } from 'vue'
+import 'element-plus/dist/index.css'
+import './style/element_visiable.scss'
+import ElementPlus from 'element-plus'
+import zhCn from 'element-plus/es/locale/lang/zh-cn'
+// 引入gin-vue-admin前端初始化相关内容
+import './core/gin-vue-admin'
+// 引入封装的router
+import router from '@/router/index'
+import '@/permission'
+import run from '@/core/gin-vue-admin.js'
+import auth from '@/directive/auth'
+import { store } from '@/pinia'
+import App from './App.vue'
+import { initDom } from './utils/positionToCode'
+initDom()
+/**
+ * @description 导入加载进度条,防止首屏加载时间过长,用户等待
+ *
+ * */
+import Nprogress from 'nprogress'
+import 'nprogress/nprogress.css'
+Nprogress.configure({ showSpinner: false, ease: 'ease', speed: 500 })
+Nprogress.start()
+
+/**
+ * 无需在这块结束,会在路由中间件中结束此块内容
+ * */
+
+const app = createApp(App)
+app.config.productionTip = false
+
+app
+ .use(run)
+ .use(store)
+ .use(auth)
+ .use(router)
+ .use(ElementPlus, { locale: zhCn })
+ .mount('#app')
+
+export default app
diff --git a/src/permission.js b/src/permission.js
new file mode 100644
index 0000000..954cfd5
--- /dev/null
+++ b/src/permission.js
@@ -0,0 +1,113 @@
+import { useUserStore } from '@/pinia/modules/user'
+import { useRouterStore } from '@/pinia/modules/router'
+import getPageTitle from '@/utils/page'
+import router from '@/router'
+import Nprogress from 'nprogress'
+
+let asyncRouterFlag = 0
+
+const whiteList = ['Login', 'Init']
+
+const getRouter = async(userStore) => {
+ const routerStore = useRouterStore()
+ await routerStore.SetAsyncRouter()
+ await userStore.GetUserInfo()
+ const asyncRouters = routerStore.asyncRouters
+ asyncRouters.forEach(asyncRouter => {
+ router.addRoute(asyncRouter)
+ })
+}
+
+async function handleKeepAlive(to) {
+ if (to.matched.some(item => item.meta.keepAlive)) {
+ if (to.matched && to.matched.length > 2) {
+ for (let i = 1; i < to.matched.length; i++) {
+ const element = to.matched[i - 1]
+ if (element.name === 'layout') {
+ to.matched.splice(i, 1)
+ await handleKeepAlive(to)
+ }
+ // 如果没有按需加载完成则等待加载
+ if (typeof element.components.default === 'function') {
+ await element.components.default()
+ await handleKeepAlive(to)
+ }
+ }
+ }
+ }
+}
+
+router.beforeEach(async(to, from) => {
+ Nprogress.start()
+ const userStore = useUserStore()
+ to.meta.matched = [...to.matched]
+ handleKeepAlive(to)
+ const token = userStore.token
+ // 在白名单中的判断情况
+ document.title = getPageTitle(to.meta.title, to)
+ if (whiteList.indexOf(to.name) > -1) {
+ if (token) {
+ if (!asyncRouterFlag && whiteList.indexOf(from.name) < 0) {
+ asyncRouterFlag++
+ await getRouter(userStore)
+ }
+ // token 可以解析但是却是不存在的用户 id 或角色 id 会导致无限调用
+ if (userStore.userInfo?.authority?.defaultRouter != null) {
+ return { name: userStore.userInfo.authority.defaultRouter }
+ } else {
+ // 强制退出账号
+ userStore.ClearStorage()
+ return {
+ name: 'Login',
+ query: {
+ redirect: document.location.hash
+ }
+ }
+ }
+ } else {
+ return true
+ }
+ } else {
+ // 不在白名单中并且已经登录的时候
+ if (token) {
+ // 添加flag防止多次获取动态路由和栈溢出
+ if (!asyncRouterFlag && whiteList.indexOf(from.name) < 0) {
+ asyncRouterFlag++
+ await getRouter(userStore)
+ if (userStore.token) {
+ return { ...to, replace: true }
+ } else {
+ return {
+ name: 'Login',
+ query: { redirect: to.href }
+ }
+ }
+ } else {
+ if (to.matched.length) {
+ return true
+ } else {
+ return { path: '/layout/404' }
+ }
+ }
+ }
+ // 不在白名单中并且未登录的时候
+ if (!token) {
+ return {
+ name: 'Login',
+ query: {
+ redirect: document.location.hash
+ }
+ }
+ }
+ }
+})
+
+router.afterEach(() => {
+ // 路由加载完成后关闭进度条
+ Nprogress.done()
+})
+
+router.onError(() => {
+ // 路由发生错误后销毁进度条
+ Nprogress.remove()
+})
diff --git a/src/pinia/index.js b/src/pinia/index.js
new file mode 100644
index 0000000..a6063cf
--- /dev/null
+++ b/src/pinia/index.js
@@ -0,0 +1,7 @@
+import { createPinia } from 'pinia'
+
+const store = createPinia()
+
+export {
+ store
+}
diff --git a/src/pinia/modules/dictionary.js b/src/pinia/modules/dictionary.js
new file mode 100644
index 0000000..5369222
--- /dev/null
+++ b/src/pinia/modules/dictionary.js
@@ -0,0 +1,39 @@
+import { findSysDictionary } from '@/api/sysDictionary'
+
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+
+export const useDictionaryStore = defineStore('dictionary', () => {
+ const dictionaryMap = ref({})
+
+ const setDictionaryMap = (dictionaryRes) => {
+ dictionaryMap.value = { ...dictionaryMap.value, ...dictionaryRes }
+ }
+
+ const getDictionary = async(type) => {
+ if (dictionaryMap.value[type] && dictionaryMap.value[type].length) {
+ return dictionaryMap.value[type]
+ } else {
+ const res = await findSysDictionary({ type })
+ if (res.code === 0) {
+ const dictionaryRes = {}
+ const dict = []
+ res.data.resysDictionary.sysDictionaryDetails && res.data.resysDictionary.sysDictionaryDetails.forEach(item => {
+ dict.push({
+ label: item.label,
+ value: item.value
+ })
+ })
+ dictionaryRes[res.data.resysDictionary.type] = dict
+ setDictionaryMap(dictionaryRes)
+ return dictionaryMap.value[type]
+ }
+ }
+ }
+
+ return {
+ dictionaryMap,
+ setDictionaryMap,
+ getDictionary
+ }
+})
diff --git a/src/pinia/modules/router.js b/src/pinia/modules/router.js
new file mode 100644
index 0000000..981116a
--- /dev/null
+++ b/src/pinia/modules/router.js
@@ -0,0 +1,121 @@
+import { asyncRouterHandle } from '@/utils/asyncRouter'
+import { emitter } from '@/utils/bus.js'
+import { asyncMenu } from '@/api/menu'
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+
+const routerListArr = []
+const notLayoutRouterArr = []
+const keepAliveRoutersArr = []
+const nameMap = {}
+
+const formatRouter = (routes, routeMap) => {
+ routes && routes.forEach(item => {
+ if ((!item.children || item.children.every(ch => ch.hidden)) && item.name !== '404' && !item.hidden) {
+ routerListArr.push({ label: item.meta.title, value: item.name })
+ }
+ item.meta.btns = item.btns
+ item.meta.hidden = item.hidden
+ if (item.meta.defaultMenu === true) {
+ notLayoutRouterArr.push({
+ ...item,
+ path: `/${item.path}`,
+ })
+ } else {
+ routeMap[item.name] = item
+ if (item.children && item.children.length > 0) {
+ formatRouter(item.children, routeMap)
+ }
+ }
+ })
+}
+
+const KeepAliveFilter = (routes) => {
+ routes && routes.forEach(item => {
+ // 子菜单中有 keep-alive 的,父菜单也必须 keep-alive,否则无效。这里将子菜单中有 keep-alive 的父菜单也加入。
+ if ((item.children && item.children.some(ch => ch.meta.keepAlive) || item.meta.keepAlive)) {
+ item.component && item.component().then(val => {
+ keepAliveRoutersArr.push(val.default.name)
+ nameMap[item.name] = val.default.name
+ })
+ }
+ if (item.children && item.children.length > 0) {
+ KeepAliveFilter(item.children)
+ }
+ })
+}
+
+export const useRouterStore = defineStore('router', () => {
+ const keepAliveRouters = ref([])
+ const setKeepAliveRouters = (history) => {
+ const keepArrTemp = []
+ history.forEach(item => {
+ if (nameMap[item.name]) {
+ keepArrTemp.push(nameMap[item.name])
+ }
+ })
+ keepAliveRouters.value = Array.from(new Set(keepArrTemp))
+ }
+ emitter.on('setKeepAlive', setKeepAliveRouters)
+
+ const asyncRouters = ref([])
+ const routerList = ref(routerListArr)
+ const routeMap = ({})
+ // 从后台获取动态路由
+ const SetAsyncRouter = async() => {
+ const baseRouter = [{
+ path: '/layout',
+ name: 'layout',
+ component: 'view/layout/index.vue',
+ meta: {
+ title: '底层layout'
+ },
+ children: []
+ }]
+ const asyncRouterRes = await asyncMenu()
+ const asyncRouter = asyncRouterRes.data.menus
+ asyncRouter && asyncRouter.push({
+ path: '404',
+ name: '404',
+ hidden: true,
+ meta: {
+ title: '迷路了*。*',
+ closeTab: true,
+ },
+ component: 'view/error/index.vue'
+ }, {
+ path: 'reload',
+ name: 'Reload',
+ hidden: true,
+ meta: {
+ title: '',
+ closeTab: true,
+ },
+ component: 'view/error/reload.vue'
+ })
+ formatRouter(asyncRouter, routeMap)
+ baseRouter[0].children = asyncRouter
+ if (notLayoutRouterArr.length !== 0) {
+ baseRouter.push(...notLayoutRouterArr)
+ }
+ baseRouter.push({
+ path: '/:catchAll(.*)',
+ redirect: '/layout/404'
+
+ })
+ asyncRouterHandle(baseRouter)
+ KeepAliveFilter(asyncRouter)
+ asyncRouters.value = baseRouter
+ routerList.value = routerListArr
+ return true
+ }
+
+ return {
+ asyncRouters,
+ routerList,
+ keepAliveRouters,
+ SetAsyncRouter,
+ routeMap
+ }
+})
+
diff --git a/src/pinia/modules/user.js b/src/pinia/modules/user.js
new file mode 100644
index 0000000..a1e87f1
--- /dev/null
+++ b/src/pinia/modules/user.js
@@ -0,0 +1,153 @@
+import { login, getUserInfo, setSelfInfo } from '@/api/user'
+import { jsonInBlacklist } from '@/api/jwt'
+import router from '@/router/index'
+import { ElLoading, ElMessage } from 'element-plus'
+import { defineStore } from 'pinia'
+import { ref, computed, watch } from 'vue'
+import { useRouterStore } from './router'
+
+export const useUserStore = defineStore('user', () => {
+ const loadingInstance = ref(null)
+
+ const userInfo = ref({
+ uuid: '',
+ nickName: '',
+ headerImg: '',
+ authority: {},
+ sideMode: 'dark',
+ activeColor: '#4D70FF',
+ baseColor: '#fff'
+ })
+ const token = ref(window.localStorage.getItem('token') || '')
+ const setUserInfo = (val) => {
+ userInfo.value = val
+ }
+
+ const setToken = (val) => {
+ token.value = val
+ }
+
+ const NeedInit = () => {
+ token.value = ''
+ window.localStorage.removeItem('token')
+ localStorage.clear()
+ router.push({ name: 'Init', replace: true })
+ }
+
+ const ResetUserInfo = (value = {}) => {
+ userInfo.value = {
+ ...userInfo.value,
+ ...value
+ }
+ }
+ /* 获取用户信息*/
+ const GetUserInfo = async() => {
+ const res = await getUserInfo()
+ if (res.code === 0) {
+ setUserInfo(res.data.userInfo)
+ }
+ return res
+ }
+ /* 登录*/
+ const LoginIn = async(loginInfo) => {
+ loadingInstance.value = ElLoading.service({
+ fullscreen: true,
+ text: '登录中,请稍候...',
+ })
+ try {
+ const res = await login(loginInfo)
+ if (res.code === 0) {
+ setUserInfo(res.data.user)
+ setToken(res.data.token)
+ const routerStore = useRouterStore()
+ await routerStore.SetAsyncRouter()
+ const asyncRouters = routerStore.asyncRouters
+ asyncRouters.forEach(asyncRouter => {
+ router.addRoute(asyncRouter)
+ })
+ await router.push({ name: userInfo.value.authority.defaultRouter })
+ loadingInstance.value.close()
+ return true
+ }
+ } catch (e) {
+ loadingInstance.value.close()
+ }
+ loadingInstance.value.close()
+ }
+ /* 登出*/
+ const LoginOut = async() => {
+ const res = await jsonInBlacklist()
+ if (res.code === 0) {
+ token.value = ''
+ sessionStorage.clear()
+ localStorage.clear()
+ router.push({ name: 'Login', replace: true })
+ window.location.reload()
+ }
+ }
+ /* 清理数据 */
+ const ClearStorage = async() => {
+ token.value = ''
+ sessionStorage.clear()
+ localStorage.clear()
+ }
+ /* 设置侧边栏模式*/
+ const changeSideMode = async(data) => {
+ const res = await setSelfInfo({ sideMode: data })
+ if (res.code === 0) {
+ userInfo.value.sideMode = data
+ ElMessage({
+ type: 'success',
+ message: '设置成功'
+ })
+ }
+ }
+
+ const mode = computed(() => userInfo.value.sideMode)
+ const sideMode = computed(() => {
+ if (userInfo.value.sideMode === 'dark') {
+ return '#191a23'
+ } else if (userInfo.value.sideMode === 'light') {
+ return '#fff'
+ } else {
+ return userInfo.value.sideMode
+ }
+ })
+ const baseColor = computed(() => {
+ if (userInfo.value.sideMode === 'dark') {
+ return '#fff'
+ } else if (userInfo.value.sideMode === 'light') {
+ return '#191a23'
+ } else {
+ return userInfo.value.baseColor
+ }
+ })
+ const activeColor = computed(() => {
+ if (userInfo.value.sideMode === 'dark' || userInfo.value.sideMode === 'light') {
+ return '#4D70FF'
+ }
+ return userInfo.activeColor
+ })
+
+ watch(() => token.value, () => {
+ window.localStorage.setItem('token', token.value)
+ })
+
+ return {
+ userInfo,
+ token,
+ NeedInit,
+ ResetUserInfo,
+ GetUserInfo,
+ LoginIn,
+ LoginOut,
+ changeSideMode,
+ mode,
+ sideMode,
+ setToken,
+ baseColor,
+ activeColor,
+ loadingInstance,
+ ClearStorage
+ }
+})
diff --git a/src/plugin/email/api/email.js b/src/plugin/email/api/email.js
new file mode 100644
index 0000000..590c862
--- /dev/null
+++ b/src/plugin/email/api/email.js
@@ -0,0 +1,30 @@
+import service from '@/utils/request'
+// @Tags System
+// @Summary 发送测试邮件
+// @Security ApiKeyAuth
+// @Produce application/json
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"发送成功"}"
+// @Router /email/emailTest [post]
+export const emailTest = (data) => {
+ return service({
+ url: '/email/emailTest',
+ method: 'post',
+ data
+ })
+}
+
+// @Tags System
+// @Summary 发送邮件
+// @Security ApiKeyAuth
+// @Produce application/json
+// @Param data body email_response.Email true "发送邮件必须的参数"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"发送成功"}"
+// @Router /email/sendEmail [post]
+export const sendEmail = (data) => {
+ return service({
+ url: '/email/sendEmail',
+ method: 'post',
+ data
+ })
+}
+
diff --git a/src/plugin/email/view/index.vue b/src/plugin/email/view/index.vue
new file mode 100644
index 0000000..50cc884
--- /dev/null
+++ b/src/plugin/email/view/index.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 发送测试邮件
+ 发送邮件
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/router/index.js b/src/router/index.js
new file mode 100644
index 0000000..290e931
--- /dev/null
+++ b/src/router/index.js
@@ -0,0 +1,24 @@
+import { createRouter, createWebHashHistory } from 'vue-router'
+
+const routes = [{
+ path: '/',
+ redirect: '/login'
+},
+{
+ path: '/init',
+ name: 'Init',
+ component: () => import('@/view/init/index.vue')
+},
+{
+ path: '/login',
+ name: 'Login',
+ component: () => import('@/view/login/index.vue')
+}
+]
+
+const router = createRouter({
+ history: createWebHashHistory(),
+ routes
+})
+
+export default router
diff --git a/src/style/base.scss b/src/style/base.scss
new file mode 100644
index 0000000..b3bda02
--- /dev/null
+++ b/src/style/base.scss
@@ -0,0 +1,65 @@
+.clearfix:after {
+ content: '';
+ display: block;
+ height: 0;
+ visibility: hidden;
+ clear: both;
+}
+
+.fl-left {
+ float: left;
+}
+
+.fl-right {
+ float: right;
+}
+
+.mg {
+ margin: 10px !important;
+}
+
+.left-mg-xs {
+ margin-left: 6px !important;
+}
+
+.left-mg-sm {
+ margin-left: 10px !important;
+}
+
+.left-mg-md {
+ margin-left: 14px !important;
+}
+
+.top-mg-lg {
+ margin-top: 20px !important;
+}
+
+.tb-mg-lg {
+ margin: 20px 0 !important;
+}
+
+.bottom-mg-lg {
+ margin-bottom: 20px !important;
+}
+
+.left-mg-lg {
+ margin-left: 18px !important;
+}
+
+.title-1 {
+ text-align: center;
+ font-size: 32px;
+}
+
+.title-3 {
+ text-align: center;
+}
+
+.keyword{
+ width: 220px;
+ margin: 0 0 0 30px;
+}
+
+#nprogress .bar {
+ background: #4D70FF !important; //自定义颜色
+}
diff --git a/src/style/basics.scss b/src/style/basics.scss
new file mode 100644
index 0000000..2d859a3
--- /dev/null
+++ b/src/style/basics.scss
@@ -0,0 +1,36 @@
+// basice
+$font-size: 14px;
+$icon-size:18px;
+$active-color:#1890ff;
+$bg-main:#f0f2f5;
+$border-color: #f4f4f4;
+$white-bg:#fff;
+$el-icon-small:30px;
+$el-icon-mini:24px;
+// aside
+$width-aside:220px;
+$width-hideside-aside:54px;
+$width-mobile-aside:210px;
+$color-aside:rgba(255, 255, 255, .9);
+$icon-arrow-size-aside:12px;
+$width-submenu-aside:55px;
+$height-aside-tilte:60px;
+$height-aside-img:30px;
+$width-aside-img:30px;
+// header
+$height-header: 60px;
+// nav-scroll
+$height-nav-scroll:40px;
+$active-bg-tabs-item-nav-scroll:#409eff;
+$bg-tabs-item-nav-scroll:#ddd;
+// table
+$bg-color-table-thead:#fafafa;
+$border-color-table:#ededed;
+$height-table-cell:45px;
+$color-table-tbody:#595959;
+$color-table-thead:#262626;
+// dashboard
+$height-car:68px;
+// mobile
+$padding-xs: 5px;
+$margin-xs: 5px;
\ No newline at end of file
diff --git a/src/style/button.scss b/src/style/button.scss
new file mode 100644
index 0000000..9c3e7c5
--- /dev/null
+++ b/src/style/button.scss
@@ -0,0 +1,9 @@
+.sticky-button {
+ position: sticky;
+ top: 2px;
+ z-index: 2;
+ background-color: #fff;
+}
+.fitler{
+ width: 60%;
+}
\ No newline at end of file
diff --git a/src/style/element_visiable.scss b/src/style/element_visiable.scss
new file mode 100644
index 0000000..a65e84f
--- /dev/null
+++ b/src/style/element_visiable.scss
@@ -0,0 +1,227 @@
+/* 改变主题色变量 */
+
+#app {
+ .el-button {
+ font-weight: 400;
+ border-radius: 2px;
+ }
+}
+
+.el-dialog {
+ border-radius: 2px;
+}
+
+::-webkit-scrollbar-track-piece {
+ background-color: #f8f8f8;
+}
+
+::-webkit-scrollbar {
+ width: 9px;
+ height: 9px;
+}
+
+::-webkit-scrollbar-thumb {
+ background-color: #dddddd;
+ background-clip: padding-box;
+ min-height: 28px;
+ border-radius: 4px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background-color: #bbb;
+}
+
+.el-button--primary {
+ --el-button-font-color: #ffffff;
+ --el-button-background-color: #4D70FF;
+ --el-button-border-color: #4D70FF;
+ --el-button-hover-color: #0d84ff;
+ --el-button-active-font-color: #e6e6e6;
+ --el-button-active-background-color: #0d84ff;
+ --el-button-active-border-color: #0d84ff;
+}
+
+.el-button--primary {
+ --el-button-font-color: #ffffff;
+ --el-button-background-color: #4D70FF;
+ --el-button-border-color: #4D70FF;
+ --el-button-hover-color: #0d84ff;
+ --el-button-active-font-color: #e6e6e6;
+ --el-button-active-background-color: #0d84ff;
+ --el-button-active-border-color: #0d84ff;
+}
+
+:root {
+ --el-color-primary: #4D70FF;
+ --el-menu-item-height:56px ;
+}
+
+.gva-search-box {
+ .el-collapse {
+ border: none;
+ .el-collapse-item__header,
+ .el-collapse-item__wrap {
+ border-bottom: none;
+ }
+ }
+ padding: 24px;
+ padding-bottom: 2px;
+ background-color: #fff;
+ border-radius: 2px;
+ margin-bottom: 12px;
+}
+
+.el-form--inline{
+ .el-form-item{
+ margin-right: 24px;
+ }
+}
+
+.el-input__inner{
+ height: 40px;
+ line-height: 40px;
+}
+
+.gva-form-box {
+ padding: 24px;
+ background-color: #fff;
+ border-radius: 2px;
+}
+
+.gva-table-box {
+ padding: 24px;
+ background-color: #fff;
+ border-radius: 2px;
+}
+
+.gva-pagination {
+ display: flex;
+ justify-content: flex-end;
+ .el-pagination__editor {
+ .el-input__inner {
+ height: 32px;
+ }
+ }
+ .el-pagination__total {
+ line-height: 32px !important;
+ }
+ //小屏幕不显示
+ @media (max-width: 750px) {
+ .el-pagination__sizes{
+ display: none !important;
+ }
+ }
+ .btn-prev {
+ padding-right: 6px;
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ width: 32px;
+ height: 32px;
+ }
+ .number {
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ width: 32px;
+ height: 32px;
+ }
+ .btn-quicknext {
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ width: 32px;
+ height: 32px;
+ }
+ .btn-next {
+ padding-left: 6px;
+ width: 32px;
+ height: 32px;
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ }
+ // 兼容久版用户升级
+ .active {
+ background: #4D70FF;
+ border-radius: 2px;
+ color: #ffffff !important;
+ }
+ .el-pager li.active+li {
+ border-left: 1px solid #ddd !important;
+ }
+ // end
+
+
+ .is-active {
+ background: #4D70FF;
+ border-radius: 2px;
+ color: #ffffff !important;
+ }
+ .el-pager li.is-active+li {
+ border-left: 1px solid #ddd !important;
+ }
+ .el-pagination__sizes {
+ .el-input {
+ .el-input__suffix {
+ margin-top: 2px;
+ }
+ }
+ }
+}
+
+.el-button--small {
+ min-height: 32px;
+ font-size: 12px !important;
+}
+
+.el-checkbox{
+ height: auto;
+}
+
+.el-button {
+ padding: 8px 16px;
+ border-radius: 2px;
+ &.el-button--text {
+ padding: 8px 0;
+ }
+}
+
+.el-dialog {
+ padding: 12px;
+ .el-dialog__body {
+ padding: 12px 6px;
+ }
+ .el-dialog__header {
+ .el-dialog__title {
+ font-size: 14px;
+ font-weight: 500;
+ }
+ padding: 2px 20px 12px 20px;
+ border-bottom: 1px solid #E4E4E4;
+ }
+ .el-dialog__footer {
+ padding: 0 16px 16px 0;
+ .dialog-footer {
+ .el-button {
+ padding-left: 24px;
+ padding-right: 24px;
+ }
+ .el-button+.el-button {
+ margin-left: 30px;
+ }
+ }
+ }
+}
+
+.el-drawer__body {
+ padding: 0;
+}
+
+.el-date-editor .el-range-separator {
+ line-height: 24px;
+}
+
+.el-select .el-input .el-select__caret.el-icon {
+ height: 38px;
+}
\ No newline at end of file
diff --git a/src/style/iconfont.css b/src/style/iconfont.css
new file mode 100644
index 0000000..bc091a0
--- /dev/null
+++ b/src/style/iconfont.css
@@ -0,0 +1,47 @@
+@font-face {
+ font-family: 'gvaIcon';
+ src: url('data:font/ttf;charset=utf-8;base64,AAEAAAANAIAAAwBQRkZUTZJUyU8AAA14AAAAHEdERUYAKQARAAANWAAAAB5PUy8yPJpJTAAAAVgAAABgY21hcM0T0L4AAAHYAAABWmdhc3D//wADAAANUAAAAAhnbHlmRk3UvwAAA0wAAAbYaGVhZB/a5jgAAADcAAAANmhoZWEHngOFAAABFAAAACRobXR4DaoBrAAAAbgAAAAebG9jYQbMCGgAAAM0AAAAGG1heHABGgB+AAABOAAAACBuYW1lXoIBAgAACiQAAAKCcG9zdN15OnUAAAyoAAAAqAABAAAAAQAA+a916l8PPPUACwQAAAAAAN5YUSMAAAAA3lhRIwBL/8ADwAM1AAAACAACAAAAAAAAAAEAAAOA/4AAXAQAAAAAAAPAAAEAAAAAAAAAAAAAAAAAAAAEAAEAAAALAHIABQAAAAAAAgAAAAoACgAAAP8AAAAAAAAABAQAAZAABQAAAokCzAAAAI8CiQLMAAAB6wAyAQgAAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZADA5mXmfQOA/4AAAAPcAIAAAAABAAAAAAAAAAAAAAAgAAEEAAAAAAAAAAQAAAAEAACLAIoAYAB1AHYASwBLAGAAAAAAAAMAAAADAAAAHAABAAAAAABUAAMAAQAAABwABAA4AAAACgAIAAIAAuZm5mrmduZ9//8AAOZl5mrmdeZ7//8ZnhmbGZEZjQABAAAAAAAAAAAAAAAAAQYAAAEAAAAAAAAAAQIAAAACAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEYAigEcAbgCUAK6AxoDbAACAIsAIANsAswAEQAjAAAlIicBJjQ3ATYeAQYHCQEeAQYhIicBJjQ3ATYeAQYHCQEeAQYDSw0J/qsLCwFVChsSAgr+xAE8CgIV/qkNCP6qCgoBVgkbEgIK/sUBOwoCFCAJATULGQsBNQoCExwI/uL+4ggbFAkBNQsZCwE1CgITHAj+4v7iCRoUAAAAAAIAigAgA2sCzAARACIAAAE0JwEmDgEWFwkBDgEWMjcBNiUBJg4BFhcJAQ4BFjI3ATY0AiAL/qsJHBECCQE8/sQJAhQZCQFVCwFA/qsKGxICCgE8/sQKAhUZCQFVCwF1DQsBNQoCExwI/uL+4gkaFAkBNQskATUKAhMcCP7i/uIJGhQJATULGQADAGD/wAOgAzUATABcAGwAAAE1NCcmJyYiBwYHBh0BDgEdARQWOwEyNj0BNCYrATU0NzY3NjIXFhcWHQEjIgYdARQWOwEGBwYHLgEjIgYUFjMyNjc2NzY3PgE9ATQmBRUUBisBIiY9ATQ2OwEyFgUUBisBIiY9ATQ2OwEyFhUDYDAvT1O+U08vMBslLB9VHi0tHiAoJkFDnENBJiggHi0tHhUPJC5SChwRHCQkHBEeCHJAMxAfKiX9kAYFVQUGBgVVBQYCVQYFVQUGBgVVBQYByQxgUlAuMDAuUFJgDAQqG6seLCweqx4tCk5DQScnJydBQ04KLR6rHiwrGiAGDxElNiUSEAc1KkUBKx6rGyhFqwQGBgSrBQYGsAQGBgSrBQYGBQAABAB1//UDjQMLABsANwBSAHEAABMyNj0BFxYyNjQvATMyNjQmKwEiBwYHBh0BFBYFIgYdAScmIgYUHwEjIgYUFjsBMjc2NzY9ATYmJQc1NCYiBh0BFBcWFxY7ATI2NCYrATc2NCYGATQ1FSYnJisBIgYUFjsBBwYUFjI/ARUUFjI2PQEnJpUNE7wJHRMKvIcMFBQM1ggCDAgCFALiDRPJCRoTCcmJDBQUDNYIAg8CAwES/gbJExkUAggKBAbWDBQUDInJCRMXAgEHCwQG2AwUFAyJvAkSHgi8ExoTAgEB9RQMibwIEhkKvBMZFAIGDAQI1gwU6hQMickJExoJyRMZFAIICgQG2AwUIsmHDBQUDNYIAg8CAxQZE8kKGRMBAcABAQIOAwMUGRO8ChkTCbyHDBQUDNYFBAAABAB2//cDjgMMABoANQBRAG0AAAEjIgYUFjsBMjc2NzY9ATQmIgYdAScmIgYUFwEzMjY0JisBIgcGBwYdARQWMjY9ARcWMjY0JyUmJyYrASIGFBY7AQcGFBYyPwEVFBYyNj0BLgE3FhcWOwEyNjQmKwE3NjQmIg8BNTQmIgYdAR4BATqJDRMTDdUJAg8CAhMaE7cKGRQKAjeJDRMTDdUJAg8CAhMaE8gJHhIK/i8HCgQH1w0TEw2JyQoTHQnIFBkTAQKoBwoEBtYNExMNibwKFBkKvBMZFAICAhoUGRMCBwoEBtYNExMNib4KExoK/iAUGRMCBwoEB9UNExMNickIEhkK8w8CAhMZFMgKGRMJyYkNExMN1QIJzQ8CAhMZFLsKGhMKvIkNExMN1QMIAAAAAAUAS//LA7UDNQAUACkAKgA3AEQAAAEiBwYHBhQXFhcWMjc2NzY0JyYnJgMiJyYnJjQ3Njc2MhcWFxYUBwYHBgMjFB4BMj4BNC4BIg4BFyIGHQEUFjI2PQE0JgIAd2ZiOzs7O2Jm7mZiOzs7O2Jmd2VXVDIzMzJUV8pXVDIzMzJUV2UrDBQWFAwMFBYUDCsNExMaExMDNTs7YmbuZmI7Ozs7YmbuZmI7O/zWMzJUV8pXVDIzMzJUV8pXVDIzAjULFAwMFBYUDAwUgBQM6w0TEw3rDBQAAQBL/+ADwAMgAD0AAAEmBg8BLgEjIgcGBwYUFxYXFjMyPgE3Ni4BBgcOAiMiJyYnJjQ3Njc2MzIeARcnJg4BFh8BMj8BNj8BNCYDpgwXAxc5yXZyY184Ojo4X2NyWaB4HgULGhcFGWaJS2FUUTAwMTBRU2FIhGQbgA0WBw4NwgUIBAwDMQ0CsQMODFhmeDk3XmHiYV43OUV9UQ0XCQsMRWo6MC9PUr9TTy8wNmNBJQMOGhYDMwMBCAu6DRYAAAAAAgBg/8YDugMiAB4AMwAABSc+ATU0JyYnJiIHBgcGFBcWFxYzMjc2NxcWMjc2JiUiJyYnJjQ3Njc2MhcWFxYUBwYHBgOxviouNDFVV8lXVTIzMzJVV2RDPzwzvgkeCAcB/hxUSEYpKiopRkioSEYpKyspRkgCvjB9RGRYVDIzNDJVWMlXVTE0GBYqvgkJChuBKylGSKhIRikqKilGSKhIRikrAAAAABIA3gABAAAAAAAAABMAKAABAAAAAAABAAgATgABAAAAAAACAAcAZwABAAAAAAADAAgAgQABAAAAAAAEAAgAnAABAAAAAAAFAAsAvQABAAAAAAAGAAgA2wABAAAAAAAKACsBPAABAAAAAAALABMBkAADAAEECQAAACYAAAADAAEECQABABAAPAADAAEECQACAA4AVwADAAEECQADABAAbwADAAEECQAEABAAigADAAEECQAFABYApQADAAEECQAGABAAyQADAAEECQAKAFYA5AADAAEECQALACYBaABDAHIAZQBhAHQAZQBkACAAYgB5ACAAaQBjAG8AbgBmAG8AbgB0AABDcmVhdGVkIGJ5IGljb25mb250AABpAGMAbwBuAGYAbwBuAHQAAGljb25mb250AABSAGUAZwB1AGwAYQByAABSZWd1bGFyAABpAGMAbwBuAGYAbwBuAHQAAGljb25mb250AABpAGMAbwBuAGYAbwBuAHQAAGljb25mb250AABWAGUAcgBzAGkAbwBuACAAMQAuADAAAFZlcnNpb24gMS4wAABpAGMAbwBuAGYAbwBuAHQAAGljb25mb250AABHAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAHMAdgBnADIAdAB0AGYAIABmAHIAbwBtACAARgBvAG4AdABlAGwAbABvACAAcAByAG8AagBlAGMAdAAuAABHZW5lcmF0ZWQgYnkgc3ZnMnR0ZiBmcm9tIEZvbnRlbGxvIHByb2plY3QuAABoAHQAdABwADoALwAvAGYAbwBuAHQAZQBsAGwAbwAuAGMAbwBtAABodHRwOi8vZm9udGVsbG8uY29tAAAAAAIAAAAAAAAACgAAAAAAAQAAAAAAAAAAAAAAAAAAAAAACwAAAAEAAgECAQMBBAEFAQYBBwEIAQkRYXJyb3ctZG91YmxlLWxlZnQSYXJyb3ctZG91YmxlLXJpZ2h0EGN1c3RvbWVyLXNlcnZpY2URZnVsbHNjcmVlbi1leHBhbmQRZnVsbHNjcmVlbi1zaHJpbmsGcHJvbXB0B3JlZnJlc2gGc2VhcmNoAAAAAf//AAIAAQAAAAwAAAAWAAAAAgABAAMACgABAAQAAAACAAAAAAAAAAEAAAAA1aQnCAAAAADeWFEjAAAAAN5YUSM=') format('truetype');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+.gvaIcon {
+ font-family: "gvaIcon" !important;
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 800;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
+
+.gvaIcon-arrow-double-left:before {
+ content: "\e665";
+ }
+
+.gvaIcon-arrow-double-right:before {
+ content: "\e666";
+}
+
+.gvaIcon-fullscreen-shrink:before {
+ content: "\e676";
+}
+.gvaIcon-customer-service:before {
+ content: "\e66a";
+ }
+
+.gvaIcon-fullscreen-expand:before {
+ content: "\e675";
+}
+
+.gvaIcon-prompt:before {
+ content: "\e67b";
+}
+
+.gvaIcon-refresh:before {
+ content: "\e67c";
+}
+
+.gvaIcon-search:before {
+ content: "\e67d";
+}
+
diff --git a/src/style/main.scss b/src/style/main.scss
new file mode 100644
index 0000000..9282bef
--- /dev/null
+++ b/src/style/main.scss
@@ -0,0 +1,1226 @@
+/* Document
+ ========================================================================== */
+
+
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+
+@import '@/style/basics.scss';
+@import '@/style/iconfont.css';
+html {
+ line-height: 1.15;
+ /* 1 */
+ -webkit-text-size-adjust: 100%;
+ /* 2 */
+}
+
+
+/* Sections
+ ========================================================================== */
+
+
+/**
+ * Remove the margin in all browsers.
+ */
+
+body {
+ margin: 0;
+}
+
+
+/**
+ * Render the `main` element consistently in IE.
+ */
+
+main {
+ display: block;
+}
+
+
+/**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+
+/* Grouping content
+ ========================================================================== */
+
+
+/**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+hr {
+ box-sizing: content-box;
+ /* 1 */
+ height: 0;
+ /* 1 */
+ overflow: visible;
+ /* 2 */
+}
+
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+pre {
+ font-family: monospace, monospace;
+ /* 1 */
+ font-size: 1em;
+ /* 2 */
+}
+
+
+/* Text-level semantics
+ ========================================================================== */
+
+
+/**
+ * Remove the gray background on active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+
+/**
+ * 1. Remove the bottom border in Chrome 57-
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+abbr[title] {
+ border-bottom: none;
+ /* 1 */
+ text-decoration: underline;
+ /* 2 */
+ text-decoration: underline dotted;
+ /* 2 */
+}
+
+
+/**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+b,
+strong {
+ font-weight: bolder;
+}
+
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+code,
+kbd,
+samp {
+ font-family: monospace, monospace;
+ /* 1 */
+ font-size: 1em;
+ /* 2 */
+}
+
+
+/**
+ * Add the correct font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+
+/**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+
+/* Embedded content
+ ========================================================================== */
+
+
+/**
+ * Remove the border on images inside links in IE 10.
+ */
+
+img {
+ border-style: none;
+}
+
+
+/* Forms
+ ========================================================================== */
+
+
+/**
+ * 1. Change the font styles in all browsers.
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: inherit;
+ /* 1 */
+ font-size: 100%;
+ /* 1 */
+ line-height: 1.15;
+ /* 1 */
+ margin: 0;
+ /* 2 */
+}
+
+
+/**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+button,
+input {
+ /* 1 */
+ overflow: visible;
+}
+
+
+/**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+button,
+select {
+ /* 1 */
+ text-transform: none;
+}
+
+
+/**
+ * Correct the inability to style clickable types in iOS and Safari.
+ */
+
+button,
+[type="button"],
+[type="reset"],
+[type="submit"] {
+ -webkit-appearance: button;
+}
+
+
+/**
+ * Remove the inner border and padding in Firefox.
+ */
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+ border-style: none;
+ padding: 0;
+}
+
+
+/**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+ outline: 1px dotted ButtonText;
+}
+
+
+/**
+ * Correct the padding in Firefox.
+ */
+
+fieldset {
+ padding: 0.35em 0.75em 0.625em;
+}
+
+
+/**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ * `fieldset` elements in all browsers.
+ */
+
+legend {
+ box-sizing: border-box;
+ /* 1 */
+ color: inherit;
+ /* 2 */
+ display: table;
+ /* 1 */
+ max-width: 100%;
+ /* 1 */
+ padding: 0;
+ /* 3 */
+ white-space: normal;
+ /* 1 */
+}
+
+
+/**
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+progress {
+ vertical-align: baseline;
+}
+
+
+/**
+ * Remove the default vertical scrollbar in IE 10+.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+
+/**
+ * 1. Add the correct box sizing in IE 10.
+ * 2. Remove the padding in IE 10.
+ */
+
+[type="checkbox"],
+[type="radio"] {
+ box-sizing: border-box;
+ /* 1 */
+ padding: 0;
+ /* 2 */
+}
+
+
+/**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+
+/**
+ * 1. Correct the odd appearance in Chrome and Safari.
+ * 2. Correct the outline style in Safari.
+ */
+
+[type="search"] {
+ -webkit-appearance: textfield;
+ /* 1 */
+ outline-offset: -2px;
+ /* 2 */
+}
+
+
+/**
+ * Remove the inner padding in Chrome and Safari on macOS.
+ */
+
+[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+
+/**
+ * 1. Correct the inability to style clickable types in iOS and Safari.
+ * 2. Change font properties to `inherit` in Safari.
+ */
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button;
+ /* 1 */
+ font: inherit;
+ /* 2 */
+}
+
+
+/* Interactive
+ ========================================================================== */
+
+
+/*
+ * Add the correct display in Edge, IE 10+, and Firefox.
+ */
+
+details {
+ display: block;
+}
+
+
+/*
+ * Add the correct display in all browsers.
+ */
+
+summary {
+ display: list-item;
+}
+
+
+/* Misc
+ ========================================================================== */
+
+
+/**
+ * Add the correct display in IE 10+.
+ */
+
+template {
+ display: none;
+}
+
+
+/**
+ * Add the correct display in IE 10.
+ */
+
+[hidden] {
+ display: none;
+}
+
+HTML,
+body,
+div,
+ul,
+ol,
+dl,
+li,
+dt,
+dd,
+p,
+blockquote,
+pre,
+form,
+fieldset,
+table,
+th,
+td {
+ border: none;
+ font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
+ font-size: 14px;
+ margin: 0px;
+ padding: 0px;
+}
+
+html,
+body {
+ height: 100%;
+ width: 100%;
+}
+
+address,
+caption,
+cite,
+code,
+th,
+var {
+ font-style: normal;
+ font-weight: normal;
+}
+
+a {
+ text-decoration: none;
+}
+
+input::-ms-clear {
+ display: none;
+}
+
+input::-ms-reveal {
+ display: none;
+}
+
+input {
+ -webkit-appearance: none;
+ margin: 0;
+ outline: none;
+ padding: 0;
+}
+
+input::-webkit-input-placeholder {
+ color: #ccc;
+}
+
+input::-ms-input-placeholder {
+ color: #ccc;
+}
+
+input::-moz-placeholder {
+ color: #ccc;
+}
+
+input[type=submit],
+input[type=button] {
+ cursor: pointer;
+}
+
+button[disabled],
+input[disabled] {
+ cursor: default;
+}
+
+img {
+ border: none;
+}
+
+ul,
+ol,
+li {
+ list-style-type: none;
+}
+
+// 导航
+#app {
+ .pd-lr-15 {
+ padding: 0 15px;
+ }
+ .height-full {
+ height: 100%;
+ }
+ .width-full {
+ width: 100%;
+ }
+ .dp-flex {
+ display: flex;
+ }
+ .justify-content-center {
+ justify-content: center;
+ }
+ .align-items {
+ align-items: center;
+ }
+ .pd-0 {
+ padding: 0;
+ }
+ .el-container {
+ position: relative;
+ height: 100%;
+ width: 100%;
+ }
+ .el-container.mobile.openside {
+ position: fixed;
+ top: 0;
+ }
+ .gva-aside {
+ -webkit-transition: width .2s;
+ transition: width .2s;
+ width: $width-aside;
+ height: 100%;
+ position: fixed;
+ font-size: 0;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1001;
+ overflow: hidden;
+ .el-menu {
+ border-right: none;
+ }
+ .tilte {
+ min-height: $height-aside-tilte;
+ line-height: $height-aside-tilte;
+ text-align: center;
+ transition: all 0.3s;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ .logoimg {
+ width: $width-aside-img;
+ height: $height-aside-img;
+ background: #fff;
+ border-radius: 50%;
+ padding: 3px;
+ }
+ .tit-text {
+ display: inline-block;
+ color: #fff;
+ font-weight: 600;
+ font-size: 20px;
+ padding-left: 10px;
+ }
+ }
+ }
+ .aside {
+ .el-menu--collapse {
+ >.el-menu-item {
+ display: flex;
+ justify-content: center;
+ }
+ }
+ .el-sub-menu {
+ .el-menu {
+ .is-active {
+ // 关闭三级菜单二级菜单样式
+ ul {
+ border: none;
+ }
+ }
+ // 关闭三级菜单二级菜单样式
+ .is-active.is-opened {
+ ul {
+ border: none;
+ }
+ }
+ }
+ }
+ }
+ .hideside {
+ .aside {
+ width: $width-hideside-aside;
+ }
+ }
+ .mobile.hideside {
+ .gva-aside {
+ -webkit-transition-duration: .2s;
+ transition-duration: .2s;
+ -webkit-transform: translate3d(-210px, 0, 0);
+ transform: translate3d(-220px, 0, 0);
+ }
+ }
+ .mobile {
+ .gva-aside {
+ -webkit-transition: -webkit-transform .28s;
+ transition: -webkit-transform .28s;
+ transition: transform .28s;
+ transition: transform .28s, -webkit-transform .28s;
+ width: $width-mobile-aside;
+ }
+ }
+ .main-cont.el-main {
+ min-height: 100%;
+ margin-left: $width-aside;
+ position: relative;
+ }
+ .hideside {
+ .main-cont.el-main {
+ margin-left: 54px;
+ }
+ }
+ .mobile {
+ .main-cont.el-main {
+ margin-left: 0px;
+ }
+ }
+ .openside.mobile {
+ .shadowBg {
+ background: #000;
+ opacity: .3;
+ width: 100%;
+ top: 0;
+ height: 100%;
+ position: absolute;
+ z-index: 999;
+ left: 0;
+ }
+ }
+}
+
+// layout
+.layout-cont {
+ .main-cont {
+ position: relative;
+ &.el-main {
+ background-color: $bg-main;
+ padding: 0;
+ }
+ }
+}
+
+.admin-box {
+ min-height: calc(100vh - 200px);
+ padding: 12px 16px;
+ margin: 100px 2px 20px;
+ .el-table--border {
+ border-radius: 4px;
+ margin-bottom: 14px;
+ }
+ .el-table {
+ thead {
+ color: $color-table-thead;
+ }
+ th {
+ padding: 6px 0;
+ .cell {
+ color: rgba($color: #000000, $alpha: 0.85);
+ font-size: 14px;
+ line-height: 40px;
+ min-height: 40px;
+ }
+ }
+ td {
+ padding: 6px 0;
+ .cell {
+ min-height: 40px;
+ line-height: 40px;
+ color: rgba($color: #000000, $alpha: 0.65);
+ }
+ }
+ td.is-leaf {
+ border-bottom: 1px solid #e8e8e8;
+ }
+ th.is-leaf {
+ background: #F7FBFF;
+ border-bottom: none;
+ }
+ }
+ .el-pagination {
+ padding: 20px 0 0 0;
+ }
+ .upload-demo,
+ .upload {
+ padding: 0;
+ }
+ .edit_container,
+ .edit {
+ padding: 0;
+ }
+ .el-input {
+ .el-input__suffix {
+ margin-top: -3px;
+ }
+ &.is-disabled {
+ .el-input__suffix {
+ margin-top: 0px;
+ }
+ }
+ }
+ .el-cascader {
+ .el-input {
+ .el-input__suffix {
+ margin-top: 0px;
+ }
+ }
+ }
+ .el-input__inner {
+ border-color: rgba($color: #000000, $alpha: 0.15);
+ height: 32px;
+ border-radius: 2px;
+ }
+}
+
+.admin-box:after,
+.admin-box:before {
+ content: "";
+ display: block;
+ clear: both;
+}
+
+.button-box {
+ background: $white-bg;
+ border: none;
+ padding: 0 0 10px 0px;
+}
+
+// table
+.has-gutter {
+ tr {
+ th {
+ background-color: #fafafa;
+ }
+ }
+}
+
+.el-table--striped {
+ .el-table__body {
+ tr.el-table__row--striped {
+ td {
+ background: #fff !important;
+ }
+ }
+ }
+}
+
+.el-table th,
+.el-table tr {
+ background-color: #ffffff;
+}
+
+.el-pagination {
+ .btn-prev,
+ .btn-next {
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ }
+ .el-pager {
+ li {
+ color: #666;
+ font-size: 12px;
+ margin: 0 5px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ }
+ }
+ padding: 20px 0 !important;
+}
+
+.el-row {
+ padding: 10px 0;
+ .el-col>label {
+ line-height: 30px;
+ text-align: right;
+ width: 80%;
+ padding-right: 15px;
+ display: inline-block;
+ }
+ .line {
+ line-height: 30px;
+ text-align: center;
+ }
+}
+
+.edit_container {
+ background-color: $white-bg;
+ padding: 15px;
+ .el-button {
+ margin: 15px 0;
+ }
+}
+
+.edit {
+ background-color: $white-bg;
+ .el-button {
+ margin: 15px 0;
+ }
+}
+
+.el-container {
+ .tips {
+ margin-top: 10px;
+ font-size: 14px;
+ font-weight: 400;
+ color: #606266;
+ }
+}
+
+.el-container.layout-cont {
+ .main-cont.el-main {
+ background-color: $bg-main;
+ .menu-total {
+ cursor: pointer;
+ font-size: 24px;
+ color: #000000;
+ margin-top: 16px;
+ }
+ }
+}
+
+.el-container.layout-cont {
+ .main-cont {
+ .router-history {
+ // box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
+ background: #fff;
+ padding: 0 6px;
+ border-top: 1px solid $border-color;
+ padding: 0;
+ .el-tabs__header {
+ margin: 0px 0 0 0;
+ .el-tabs__item {
+ height: $height-nav-scroll;
+ height: $height-nav-scroll;
+ border: none;
+ border-left: 1px solid $border-color;
+ border-right: 1px solid $border-color;
+ +.el-tabs__item {
+ border-left: 0px solid $border-color;
+ }
+ }
+ .el-tabs__item.is-active {
+ background-color: rgba(64, 158, 255, .08);
+ }
+ .el-tabs__nav {
+ border: none;
+ }
+ }
+ }
+ }
+}
+
+.el-table__row {
+ .el-button.el-button--text.el-button--small {
+ position: relative;
+ }
+ // .el-button.el-button--text.el-button--small::after {
+ // content: '';
+ // position: absolute;
+ // width: 1px;
+ // height: 50%;
+ // top: 5px;
+ // margin-left: 15px;
+ // background-color: #e8e8e8;
+ // }
+ .cell {
+ button:last-child::after {
+ content: '' !important;
+ position: absolute !important;
+ width: 0px !important;
+ }
+ }
+}
+
+.clear:after,
+.clear:before {
+ content: "";
+ display: block;
+ clear: both;
+}
+
+.el-table--striped .el-table__body tr.el-table__row--level-1 td:first-child {
+ .cell {
+ .el-table__indent {
+ border-right: 1.5px solid #ccc;
+ margin-left: 6px;
+ }
+ .el-table__placeholder {
+ width: 10px;
+ }
+ }
+}
+
+.el-table--striped .el-table__body tr.el-table__row--level-2 td:first-child {
+ .cell {
+ .el-table__indent {
+ border-right: 1.5px solid #ccc;
+ margin-left: 6px;
+ }
+ .el-table__placeholder {
+ width: 10px;
+ }
+ }
+}
+
+$headerHigh: 52px;
+$mainHight: 100vh;
+.dropdown-group {
+ min-width: 100px;
+}
+
+.topfix {
+ position: fixed;
+ top: 0;
+ box-sizing: border-box;
+ z-index: 999;
+ >.el-row {
+ padding: 0;
+ .el-col-lg-14 {
+ height: 60px;
+ }
+ }
+}
+
+.layout-cont {
+ .right-box {
+ padding-top: 16px;
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ img {
+ vertical-align: middle;
+ border: 1px solid #ccc;
+ border-radius: 6px;
+ }
+ }
+ .header-cont {
+ padding: 0 16px;
+ height: $height-header;
+ background: #fff;
+ }
+ .main-cont {
+ .breadcrumb {
+ height: $height-header;
+ line-height: $height-header;
+ display: inline-block;
+ padding: 0;
+ margin-left: 46px;
+ font-size: 16px;
+ .el-breadcrumb__item {
+ .el-breadcrumb__inner {
+ color: rgba($color: #000000, $alpha: 0.45);
+ }
+ }
+ .el-breadcrumb__item:nth-last-child(1) {
+ .el-breadcrumb__inner {
+ color: rgba($color: #000000, $alpha: 0.65);
+ }
+ }
+ }
+ &.el-main {
+ overflow: auto;
+ background: #fff;
+ }
+ height: $mainHight !important;
+ overflow: visible;
+ position: relative;
+ .menu-total {
+ margin-left: 6px;
+ cursor: pointer;
+ float: left;
+ margin-top: 10px;
+ width: 30px;
+ height: 30px;
+ line-height: 30px;
+ font-size: 30px;
+ }
+ .aside {
+ overflow: auto;
+ // background: #fff;
+ &::-webkit-scrollbar {
+ display: none;
+ }
+ }
+ .el-menu-vertical {
+ height: calc(100vh - 60px) !important;
+ visibility: auto;
+ &:not(.el-menu--collapse) {
+ width: 220px;
+ }
+ }
+ .el-menu--collapse {
+ width: 54px;
+ li {
+ .el-tooltip,
+ .el-sub-menu__title {
+ padding: 0px 15px !important;
+ }
+ }
+ }
+ &::-webkit-scrollbar {
+ display: none;
+ }
+ &.main-left {
+ width: auto !important;
+ }
+ &.main-right {
+ .admin-title {
+ float: left;
+ font-size: 16px;
+ vertical-align: middle;
+ margin-left: 20px;
+ img {
+ vertical-align: middle;
+ }
+ &.collapse {
+ width: 53px;
+ }
+ }
+ }
+ }
+}
+
+.header-avatar {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.search-component {
+ display: inline-flex;
+ overflow: hidden;
+ text-align: center;
+ .el-input__inner {
+ border: none;
+ border-bottom: 1px solid #606266;
+ }
+ .el-dropdown-link {
+ cursor: pointer;
+ }
+ .search-icon {
+ font-size: $icon-size;
+ display: inline-block;
+ vertical-align: middle;
+ box-sizing: border-box;
+ color: rgba($color: #000000, $alpha: 0.65);
+ }
+ .dropdown-group {
+ min-width: 100px;
+ }
+ .user-box {
+ cursor: pointer;
+ margin-right: 24px;
+ color: rgba($color: #000000, $alpha: 0.65);
+ }
+}
+
+.transition-box {
+ overflow: hidden;
+ width: 160px;
+ margin-right: 32px;
+ text-align: center;
+ margin-top: -12px;
+ .el-input__wrapper{
+ .el-input__inner{
+ height: 100%;
+ }
+ box-shadow: none !important;
+ }
+ .el-select .el-input .el-input__wrapper.is-focus{
+ box-shadow: none !important;
+ }
+ .el-select .el-input.is-focus .el-input__wrapper{
+ box-shadow: none !important;
+ }
+}
+
+.screenfull {
+ overflow: hidden;
+ color: rgba($color: #000000, $alpha: 0.65);
+}
+
+.el-dropdown {
+ overflow: hidden;
+}
+
+// dashboard
+.card {
+ background-color: $white-bg;
+ padding: 20px;
+ border-radius: 4px;
+ overflow: hidden;
+ .car-left {
+ height: $height-car;
+ // width: 70%;
+ // float: left;
+ }
+ .car-right {
+ height: $height-car;
+ // width: 29%;
+ // float: left;
+ .flow,
+ .user-number,
+ .feedback {
+ width: $el-icon-mini;
+ height: $el-icon-mini;
+ display: inline-block;
+ border-radius: 50%;
+ line-height: $el-icon-mini;
+ text-align: center;
+ font-size: 13px;
+ margin-right: 5px;
+ }
+ .flow {
+ background-color: #fff7e8;
+ border-color: #feefd0;
+ color: #faad14;
+ }
+ .user-number {
+ background-color: #ecf5ff;
+ border-color: #d9ecff;
+ color: #409eff;
+ }
+ .feedback {
+ background-color: #eef9e8;
+ border-color: #dcf3d1;
+ color: #52c41a;
+ }
+ .card-item {
+ padding-right: 20px;
+ text-align: right;
+ margin-top: 12px;
+ b {
+ margin-top: 6px;
+ display: block;
+ }
+ }
+ }
+ .card-img {
+ width: $height-car;
+ height: $height-car;
+ display: inline-block;
+ float: left;
+ overflow: hidden;
+ img {
+ width: 100%;
+ height: 100%;
+ border-radius: 50%;
+ }
+ }
+ .text {
+ height: $height-car;
+ margin-left: 10px;
+ float: left;
+ margin-top: 14px;
+ h4 {
+ font-size: 20px;
+ color: #262626;
+ font-weight: 500;
+ white-space: nowrap;
+ word-break: break-all;
+ text-overflow: ellipsis;
+ }
+ .tips-text {
+ color: #8c8c8c;
+ margin-top: 8px;
+ .el-icon {
+ margin-right: 8px;
+ display: inline-block;
+ }
+ }
+ }
+}
+
+.shadow {
+ margin: 4px 0;
+ .grid-content {
+ background-color: $white-bg;
+ border-radius: 4px;
+ text-align: center;
+ padding: 10px 0;
+ cursor: pointer;
+ .el-icon {
+ width: $el-icon-small;
+ height: $el-icon-small;
+ font-size: $el-icon-small;
+ margin-bottom: 8px;
+ }
+ }
+}
+
+.gva-btn-list {
+ margin-bottom: 12px;
+ display: flex;
+ .el-button+.el-button {
+ margin-left: 12px;
+ }
+}
+
+.justify-content-flex-end {
+ justify-content: flex-end;
+}
\ No newline at end of file
diff --git a/src/style/mobile.scss b/src/style/mobile.scss
new file mode 100644
index 0000000..a593f2c
--- /dev/null
+++ b/src/style/mobile.scss
@@ -0,0 +1,77 @@
+@import '@/style/basics.scss';
+@media screen and (min-width: 320px)and (max-width: 750px) {
+ .el-header {
+ padding: 0 $padding-xs;
+ }
+ .layout-cont {
+ .main-cont {
+ .breadcrumb {
+ padding: 0 $padding-xs;
+ }
+ }
+ }
+ .layout-cont {
+ .right-box {
+ margin-right: $margin-xs;
+ }
+ }
+ .el-main {
+ .admin-box {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .big.admin-box {
+ padding: 0;
+ }
+ .big {
+ .bottom {
+ .chart-player {
+ height: auto!important;
+ margin-bottom: 15px;
+ }
+ .todoapp {
+ background-color: #fff;
+ padding-bottom: 10px;
+ }
+ }
+ }
+ }
+ .card .car-left,
+ .card .car-right {
+ width: 100%;
+ height: 100%;
+ }
+ .card {
+ padding-left: $padding-xs;
+ padding-right: $padding-xs;
+ }
+ .card {
+ .text {
+ width: 100%;
+ h4 {
+ white-space: break-spaces;
+ }
+ }
+ }
+ .shadow {
+ margin-left: 4px;
+ margin-right: 4px;
+ .grid-content {
+ margin-bottom: 10px;
+ padding: 0;
+ }
+ }
+ .el-dialog {
+ width: 90%;
+ }
+ .el-transfer {
+ .el-transfer-panel {
+ width: 40%;
+ display: inline-block;
+ }
+ .el-transfer__buttons {
+ padding: 0 5px;
+ display: inline-block;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/style/newLogin.scss b/src/style/newLogin.scss
new file mode 100644
index 0000000..5d89b3c
--- /dev/null
+++ b/src/style/newLogin.scss
@@ -0,0 +1,105 @@
+#userLayout {
+ margin: 0;
+ padding: 0;
+ background-image: url("@/assets/login_background.jpg");
+ background-size: cover;
+ width: 100%;
+ height: 100%;
+ position: relative;
+ .input-icon {
+ padding-right: 6px;
+ padding-top: 4px;
+ }
+ .login_panel {
+ position: absolute;
+ top: 3vh;
+ left: 2vw;
+ width: 96vw;
+ height: 94vh;
+ background-color: rgba(255, 255, 255, .8);
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: space-evenly;
+ .login_panel_right {
+ background-image: url("@/assets/login_left.svg");
+ background-size: cover;
+ width: 40%;
+ height: 60%;
+ float: right !important;
+ }
+ .login_panel_form {
+ width: 420px;
+ background-color: #fff;
+ padding: 40px 40px 40px 40px;
+ border-radius: 10px;
+ box-shadow: 2px 3px 7px rgba(0, 0, 0, .2);
+ .login_panel_form_title {
+ display: flex;
+ align-items: center;
+ margin: 30px 0;
+ .login_panel_form_title_logo {
+ width: 90px;
+ height: 72px;
+ }
+ .login_panel_form_title_p {
+ font-size: 40px;
+ padding-left: 20px;
+ }
+ }
+ .vPicBox {
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
+ }
+ .vPic {
+ width: 33%;
+ height: 38px;
+ background: #ccc;
+ img {
+ width: 100%;
+ height: 100%;
+ vertical-align: middle;
+ }
+ }
+ }
+ .login_panel_foot {
+ position: absolute;
+ bottom: 20px;
+ .links {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ .link-icon {
+ width: 30px;
+ height: 30px;
+ }
+ }
+ .copyright {
+ color: #777777;
+ margin-top: 5px;
+ }
+ }
+ }
+}
+
+//小屏幕不显示右侧,将登录框居中
+@media (max-width: 750px) {
+ .login_panel_right {
+ display: none;
+ }
+ .login_panel {
+ width: 100vw;
+ height: 100vh;
+ top: 0;
+ left: 0;
+ }
+ .login_panel_form {
+ width: 100%;
+ }
+}
+
+
+/*
+ powerBy : bypanghu@163.com
+*/
\ No newline at end of file
diff --git a/src/utils/asyncRouter.js b/src/utils/asyncRouter.js
new file mode 100644
index 0000000..48809ed
--- /dev/null
+++ b/src/utils/asyncRouter.js
@@ -0,0 +1,33 @@
+const viewModules = import.meta.glob('../view/**/*.vue')
+const pluginModules = import.meta.glob('../plugin/**/*.vue')
+
+export const asyncRouterHandle = (asyncRouter) => {
+ asyncRouter.forEach(item => {
+ if (item.component) {
+ if (item.component.split('/')[0] === 'view') {
+ item.component = dynamicImport(viewModules, item.component)
+ } else if (item.component.split('/')[0] === 'plugin') {
+ item.component = dynamicImport(pluginModules, item.component)
+ }
+ } else {
+ delete item['component']
+ }
+ if (item.children) {
+ asyncRouterHandle(item.children)
+ }
+ })
+}
+
+function dynamicImport(
+ dynamicViewsModules,
+ component
+) {
+ const keys = Object.keys(dynamicViewsModules)
+ const matchKeys = keys.filter((key) => {
+ const k = key.replace('../', '')
+ return k === component
+ })
+ const matchKey = matchKeys[0]
+
+ return dynamicViewsModules[matchKey]
+}
diff --git a/src/utils/btnAuth.js b/src/utils/btnAuth.js
new file mode 100644
index 0000000..f94fa9b
--- /dev/null
+++ b/src/utils/btnAuth.js
@@ -0,0 +1,6 @@
+import { useRoute } from 'vue-router'
+import { reactive } from 'vue'
+export const useBtnAuth = () => {
+ const route = useRoute()
+ return route.meta.btns || reactive({})
+}
diff --git a/src/utils/bus.js b/src/utils/bus.js
new file mode 100644
index 0000000..4b673fa
--- /dev/null
+++ b/src/utils/bus.js
@@ -0,0 +1,6 @@
+
+// using ES6 modules
+import mitt from 'mitt'
+
+export const emitter = mitt()
+
diff --git a/src/utils/closeThisPage.js b/src/utils/closeThisPage.js
new file mode 100644
index 0000000..b2a0c05
--- /dev/null
+++ b/src/utils/closeThisPage.js
@@ -0,0 +1,5 @@
+import { emitter } from '@/utils/bus.js'
+
+export const closeThisPage = () => {
+ emitter.emit('closeThisPage')
+}
diff --git a/src/utils/date.js b/src/utils/date.js
new file mode 100644
index 0000000..6bb8570
--- /dev/null
+++ b/src/utils/date.js
@@ -0,0 +1,30 @@
+// 对Date的扩展,将 Date 转化为指定格式的String
+// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
+// 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
+// (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
+// (new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
+// eslint-disable-next-line no-extend-native
+Date.prototype.Format = function(fmt) {
+ var o = {
+ 'M+': this.getMonth() + 1, // 月份
+ 'd+': this.getDate(), // 日
+ 'h+': this.getHours(), // 小时
+ 'm+': this.getMinutes(), // 分
+ 's+': this.getSeconds(), // 秒
+ 'q+': Math.floor((this.getMonth() + 3) / 3), // 季度
+ 'S': this.getMilliseconds() // 毫秒
+ }
+ if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length)) }
+ for (var k in o) {
+ if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))) }
+ }
+ return fmt
+}
+
+export function formatTimeToStr(times, pattern) {
+ var d = new Date(times).Format('yyyy-MM-dd hh:mm:ss')
+ if (pattern) {
+ d = new Date(times).Format(pattern)
+ }
+ return d.toLocaleString()
+}
diff --git a/src/utils/dictionary.js b/src/utils/dictionary.js
new file mode 100644
index 0000000..1b0dba8
--- /dev/null
+++ b/src/utils/dictionary.js
@@ -0,0 +1,19 @@
+import { useDictionaryStore } from '@/pinia/modules/dictionary'
+// 获取字典方法 使用示例 getDict('sex').then(res) 或者 async函数下 const res = await getDict('sex')
+export const getDict = async(type) => {
+ const dictionaryStore = useDictionaryStore()
+ await dictionaryStore.getDictionary(type)
+ return dictionaryStore.dictionaryMap[type]
+}
+
+// 字典文字展示方法
+export const showDictLabel = (dict, code) => {
+ if (!dict) {
+ return ''
+ }
+ const dictMap = {}
+ dict.forEach(item => {
+ dictMap[item.value] = item.label
+ })
+ return dictMap[code]
+}
diff --git a/src/utils/downloadImg.js b/src/utils/downloadImg.js
new file mode 100644
index 0000000..93fb222
--- /dev/null
+++ b/src/utils/downloadImg.js
@@ -0,0 +1,19 @@
+export const downloadImage = (imgsrc, name) => { // 下载图片地址和图片名
+ var image = new Image()
+ image.setAttribute('crossOrigin', 'anonymous')
+ image.onload = function() {
+ var canvas = document.createElement('canvas')
+ canvas.width = image.width
+ canvas.height = image.height
+ var context = canvas.getContext('2d')
+ context.drawImage(image, 0, 0, image.width, image.height)
+ var url = canvas.toDataURL('image/png') // 得到图片的base64编码数据
+
+ var a = document.createElement('a') // 生成一个a元素
+ var event = new MouseEvent('click') // 创建一个单击事件
+ a.download = name || 'photo' // 设置图片名称
+ a.href = url // 将生成的URL设置为a.href属性
+ a.dispatchEvent(event) // 触发a的单击事件
+ }
+ image.src = imgsrc
+}
diff --git a/src/utils/fmtRouterTitle.js b/src/utils/fmtRouterTitle.js
new file mode 100644
index 0000000..bcaeb67
--- /dev/null
+++ b/src/utils/fmtRouterTitle.js
@@ -0,0 +1,13 @@
+export const fmtTitle = (title, now) => {
+ const reg = /\$\{(.+?)\}/
+ const reg_g = /\$\{(.+?)\}/g
+ const result = title.match(reg_g)
+ if (result) {
+ result.forEach((item) => {
+ const key = item.match(reg)[1]
+ const value = now.params[key] || now.query[key]
+ title = title.replace(item, value)
+ })
+ }
+ return title
+}
diff --git a/src/utils/format.js b/src/utils/format.js
new file mode 100644
index 0000000..b8361be
--- /dev/null
+++ b/src/utils/format.js
@@ -0,0 +1,28 @@
+import { formatTimeToStr } from '@/utils/date'
+import { getDict } from '@/utils/dictionary'
+
+export const formatBoolean = (bool) => {
+ if (bool !== null) {
+ return bool ? '是' : '否'
+ } else {
+ return ''
+ }
+}
+export const formatDate = (time) => {
+ if (time !== null && time !== '') {
+ var date = new Date(time)
+ return formatTimeToStr(date, 'yyyy-MM-dd hh:mm:ss')
+ } else {
+ return ''
+ }
+}
+
+export const filterDict = (value, options) => {
+ const rowLabel = options && options.filter(item => item.value === value)
+ return rowLabel && rowLabel[0] && rowLabel[0].label
+}
+
+export const getDictFunc = async(type) => {
+ const dicts = await getDict(type)
+ return dicts
+}
diff --git a/src/utils/image.js b/src/utils/image.js
new file mode 100644
index 0000000..6e0d1e8
--- /dev/null
+++ b/src/utils/image.js
@@ -0,0 +1,92 @@
+export default class ImageCompress {
+ constructor(file, fileSize, maxWH = 1920) {
+ this.file = file
+ this.fileSize = fileSize
+ this.maxWH = maxWH // 最大长宽
+ }
+
+ compress() {
+ // 压缩
+ const fileType = this.file.type
+ const fileSize = this.file.size / 1024
+ return new Promise(resolve => {
+ const reader = new FileReader()
+ reader.readAsDataURL(this.file)
+ reader.onload = () => {
+ const canvas = document.createElement('canvas')
+ const img = document.createElement('img')
+ img.src = reader.result
+ img.onload = () => {
+ const ctx = canvas.getContext('2d')
+ const _dWH = this.dWH(img.width, img.height, this.maxWH)
+ canvas.width = _dWH.width
+ canvas.height = _dWH.height
+
+ // 清空后, 重写画布
+ ctx.clearRect(0, 0, canvas.width, canvas.height)
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
+
+ const newImgData = canvas.toDataURL(fileType, 0.90)
+
+ // 压缩宽高后的图像大小
+ const newImgSize = this.fileSizeKB(newImgData)
+
+ if (newImgSize > this.fileSize) {
+ console.log('图片尺寸太大!' + fileSize + ' >> ' + newImgSize)
+ }
+
+ const blob = this.dataURLtoBlob(newImgData, fileType)
+ const nfile = new File([blob], this.file.name)
+ resolve(nfile)
+ }
+ }
+ })
+ }
+
+ /**
+ * 长宽等比缩小
+ * 图像的一边(长或宽)为最大目标值
+ */
+ dWH(srcW, srcH, dMax) {
+ const defaults = {
+ width: srcW,
+ height: srcH
+ }
+ if (Math.max(srcW, srcH) > dMax) {
+ if (srcW > srcH) {
+ defaults.width = dMax
+ defaults.height = Math.round(srcH * (dMax / srcW))
+ return defaults
+ } else {
+ defaults.height = dMax
+ defaults.width = Math.round(srcW * (dMax / srcH))
+ return defaults
+ }
+ } else {
+ return defaults
+ }
+ }
+
+ fileSizeKB(dataURL) {
+ let sizeKB = 0
+ sizeKB = Math.round((dataURL.split(',')[1].length * 3 / 4) / 1024)
+ return sizeKB
+ }
+
+ /**
+ * 转为Blob
+ */
+ dataURLtoBlob(dataURL, fileType) {
+ const byteString = atob(dataURL.split(',')[1])
+ let mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0]
+ const ab = new ArrayBuffer(byteString.length)
+ const ia = new Uint8Array(ab)
+ for (let i = 0; i < byteString.length; i++) {
+ ia[i] = byteString.charCodeAt(i)
+ }
+ if (fileType) {
+ mimeString = fileType
+ }
+ return new Blob([ab], { type: mimeString, lastModifiedDate: new Date() })
+ }
+}
diff --git a/src/utils/page.js b/src/utils/page.js
new file mode 100644
index 0000000..6a3c6d8
--- /dev/null
+++ b/src/utils/page.js
@@ -0,0 +1,9 @@
+import { fmtTitle } from '@/utils/fmtRouterTitle'
+import config from '@/core/config'
+export default function getPageTitle(pageTitle, route) {
+ if (pageTitle) {
+ const title = fmtTitle(pageTitle, route)
+ return `${title} - ${config.appName}`
+ }
+ return `${config.appName}`
+}
diff --git a/src/utils/positionToCode.js b/src/utils/positionToCode.js
new file mode 100644
index 0000000..3fb1f9f
--- /dev/null
+++ b/src/utils/positionToCode.js
@@ -0,0 +1,36 @@
+export const initDom = () => {
+ if (import.meta.env.MODE === 'development') {
+ document.onmousedown = function(e) {
+ if (e.shiftKey && e.button === 0) {
+ e.preventDefault()
+ sendRequestToOpenFileInEditor(getFilePath(e))
+ }
+ }
+ }
+}
+
+const getFilePath = (e) => {
+ let element = e
+ if (e.target) {
+ element = e.target
+ }
+ if (!element || !element.getAttribute) return null
+ if (element.getAttribute('code-location')) {
+ return element.getAttribute('code-location')
+ }
+ return getFilePath(element.parentNode)
+}
+
+const sendRequestToOpenFileInEditor = (filePath) => {
+ const protocol = window.location.protocol
+ ? window.location.protocol
+ : 'http:'
+ const hostname = window.location.hostname
+ ? window.location.hostname
+ : 'localhost'
+ const port = window.location.port ? window.location.port : '80'
+ fetch(`${protocol}//${hostname}:${port}/gvaPositionCode?filePath=${filePath}`)
+ .catch((error) => {
+ console.log(error)
+ })
+}
diff --git a/src/utils/request.js b/src/utils/request.js
new file mode 100644
index 0000000..6ca0ef7
--- /dev/null
+++ b/src/utils/request.js
@@ -0,0 +1,141 @@
+import axios from 'axios' // 引入axios
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { useUserStore } from '@/pinia/modules/user'
+import { emitter } from '@/utils/bus.js'
+import router from '@/router/index'
+
+const service = axios.create({
+ baseURL: import.meta.env.VITE_BASE_API,
+ timeout: 99999
+})
+let acitveAxios = 0
+let timer
+const showLoading = () => {
+ acitveAxios++
+ if (timer) {
+ clearTimeout(timer)
+ }
+ timer = setTimeout(() => {
+ if (acitveAxios > 0) {
+ emitter.emit('showLoading')
+ }
+ }, 400)
+}
+
+const closeLoading = () => {
+ acitveAxios--
+ if (acitveAxios <= 0) {
+ clearTimeout(timer)
+ emitter.emit('closeLoading')
+ }
+}
+// http request 拦截器
+service.interceptors.request.use(
+ config => {
+ if (!config.donNotShowLoading) {
+ showLoading()
+ }
+ const userStore = useUserStore()
+ config.headers = {
+ 'Content-Type': 'application/json',
+ 'x-token': userStore.token,
+ 'x-user-id': userStore.userInfo.ID,
+ ...config.headers
+ }
+ return config
+ },
+ error => {
+ if (!error.config.donNotShowLoading) {
+ closeLoading()
+ }
+ ElMessage({
+ showClose: true,
+ message: error,
+ type: 'error'
+ })
+ return error
+ }
+)
+
+// http response 拦截器
+service.interceptors.response.use(
+ response => {
+ const userStore = useUserStore()
+ if (!response.config.donNotShowLoading) {
+ closeLoading()
+ }
+ if (response.headers['new-token']) {
+ userStore.setToken(response.headers['new-token'])
+ }
+ if (response.data.code === 0 || response.headers.success === 'true') {
+ if (response.headers.msg) {
+ response.data.msg = decodeURI(response.headers.msg)
+ }
+ return response.data
+ } else {
+ ElMessage({
+ showClose: true,
+ message: response.data.msg || decodeURI(response.headers.msg),
+ type: 'error'
+ })
+ if (response.data.data && response.data.data.reload) {
+ userStore.token = ''
+ localStorage.clear()
+ router.push({ name: 'Login', replace: true })
+ }
+ return response.data.msg ? response.data : response
+ }
+ },
+ error => {
+ if (!error.config.donNotShowLoading) {
+ closeLoading()
+ }
+
+ if (!error.response) {
+ ElMessageBox.confirm(`
+ 检测到请求错误
+ ${error}
+ `, '请求报错', {
+ dangerouslyUseHTMLString: true,
+ distinguishCancelAndClose: true,
+ confirmButtonText: '稍后重试',
+ cancelButtonText: '取消'
+ })
+ return
+ }
+
+ switch (error.response.status) {
+ case 500:
+ ElMessageBox.confirm(`
+ 检测到接口错误${error}
+ 错误码 500 :此类错误内容常见于后台panic,请先查看后台日志,如果影响您正常使用可强制登出清理缓存
+ `, '接口报错', {
+ dangerouslyUseHTMLString: true,
+ distinguishCancelAndClose: true,
+ confirmButtonText: '清理缓存',
+ cancelButtonText: '取消'
+ })
+ .then(() => {
+ const userStore = useUserStore()
+ userStore.token = ''
+ localStorage.clear()
+ router.push({ name: 'Login', replace: true })
+ })
+ break
+ case 404:
+ ElMessageBox.confirm(`
+ 检测到接口错误${error}
+ 错误码 404 :此类错误多为接口未注册(或未重启)或者请求路径(方法)与api路径(方法)不符--如果为自动化代码请检查是否存在空格
+ `, '接口报错', {
+ dangerouslyUseHTMLString: true,
+ distinguishCancelAndClose: true,
+ confirmButtonText: '我知道了',
+ cancelButtonText: '取消'
+ })
+ break
+ }
+
+ return error
+ }
+)
+export default service
diff --git a/src/utils/stringFun.js b/src/utils/stringFun.js
new file mode 100644
index 0000000..eac4179
--- /dev/null
+++ b/src/utils/stringFun.js
@@ -0,0 +1,29 @@
+/* eslint-disable */
+export const toUpperCase = (str) => {
+ if (str[0]) {
+ return str.replace(str[0], str[0].toUpperCase())
+ } else {
+ return ''
+ }
+}
+
+export const toLowerCase = (str) => {
+ if (str[0]) {
+ return str.replace(str[0], str[0].toLowerCase())
+ } else {
+ return ''
+ }
+}
+
+// 驼峰转换下划线
+export const toSQLLine = (str) => {
+ if (str === 'ID') return 'ID'
+ return str.replace(/([A-Z])/g, "_$1").toLowerCase();
+}
+
+// 下划线转换驼峰
+export const toHump = (name) => {
+ return name.replace(/\_(\w)/g, function(all, letter) {
+ return letter.toUpperCase();
+ });
+}
\ No newline at end of file
diff --git a/src/view/about/index.vue b/src/view/about/index.vue
new file mode 100644
index 0000000..7506471
--- /dev/null
+++ b/src/view/about/index.vue
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+ gin-vue-admin
+
+
+
+
+
+ flipped-aurora团队
+
+
+
+
+
+
+
+ 提交记录
+
+
+
+
+
+ {{ item.title }}
+ {{ item.message }}
+
+
+
+
+ Load more
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/dashboard/dashboardCharts/echartsLine.vue b/src/view/dashboard/dashboardCharts/echartsLine.vue
new file mode 100644
index 0000000..f525619
--- /dev/null
+++ b/src/view/dashboard/dashboardCharts/echartsLine.vue
@@ -0,0 +1,129 @@
+
+
+
+
+
diff --git a/src/view/dashboard/dashboardTable/dashboardTable.vue b/src/view/dashboard/dashboardTable/dashboardTable.vue
new file mode 100644
index 0000000..4a6bb09
--- /dev/null
+++ b/src/view/dashboard/dashboardTable/dashboardTable.vue
@@ -0,0 +1,112 @@
+
+
+
+ 更新日志
+
+
+
+
+ {{ key+1 }}
+
+
{{ item.message }}
+
{{ item.from }}
+
+
+
+
+
+
+
+
+
diff --git a/src/view/dashboard/index.vue b/src/view/dashboard/index.vue
new file mode 100644
index 0000000..b966deb
--- /dev/null
+++ b/src/view/dashboard/index.vue
@@ -0,0 +1,329 @@
+
+
+
+
+
+
早安,管理员,请开始一天的工作吧
+
{{ weatherInfo }}
+
+
+
+
+
+
+
+ 今日流量 (1231231)
+
+
+
+
+
+
+
+
+
+
+ 好评率 (99%)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ card.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/dashboard/weather.js b/src/view/dashboard/weather.js
new file mode 100644
index 0000000..11b2152
--- /dev/null
+++ b/src/view/dashboard/weather.js
@@ -0,0 +1,31 @@
+
+import axios from 'axios'
+import { ref } from 'vue'
+
+const weatherInfo = ref('今日晴,0℃ - 10℃,天气寒冷,注意添加衣物。')
+const amapKey = '8e8baa8a7317586c29ec694895de6e0a'
+
+export const useWeatherInfo = () => {
+ ip()
+ return weatherInfo
+}
+
+export const ip = async() => {
+ // key换成你自己的 https://console.amap.com/dev/index
+ if (amapKey === '') {
+ return false
+ }
+ const res = await axios.get('https://restapi.amap.com/v3/ip?key=' + amapKey)
+ if (res.data.adcode) {
+ getWeather(res.data.adcode)
+ }
+}
+
+const getWeather = async(code) => {
+ const response = await axios.get('https://restapi.amap.com/v3/weather/weatherInfo?key=' + amapKey + '&extensions=base&city=' + code)
+ if (response.data.status === '1') {
+ const s = response.data.lives[0]
+ weatherInfo.value = s.city + ' 天气:' + s.weather + ' 温度:' + s.temperature + '摄氏度 风向:' + s.winddirection + ' 风力:' + s.windpower + '级 空气湿度:' + s.humidity
+ }
+}
+
diff --git a/src/view/error/index.vue b/src/view/error/index.vue
new file mode 100644
index 0000000..4a10d83
--- /dev/null
+++ b/src/view/error/index.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
页面被神秘力量吸走了(如果您是开源版请联系我们修复)
+
常见问题为当前此角色无当前路由,如果确定要使用本路由,请到角色管理进行分配
+
↓
+
+
+
+
+
+
+
+
+
diff --git a/src/view/error/reload.vue b/src/view/error/reload.vue
new file mode 100644
index 0000000..fdeb8ce
--- /dev/null
+++ b/src/view/error/reload.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/src/view/example/breakpoint/breakpoint.vue b/src/view/example/breakpoint/breakpoint.vue
new file mode 100644
index 0000000..5f683ad
--- /dev/null
+++ b/src/view/example/breakpoint/breakpoint.vue
@@ -0,0 +1,266 @@
+
+
+
+
大文件上传
+
+
上传文件
+
请上传不超过5MB的文件
+
+
+
+
+
+
+ {{ file.name }}
+ {{ percentage }}%
+
+
+
+
+
此版本为先行体验功能测试版,样式美化和性能优化正在进行中,上传切片文件和合成的完整文件分别再QMPlusserver目录的breakpointDir文件夹和fileDir文件夹
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/example/customer/customer.vue b/src/view/example/customer/customer.vue
new file mode 100644
index 0000000..215fe8f
--- /dev/null
+++ b/src/view/example/customer/customer.vue
@@ -0,0 +1,182 @@
+
+
+
+
+
+ 新增
+
+
+
+
+
+ {{ formatDate(scope.row.CreatedAt) }}
+
+
+
+
+
+
+
+ 变更
+
+ 确定要删除吗?
+
+ 取消
+ 确定
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/example/index.vue b/src/view/example/index.vue
new file mode 100644
index 0000000..554852f
--- /dev/null
+++ b/src/view/example/index.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/example/upload/upload.vue b/src/view/example/upload/upload.vue
new file mode 100644
index 0000000..cfab617
--- /dev/null
+++ b/src/view/example/upload/upload.vue
@@ -0,0 +1,210 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatDate(scope.row.UpdatedAt) }}
+
+
+
+
+ {{ scope.row.name }}
+
+
+
+
+
+ {{ scope.row.tag }}
+
+
+
+
+
+ 下载
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/init/index.vue b/src/view/init/index.vue
new file mode 100644
index 0000000..a3261ae
--- /dev/null
+++ b/src/view/init/index.vue
@@ -0,0 +1,320 @@
+
+
+
+
+
+
GIN-VUE-ADMIN
+
初始化须知
+
1.您需有用一定的VUE和GOLANG基础
+
2.请您确认是否已经阅读过官方文档
+
3.请您确认是否了解后续的配置流程
+
注:开发组不为文档中书写过的内容提供无偿服务
+
+
+ 阅读文档
+
+
+ 我已确认
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/layout/aside/asideComponent/asyncSubmenu.vue b/src/view/layout/aside/asideComponent/asyncSubmenu.vue
new file mode 100644
index 0000000..7bbbd29
--- /dev/null
+++ b/src/view/layout/aside/asideComponent/asyncSubmenu.vue
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+ {{ routerInfo.meta.title }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/layout/aside/asideComponent/index.vue b/src/view/layout/aside/asideComponent/index.vue
new file mode 100644
index 0000000..2b34bae
--- /dev/null
+++ b/src/view/layout/aside/asideComponent/index.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/layout/aside/asideComponent/menuItem.vue b/src/view/layout/aside/asideComponent/menuItem.vue
new file mode 100644
index 0000000..8d4abbd
--- /dev/null
+++ b/src/view/layout/aside/asideComponent/menuItem.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/layout/aside/historyComponent/history.vue b/src/view/layout/aside/historyComponent/history.vue
new file mode 100644
index 0000000..f9d6dce
--- /dev/null
+++ b/src/view/layout/aside/historyComponent/history.vue
@@ -0,0 +1,363 @@
+
+
+
+
+
+
+ {{ fmtTitle(item.meta.title,item) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/layout/aside/index.vue b/src/view/layout/aside/index.vue
new file mode 100644
index 0000000..270614c
--- /dev/null
+++ b/src/view/layout/aside/index.vue
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/layout/bottomInfo/bottomInfo.vue b/src/view/layout/bottomInfo/bottomInfo.vue
new file mode 100644
index 0000000..0346424
--- /dev/null
+++ b/src/view/layout/bottomInfo/bottomInfo.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
diff --git a/src/view/layout/index.vue b/src/view/layout/index.vue
new file mode 100644
index 0000000..6e58323
--- /dev/null
+++ b/src/view/layout/index.vue
@@ -0,0 +1,258 @@
+
+
+
+
+
+
+
+
{{ $GIN_VUE_ADMIN.appName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/layout/screenfull/index.vue b/src/view/layout/screenfull/index.vue
new file mode 100644
index 0000000..66491a0
--- /dev/null
+++ b/src/view/layout/screenfull/index.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/view/layout/search/search.vue b/src/view/layout/search/search.vue
new file mode 100644
index 0000000..a4d8f10
--- /dev/null
+++ b/src/view/layout/search/search.vue
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
diff --git a/src/view/layout/setting/index.vue b/src/view/layout/setting/index.vue
new file mode 100644
index 0000000..0140a25
--- /dev/null
+++ b/src/view/layout/setting/index.vue
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 简约白
+
+
+
+
+
+
+
+
+
+
+ 商务黑
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/login/index.vue b/src/view/login/index.vue
new file mode 100644
index 0000000..4a0ce38
--- /dev/null
+++ b/src/view/login/index.vue
@@ -0,0 +1,228 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/view/person/person.vue b/src/view/person/person.vue
new file mode 100644
index 0000000..fa874b3
--- /dev/null
+++ b/src/view/person/person.vue
@@ -0,0 +1,561 @@
+
+
+
+
+
+
+
+
+
+
+
+ 重新上传
+
+
+
+ {{ userStore.userInfo.nickName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
这个家伙很懒,什么都没有留下
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ time>0?`(${time}s)后重新获取`:'获取验证码' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ emailTime>0?`(${emailTime}s)后重新获取`:'获取验证码' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/routerHolder.vue b/src/view/routerHolder.vue
new file mode 100644
index 0000000..d65fc4e
--- /dev/null
+++ b/src/view/routerHolder.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/api/api.vue b/src/view/superAdmin/api/api.vue
new file mode 100644
index 0000000..0c2b76a
--- /dev/null
+++ b/src/view/superAdmin/api/api.vue
@@ -0,0 +1,391 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
新增
+
+ 确定要删除吗?
+
+ 取消
+ 确定
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.method }} / {{ methodFilter(scope.row.method) }}
+
+
+
+
+
+
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/authority/authority.vue b/src/view/superAdmin/authority/authority.vue
new file mode 100644
index 0000000..1d80c5f
--- /dev/null
+++ b/src/view/superAdmin/authority/authority.vue
@@ -0,0 +1,410 @@
+
+
+
+
+
+ 新增角色
+
+
+
+
+
+
+ 设置权限
+ 新增子角色
+ 拷贝
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/authority/components/apis.vue b/src/view/superAdmin/authority/components/apis.vue
new file mode 100644
index 0000000..dd1c522
--- /dev/null
+++ b/src/view/superAdmin/authority/components/apis.vue
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/authority/components/datas.vue b/src/view/superAdmin/authority/components/datas.vue
new file mode 100644
index 0000000..4f2facd
--- /dev/null
+++ b/src/view/superAdmin/authority/components/datas.vue
@@ -0,0 +1,118 @@
+
+
+
+ 确 定
+ 全选
+ 本角色
+ 本角色及子角色
+
+
+
+ {{ item.authorityName }}
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/authority/components/menus.vue b/src/view/superAdmin/authority/components/menus.vue
new file mode 100644
index 0000000..31c73cc
--- /dev/null
+++ b/src/view/superAdmin/authority/components/menus.vue
@@ -0,0 +1,225 @@
+
+
+
+
+ 确 定
+
+
+
+
+
+ {{ node.label }}
+
+ setDefault(data)"
+ >
+ {{ row.defaultRouter === data.name?"首页":"设为首页" }}
+
+
+
+ OpenBtn(data)"
+ >
+ 分配按钮
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/dictionary/sysDictionary.vue b/src/view/superAdmin/dictionary/sysDictionary.vue
new file mode 100644
index 0000000..5b4377e
--- /dev/null
+++ b/src/view/superAdmin/dictionary/sysDictionary.vue
@@ -0,0 +1,375 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+ 新增
+
+
+
+
+ {{
+ formatDate(scope.row.CreatedAt)
+ }}
+
+
+
+
+
+
+
+ {{
+ formatBoolean(scope.row.status)
+ }}
+
+
+
+
+
+
+ 详情
+ 变更
+
+ 确定要删除吗?
+
+ 取消
+ 确定
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/dictionary/sysDictionaryDetail.vue b/src/view/superAdmin/dictionary/sysDictionaryDetail.vue
new file mode 100644
index 0000000..4e2d55d
--- /dev/null
+++ b/src/view/superAdmin/dictionary/sysDictionaryDetail.vue
@@ -0,0 +1,291 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+ 新增字典项
+
+
+
+
+ {{ formatDate(scope.row.CreatedAt) }}
+
+
+
+
+
+
+
+ {{ formatBoolean(scope.row.status) }}
+
+
+
+
+
+
+ 变更
+
+ 确定要删除吗?
+
+ 取消
+ 确定
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/index.vue b/src/view/superAdmin/index.vue
new file mode 100644
index 0000000..28c4fde
--- /dev/null
+++ b/src/view/superAdmin/index.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/menu/icon.vue b/src/view/superAdmin/menu/icon.vue
new file mode 100644
index 0000000..0b97b75
--- /dev/null
+++ b/src/view/superAdmin/menu/icon.vue
@@ -0,0 +1,1190 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.key }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/menu/menu.vue b/src/view/superAdmin/menu/menu.vue
new file mode 100644
index 0000000..7698953
--- /dev/null
+++ b/src/view/superAdmin/menu/menu.vue
@@ -0,0 +1,529 @@
+
+
+
+
+ 新增根菜单
+
+
+
+
+
+
+
+ {{ scope.row.meta.title }}
+
+
+
+
+
+
+
+
+ {{ scope.row.meta.icon }}
+
+
+
+
+
+
+
+ {{ scope.row.hidden?"隐藏":"显示" }}
+
+
+
+
+
+
+
+ 添加子菜单
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 路由Path
+ 添加参数
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 如果菜单包含子菜单,请创建router-view二级路由页面或者点我设置
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 高亮菜单
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 是否为基础页面
+
+
+
+
+
+
+
+
+
+
+
+
+
+
新增菜单参数
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 删除
+
+
+
+
+
+
新增可控按钮
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/operation/sysOperationRecord.vue b/src/view/superAdmin/operation/sysOperationRecord.vue
new file mode 100644
index 0000000..6bc43eb
--- /dev/null
+++ b/src/view/superAdmin/operation/sysOperationRecord.vue
@@ -0,0 +1,257 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+ 确定要删除吗?
+
+ 取消
+ 确定
+
+
+ 删除
+
+
+
+
+
+
+
+ {{ scope.row.user.userName }}({{ scope.row.user.nickName }})
+
+
+
+ {{ formatDate(scope.row.CreatedAt) }}
+
+
+
+
+ {{ scope.row.status }}
+
+
+
+
+
+
+
+
+
+
+
+
{{ fmtBody(scope.row.body) }}
+
+
+
+
+
+
+
无
+
+
+
+
+
+
+
+
+
{{ fmtBody(scope.row.resp) }}
+
+
+
+
+
+
无
+
+
+
+
+
+
+ 确定要删除吗?
+
+ 取消
+ 确定
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/superAdmin/user/user.vue b/src/view/superAdmin/user/user.vue
new file mode 100644
index 0000000..9a96400
--- /dev/null
+++ b/src/view/superAdmin/user/user.vue
@@ -0,0 +1,446 @@
+
+
+
+
+
+ 新增用户
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {changeAuthority(scope.row,flag,0)}"
+ @remove-tag="(removeAuth)=>{changeAuthority(scope.row,false,removeAuth)}"
+ />
+
+
+
+
+ {switchEnable(scope.row)}"
+ />
+
+
+
+
+
+
+ 确定要删除此用户吗
+
+ 取消
+ 确定
+
+
+ 删除
+
+
+ 编辑
+ 重置密码
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/system/state.vue b/src/view/system/state.vue
new file mode 100644
index 0000000..a7afd7c
--- /dev/null
+++ b/src/view/system/state.vue
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+ Runtime
+
+
+
+ os:
+
+
+
+ cpu nums:
+
+
+
+ compiler:
+
+
+
+ go version:
+
+
+
+ goroutine nums:
+
+
+
+
+
+
+
+
+ Disk
+
+
+
+
+
+ total (MB)
+
+
+
+ used (MB)
+
+
+
+ total (GB)
+
+
+
+ used (GB)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CPU
+
+
+
+ physical number of cores:
+
+
+
+ core {{ index }}:
+
+
+
+
+
+
+
+
+ Ram
+
+
+
+
+
+ total (MB)
+
+
+
+ used (MB)
+
+
+
+ total (GB)
+
+
+
+ used (GB)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/systemTools/autoCode/component/fieldDialog.vue b/src/view/systemTools/autoCode/component/fieldDialog.vue
new file mode 100644
index 0000000..8435bae
--- /dev/null
+++ b/src/view/systemTools/autoCode/component/fieldDialog.vue
@@ -0,0 +1,234 @@
+
+
+
+
+
+
+
+ 自动填充
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/systemTools/autoCode/component/previewCodeDialg.vue b/src/view/systemTools/autoCode/component/previewCodeDialg.vue
new file mode 100644
index 0000000..a33d3cb
--- /dev/null
+++ b/src/view/systemTools/autoCode/component/previewCodeDialg.vue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/view/systemTools/autoCode/index.vue b/src/view/systemTools/autoCode/index.vue
new file mode 100644
index 0000000..b73dbf1
--- /dev/null
+++ b/src/view/systemTools/autoCode/index.vue
@@ -0,0 +1,723 @@
+
+
+
+
+
+
+
+
+
+ 点这里从现有数据库创建代码
+
+
+
+
+
+
+
+ 业务库
+
+
+
+
+
+ {{ item.aliasName }}
+ {{ item.dbName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 使用此表创建
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 业务库
+
+
+
+
+
+ {{ item.aliasName }}
+ {{ item.dbName }}
+
+
+
+
+
+
+
+ 创建资源标识
+
+
+
+
+
+
+
+ 自动创建API
+
+
+
+
+
+
+
+ 自动移动文件
+
+
+
+
+
+
+
+
+
+ 新增Field
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 高级编辑
+ 上移
+ 下移
+
+ 确定删除吗?
+
+ 取消
+ 确定
+
+
+ 删除
+
+
+
+
+
+
+
+ 预览代码
+ 生成代码
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/systemTools/autoCodeAdmin/index.vue b/src/view/systemTools/autoCodeAdmin/index.vue
new file mode 100644
index 0000000..6895e17
--- /dev/null
+++ b/src/view/systemTools/autoCodeAdmin/index.vue
@@ -0,0 +1,188 @@
+
+
+
+
+ 新增
+
+
+
+
+
+ {{ formatDate(scope.row.CreatedAt) }}
+
+
+
+
+
+
+
+ 已回滚
+
+
+ 未回滚
+
+
+
+
+
+
+ 回滚(删表)
+ 回滚(不删表)
+ 复用
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/systemTools/autoPkg/autoPkg.vue b/src/view/systemTools/autoPkg/autoPkg.vue
new file mode 100644
index 0000000..3cb5c22
--- /dev/null
+++ b/src/view/systemTools/autoPkg/autoPkg.vue
@@ -0,0 +1,160 @@
+
+
+
+
+
+ 新增
+
+
+
+
+
+
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/systemTools/autoPlug/autoPlug.vue b/src/view/systemTools/autoPlug/autoPlug.vue
new file mode 100644
index 0000000..7f42dbe
--- /dev/null
+++ b/src/view/systemTools/autoPlug/autoPlug.vue
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 创建
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/systemTools/formCreate/index.vue b/src/view/systemTools/formCreate/index.vue
new file mode 100644
index 0000000..9e273b6
--- /dev/null
+++ b/src/view/systemTools/formCreate/index.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/view/systemTools/index.vue b/src/view/systemTools/index.vue
new file mode 100644
index 0000000..1077e8b
--- /dev/null
+++ b/src/view/systemTools/index.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/view/systemTools/installPlugin/index.vue b/src/view/systemTools/installPlugin/index.vue
new file mode 100644
index 0000000..0487bb7
--- /dev/null
+++ b/src/view/systemTools/installPlugin/index.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+ 拖拽或点击上传
+
+
+
+ 请把安装包的zip拖拽至此处上传
+
+
+
+
+
+
+
diff --git a/src/view/systemTools/system/system.vue b/src/view/systemTools/system/system.vue
new file mode 100644
index 0000000..a75f58e
--- /dev/null
+++ b/src/view/systemTools/system/system.vue
@@ -0,0 +1,463 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 开启
+
+
+ 开启
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 测试邮件
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 本地文件配置
+
+
+
+
+
+
+
+
+ qiniu上传配置
+
+
+
+
+
+
+
+
+
+
+ 开启
+
+
+
+
+
+
+
+
+ 开启
+
+
+
+ 腾讯云COS上传配置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 阿里云OSS上传配置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 华为云Obs上传配置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 立即更新
+ 重启服务(开发中)
+
+
+
+
+
+
+
+
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..5dfe9a2
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,97 @@
+import legacyPlugin from '@vitejs/plugin-legacy'
+// import usePluginImport from 'vite-plugin-importer';
+import { viteLogo } from './src/core/config'
+import Banner from 'vite-plugin-banner'
+import * as path from 'path'
+import * as dotenv from 'dotenv'
+import * as fs from 'fs'
+import vuePlugin from '@vitejs/plugin-vue'
+import GvaPosition from './vitePlugin/gvaPosition'
+import GvaPositionServer from './vitePlugin/codeServer'
+// @see https://cn.vitejs.dev/config/
+export default ({
+ command,
+ mode
+}) => {
+ const NODE_ENV = process.env.NODE_ENV || 'development'
+ const envFiles = [
+ `.env.${NODE_ENV}`
+ ]
+ for (const file of envFiles) {
+ const envConfig = dotenv.parse(fs.readFileSync(file))
+ for (const k in envConfig) {
+ process.env[k] = envConfig[k]
+ }
+ }
+
+ viteLogo(process.env)
+
+ const timestamp = Date.parse(new Date())
+
+ // const rollupOptions = {
+ // output: {
+ // entryFileNames: `gva/gin-vue-admin-[name].${timestamp}.js`,
+ // chunkFileNames: `js/gin-vue-admin-[name].${timestamp}.js`,
+ // assetFileNames: `assets/gin-vue-admin-[name].${timestamp}.[ext]`
+ // }
+ // }
+
+ const optimizeDeps = {}
+
+ const alias = {
+ '@': path.resolve(__dirname, './src'),
+ 'vue$': 'vue/dist/vue.runtime.esm-bundler.js',
+ }
+
+ const esbuild = {}
+
+ return {
+ base: './', // index.html文件所在位置
+ root: './', // js导入的资源路径,src
+ resolve: {
+ alias,
+ },
+ define: {
+ 'process.env': {}
+ },
+ server: {
+ // 如果使用docker-compose开发模式,设置为false
+ open: true,
+ port: process.env.VITE_CLI_PORT,
+ proxy: {
+ // 把key的路径代理到target位置
+ // detail: https://cli.vuejs.org/config/#devserver-proxy
+ [process.env.VITE_BASE_API]: { // 需要代理的路径 例如 '/api'
+ target: `${process.env.VITE_BASE_PATH}:${process.env.VITE_SERVER_PORT}/`, // 代理到 目标路径
+ changeOrigin: true,
+ rewrite: path => path.replace(new RegExp('^' + process.env.VITE_BASE_API), ''),
+ }
+ },
+ },
+ build: {
+ target: 'es2017',
+ minify: 'terser', // 是否进行压缩,boolean | 'terser' | 'esbuild',默认使用terser
+ manifest: false, // 是否产出manifest.json
+ sourcemap: false, // 是否产出sourcemap.json
+ outDir: 'dist', // 产出目录
+ // rollupOptions,
+ },
+ esbuild,
+ optimizeDeps,
+ plugins: [
+ GvaPositionServer(),
+ GvaPosition(),
+ legacyPlugin({
+ targets: ['Android > 39', 'Chrome >= 60', 'Safari >= 10.1', 'iOS >= 10.3', 'Firefox >= 54', 'Edge >= 15'],
+ }), vuePlugin(), [Banner(`\n Build based on gin-vue-admin \n Time : ${timestamp}`)]
+ ],
+ css: {
+ preprocessorOptions: {
+ less: {
+ // 支持内联 JavaScript
+ javascriptEnabled: true,
+ }
+ }
+ },
+ }
+}
diff --git a/vitePlugin/codeServer/index.js b/vitePlugin/codeServer/index.js
new file mode 100644
index 0000000..714a4db
--- /dev/null
+++ b/vitePlugin/codeServer/index.js
@@ -0,0 +1,59 @@
+const child_process = require('child_process')
+import * as dotenv from 'dotenv'
+import * as fs from 'fs'
+
+const NODE_ENV = process.env.NODE_ENV || 'development'
+const envFiles = [
+ `.env.${NODE_ENV}`
+]
+for (const file of envFiles) {
+ const envConfig = dotenv.parse(fs.readFileSync(file))
+ for (const k in envConfig) {
+ process.env[k] = envConfig[k]
+ }
+}
+
+export default function GvaPositionServer() {
+ return {
+ name: 'gva-position-server',
+ apply: 'serve',
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req._parsedUrl.pathname === '/gvaPositionCode') {
+ const path = req._parsedUrl.query && req._parsedUrl.query.split('=')[1]
+ if (path && path !== 'null') {
+ if (process.env.VITE_EDITOR === 'webstorm') {
+ const linePath = path.split(':')[1]
+ const filePath = path.split(':')[0]
+ const platform = os()
+ if (platform === 'win32') {
+ child_process.exec(`webstorm64.exe --line ${linePath} ${filePath}`)
+ } else {
+ child_process.exec(`webstorm64 --line ${linePath} ${filePath}`)
+ }
+ } else {
+ child_process.exec('code -r -g ' + path)
+ }
+ }
+ }
+ next()
+ })
+ }
+ }
+}
+
+function os() {
+ 'use strict'
+ const os = require('os')
+ const platform = os.platform()
+ switch (platform) {
+ case 'darwin':
+ return 'MacOSX'
+ case 'linux':
+ return 'Linux'
+ case 'win32':
+ return 'Windows'
+ default:
+ return '无法确定操作系统!'
+ }
+}
diff --git a/vitePlugin/gvaPosition/index.js b/vitePlugin/gvaPosition/index.js
new file mode 100644
index 0000000..0644c7a
--- /dev/null
+++ b/vitePlugin/gvaPosition/index.js
@@ -0,0 +1,51 @@
+export default function GvaPosition() {
+ return {
+ name: 'gva-position',
+ apply: 'serve',
+ transform(code, id) {
+ const index = id.lastIndexOf('.')
+ const ext = id.substr(index + 1)
+ if (ext.toLowerCase() === 'vue') {
+ return codeLineTrack(code, id)
+ }
+ },
+ }
+}
+
+const codeLineTrack = (code, id) => {
+ const lineList = code.split('\n')
+ const newList = []
+ lineList.forEach((item, index) => {
+ newList.push(addLineAttr(item, index + 1, id)) // 添加位置属性,index+1为具体的代码行号
+ })
+ return newList.join('\n')
+}
+
+const addLineAttr = (lineStr, line, id) => {
+ if (!/^\s+ {
+ const skip = [
+ 'KeepAlive',
+ 'template',
+ 'keep-alive',
+ 'transition',
+ 'el-',
+ 'El',
+ 'router-view',
+ ]
+ if (item && !skip.some((i) => item.indexOf(i) > -1)) {
+ const reg = new RegExp(`${item}`)
+ const location = `${item} code-location="${id}:${line}"`
+ lineStr = lineStr.replace(reg, location)
+ }
+ })
+ }
+ return lineStr
+}