Repository: Carole007/carole-admin
Branch: master
Commit: db15e9b70ac6
Files: 299
Total size: 40.0 MB
Directory structure:
gitextract_tddldwrd/
├── .gitignore
├── LICENSE
├── README.md
├── carole.sql
├── docs/
│ ├── .nojekyll
│ ├── README.md
│ ├── _coverpage.md
│ ├── _navbar.md
│ ├── _sidebar.md
│ ├── code_gen.md
│ ├── config.md
│ ├── faq.md
│ ├── guide.md
│ ├── index.html
│ └── install.md
├── front/
│ ├── LICENSE
│ ├── README.md
│ ├── bin/
│ │ ├── build.bat
│ │ ├── package.bat
│ │ └── run-web.bat
│ ├── html/
│ │ └── ie.html
│ ├── index.html
│ ├── package.json
│ ├── src/
│ │ ├── App.vue
│ │ ├── api/
│ │ │ ├── login.js
│ │ │ ├── menu.js
│ │ │ ├── monitor/
│ │ │ │ ├── cache.js
│ │ │ │ ├── logininfor.js
│ │ │ │ ├── online.js
│ │ │ │ └── server.js
│ │ │ ├── system/
│ │ │ │ ├── config.js
│ │ │ │ ├── dept.js
│ │ │ │ ├── dict/
│ │ │ │ │ ├── data.js
│ │ │ │ │ └── type.js
│ │ │ │ ├── menu.js
│ │ │ │ ├── notice.js
│ │ │ │ ├── post.js
│ │ │ │ ├── role.js
│ │ │ │ └── user.js
│ │ │ └── tool/
│ │ │ └── gen.js
│ │ ├── assets/
│ │ │ └── styles/
│ │ │ ├── btn.scss
│ │ │ ├── element-ui.scss
│ │ │ ├── index.scss
│ │ │ ├── mixin.scss
│ │ │ ├── ruoyi.scss
│ │ │ ├── sidebar.scss
│ │ │ ├── transition.scss
│ │ │ └── variables.module.scss
│ │ ├── components/
│ │ │ ├── Breadcrumb/
│ │ │ │ └── index.vue
│ │ │ ├── Crontab/
│ │ │ │ ├── day.vue
│ │ │ │ ├── hour.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── min.vue
│ │ │ │ ├── month.vue
│ │ │ │ ├── result.vue
│ │ │ │ ├── second.vue
│ │ │ │ ├── week.vue
│ │ │ │ └── year.vue
│ │ │ ├── DictTag/
│ │ │ │ └── index.vue
│ │ │ ├── Editor/
│ │ │ │ └── index.vue
│ │ │ ├── FileList/
│ │ │ │ └── index.vue
│ │ │ ├── FileUpload/
│ │ │ │ └── index.vue
│ │ │ ├── Hamburger/
│ │ │ │ └── index.vue
│ │ │ ├── HeaderSearch/
│ │ │ │ └── index.vue
│ │ │ ├── IconSelect/
│ │ │ │ ├── index.vue
│ │ │ │ └── requireIcons.js
│ │ │ ├── ImagePreview/
│ │ │ │ └── index.vue
│ │ │ ├── ImageUpload/
│ │ │ │ └── index.vue
│ │ │ ├── Pagination/
│ │ │ │ └── index.vue
│ │ │ ├── ParentView/
│ │ │ │ └── index.vue
│ │ │ ├── RightToolbar/
│ │ │ │ └── index.vue
│ │ │ ├── Screenfull/
│ │ │ │ └── index.vue
│ │ │ ├── SizeSelect/
│ │ │ │ └── index.vue
│ │ │ ├── SvgIcon/
│ │ │ │ ├── index.vue
│ │ │ │ └── svgicon.js
│ │ │ ├── TopNav/
│ │ │ │ └── index.vue
│ │ │ ├── TreeSelect/
│ │ │ │ └── index.vue
│ │ │ └── iFrame/
│ │ │ └── index.vue
│ │ ├── directive/
│ │ │ ├── common/
│ │ │ │ └── copyText.js
│ │ │ ├── index.js
│ │ │ └── permission/
│ │ │ ├── hasPermi.js
│ │ │ └── hasRole.js
│ │ ├── layout/
│ │ │ ├── components/
│ │ │ │ ├── AppMain.vue
│ │ │ │ ├── IframeToggle/
│ │ │ │ │ └── index.vue
│ │ │ │ ├── InnerLink/
│ │ │ │ │ └── index.vue
│ │ │ │ ├── Navbar.vue
│ │ │ │ ├── Settings/
│ │ │ │ │ └── index.vue
│ │ │ │ ├── Sidebar/
│ │ │ │ │ ├── Link.vue
│ │ │ │ │ ├── Logo.vue
│ │ │ │ │ ├── SidebarItem.vue
│ │ │ │ │ └── index.vue
│ │ │ │ ├── TagsView/
│ │ │ │ │ ├── ScrollPane.vue
│ │ │ │ │ └── index.vue
│ │ │ │ └── index.js
│ │ │ └── index.vue
│ │ ├── main.js
│ │ ├── permission.js
│ │ ├── plugins/
│ │ │ ├── auth.js
│ │ │ ├── cache.js
│ │ │ ├── download.js
│ │ │ ├── index.js
│ │ │ ├── modal.js
│ │ │ └── tab.js
│ │ ├── router/
│ │ │ └── index.js
│ │ ├── settings.js
│ │ ├── store/
│ │ │ ├── index.js
│ │ │ └── modules/
│ │ │ ├── app.js
│ │ │ ├── dict.js
│ │ │ ├── permission.js
│ │ │ ├── settings.js
│ │ │ ├── tagsView.js
│ │ │ └── user.js
│ │ ├── utils/
│ │ │ ├── auth.js
│ │ │ ├── dict.js
│ │ │ ├── dynamicTitle.js
│ │ │ ├── errorCode.js
│ │ │ ├── index.js
│ │ │ ├── jsencrypt.js
│ │ │ ├── permission.js
│ │ │ ├── request.js
│ │ │ ├── ruoyi.js
│ │ │ ├── scroll-to.js
│ │ │ ├── theme.js
│ │ │ └── validate.js
│ │ └── views/
│ │ ├── error/
│ │ │ ├── 401.vue
│ │ │ └── 404.vue
│ │ ├── index.vue
│ │ ├── login.vue
│ │ ├── monitor/
│ │ │ ├── cache/
│ │ │ │ ├── index.vue
│ │ │ │ └── list.vue
│ │ │ ├── logininfor/
│ │ │ │ └── index.vue
│ │ │ ├── online/
│ │ │ │ └── index.vue
│ │ │ └── server/
│ │ │ └── index.vue
│ │ ├── redirect/
│ │ │ └── index.vue
│ │ ├── system/
│ │ │ ├── config/
│ │ │ │ ├── edit.vue
│ │ │ │ └── index.vue
│ │ │ ├── dept/
│ │ │ │ └── index.vue
│ │ │ ├── dict/
│ │ │ │ ├── data.vue
│ │ │ │ └── index.vue
│ │ │ ├── menu/
│ │ │ │ └── index.vue
│ │ │ ├── notice/
│ │ │ │ └── index.vue
│ │ │ ├── post/
│ │ │ │ └── index.vue
│ │ │ ├── role/
│ │ │ │ ├── authUser.vue
│ │ │ │ ├── index.vue
│ │ │ │ └── selectUser.vue
│ │ │ └── user/
│ │ │ ├── authRole.vue
│ │ │ ├── index.vue
│ │ │ └── profile/
│ │ │ ├── index.vue
│ │ │ ├── resetPwd.vue
│ │ │ ├── userAvatar.vue
│ │ │ └── userInfo.vue
│ │ └── tool/
│ │ ├── gen/
│ │ │ ├── basicInfoForm.vue
│ │ │ ├── editTable.vue
│ │ │ ├── excuteSql.vue
│ │ │ ├── genInfoForm.vue
│ │ │ ├── importTable.vue
│ │ │ └── index.vue
│ │ └── swagger/
│ │ └── index.vue
│ ├── vite/
│ │ └── plugins/
│ │ ├── auto-import.js
│ │ ├── compression.js
│ │ ├── index.js
│ │ ├── setup-extend.js
│ │ └── svg-icon.js
│ ├── vite.config.js
│ └── vite.config.js.timestamp-1718102364365-ed912c0771327.mjs
└── server/
├── .eslintignore
├── .eslintrc.js
├── .prettierrc
├── nest-cli.json
├── package.json
├── src/
│ ├── admin/
│ │ ├── admin.module.ts
│ │ ├── common/
│ │ │ ├── captcha/
│ │ │ │ ├── captcha.controller.ts
│ │ │ │ └── vo/
│ │ │ │ └── CaptchaImageVo.ts
│ │ │ └── upload/
│ │ │ ├── config/
│ │ │ │ └── uploadConfig.ts
│ │ │ ├── dto/
│ │ │ │ └── upload.dto.ts
│ │ │ ├── upload.controller.ts
│ │ │ └── vo/
│ │ │ └── upload.ts
│ │ ├── gen/
│ │ │ ├── dto/
│ │ │ │ ├── exucteSqlDto.ts
│ │ │ │ ├── queryDatabaseDto.ts
│ │ │ │ └── queryGenTableDto.ts
│ │ │ └── gen.controller.ts
│ │ └── system/
│ │ ├── auth/
│ │ │ ├── auth.controller.ts
│ │ │ └── dto/
│ │ │ └── LoginBody.ts
│ │ ├── config/
│ │ │ ├── dto/
│ │ │ │ └── index.ts
│ │ │ ├── service/
│ │ │ │ └── sys-config.service.ts
│ │ │ └── sys-config.controller.ts
│ │ ├── dept/
│ │ │ ├── dto/
│ │ │ │ └── index.ts
│ │ │ ├── service/
│ │ │ │ └── sys-dept.service.ts
│ │ │ └── sys-dept.controller.ts
│ │ ├── dict-data/
│ │ │ ├── dict-data.controller.ts
│ │ │ ├── dto/
│ │ │ │ ├── createDictDataDto.ts
│ │ │ │ ├── queryDictDataDto.ts
│ │ │ │ └── updateDictDataDto.ts
│ │ │ └── service/
│ │ │ └── sys-dict-data.service.ts
│ │ ├── dict-type/
│ │ │ ├── dict-type.controller.ts
│ │ │ ├── dto/
│ │ │ │ ├── createDictTypeDto.ts
│ │ │ │ ├── queryDictTypeDto.ts
│ │ │ │ └── updateDictTypeDto.ts
│ │ │ └── service/
│ │ │ └── sys-dict-type.service.ts
│ │ ├── logininfor/
│ │ │ ├── dto/
│ │ │ │ └── index.ts
│ │ │ ├── service/
│ │ │ │ └── sys-logininfor.service.ts
│ │ │ └── sys-logininfor.controller.ts
│ │ ├── menu/
│ │ │ ├── dto/
│ │ │ │ ├── index.ts
│ │ │ │ └── queryMenuDto.ts
│ │ │ ├── service/
│ │ │ │ └── sys-menu.service.ts
│ │ │ └── sys-menu.controller.ts
│ │ ├── monitor/
│ │ │ └── monitor.controller.ts
│ │ ├── notice/
│ │ │ ├── dto/
│ │ │ │ └── index.ts
│ │ │ ├── service/
│ │ │ │ └── sys-notice.service.ts
│ │ │ └── sys-notice.controller.ts
│ │ ├── post/
│ │ │ ├── dto/
│ │ │ │ └── index.ts
│ │ │ ├── service/
│ │ │ │ └── sys-post.service.ts
│ │ │ └── sys-post.controller.ts
│ │ ├── role/
│ │ │ ├── dto/
│ │ │ │ └── index.ts
│ │ │ ├── service/
│ │ │ │ └── sys-role.service.ts
│ │ │ └── sys-role.controller.ts
│ │ └── user/
│ │ ├── dto/
│ │ │ └── index.ts
│ │ ├── service/
│ │ │ └── sys-user.service.ts
│ │ └── sys-user.controller.ts
│ ├── app.module.ts
│ ├── common/
│ │ ├── common.module.ts
│ │ ├── constant/
│ │ │ ├── Constants.ts
│ │ │ ├── GenConstants.ts
│ │ │ └── HttpStatus.ts
│ │ ├── decorator/
│ │ │ ├── require-premission.decorator.ts
│ │ │ ├── require-role.decorator.ts
│ │ │ └── throttle-user.ts
│ │ ├── domain/
│ │ │ ├── BaseDomain.ts
│ │ │ ├── PageDomain.ts
│ │ │ ├── TableDataInfo.ts
│ │ │ └── queryDomain.ts
│ │ ├── exception/
│ │ │ ├── AuthorizationException.ts
│ │ │ └── ValidationException.ts
│ │ ├── filter/
│ │ │ └── global-error.filter.ts
│ │ ├── guard/
│ │ │ ├── permission/
│ │ │ │ ├── permission.guard.ts
│ │ │ │ └── role.guard.ts
│ │ │ └── throttler/
│ │ │ └── throttler-custom.guard.ts
│ │ ├── interceptors/
│ │ │ └── remove-throttle-headers.interceptor.ts
│ │ ├── middleware/
│ │ │ └── auth/
│ │ │ └── auth.middleware.ts
│ │ ├── pipe/
│ │ │ ├── parse-int-array.pipe.ts
│ │ │ └── validation.pipe.ts
│ │ ├── prisma-client/
│ │ │ ├── default.d.ts
│ │ │ ├── default.js
│ │ │ ├── edge.d.ts
│ │ │ ├── edge.js
│ │ │ ├── index-browser.js
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ ├── libquery_engine-darwin.dylib.node
│ │ │ ├── package.json
│ │ │ ├── query_engine-windows.dll.node
│ │ │ ├── runtime/
│ │ │ │ ├── edge-esm.js
│ │ │ │ ├── edge.js
│ │ │ │ ├── index-browser.d.ts
│ │ │ │ ├── index-browser.js
│ │ │ │ ├── library.d.ts
│ │ │ │ ├── library.js
│ │ │ │ ├── react-native.js
│ │ │ │ └── wasm.js
│ │ │ ├── schema.prisma
│ │ │ ├── wasm.d.ts
│ │ │ └── wasm.js
│ │ ├── result/
│ │ │ └── Result.ts
│ │ ├── service/
│ │ │ ├── auth/
│ │ │ │ └── auth.service.ts
│ │ │ ├── gen/
│ │ │ │ ├── gen-template/
│ │ │ │ │ ├── js/
│ │ │ │ │ │ └── api.js.vm
│ │ │ │ │ ├── node/
│ │ │ │ │ │ ├── controller.ts.vm
│ │ │ │ │ │ ├── dto.ts.vm
│ │ │ │ │ │ └── service.ts.vm
│ │ │ │ │ ├── sql/
│ │ │ │ │ │ └── sql.vm
│ │ │ │ │ └── vue/
│ │ │ │ │ └── index.vue.vm
│ │ │ │ └── gen.service.ts
│ │ │ └── prisma/
│ │ │ └── prisma.service.ts
│ │ ├── swagger/
│ │ │ └── vo/
│ │ │ └── index.ts
│ │ ├── types/
│ │ │ └── gen.d.ts
│ │ └── utils/
│ │ ├── Valids.ts
│ │ ├── cache.ts
│ │ ├── captcha.ts
│ │ ├── email.ts
│ │ ├── index.ts
│ │ ├── prismaUtil.js
│ │ ├── redisUtils.ts
│ │ └── systemInfo.ts
│ ├── config-development.json
│ ├── config-production.json
│ ├── config.ts
│ ├── main.ts
│ ├── prisma/
│ │ ├── schema/
│ │ │ ├── gen.prisma
│ │ │ └── system.prisma
│ │ └── schema.prisma
│ └── schedule/
│ └── index.ts
├── test/
│ ├── app.e2e-spec.ts
│ ├── jest-e2e.json
│ └── password.js
├── tsconfig.build.json
├── tsconfig.json
├── 更新prisma的model.bat
├── 更新prisma的model.sh
├── 驼峰生成prisma的model.bat
└── 驼峰生成prisma的model.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.DS_Store
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# idea
.idea
.vscode
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2024 Carole
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
Carole-Admin
一款基于 NestJS + Vue 前后端分离的后台框架
---
## 🌟 平台简介
**Carole-Admin** 是一款基于 [NestJS](https://nestjs.com/) + [Prisma](https://www.prisma.io/) + [Vue](https://vuejs.org/) + [Vite](https://vitejs.dev/) 的前后端分离全栈快速开发平台,前端参考 [若依](https://github.com/yangzongzhuan/RuoYi-Vue3) 实现。
- 前端: [Vue3](https://vuejs.org/)、[Element Plus](https://element-plus.org/)、[Vite](https://vitejs.dev/)
- 后端: [NestJS](https://nestjs.com/)、[Prisma](https://www.prisma.io/)、[ioredis](https://github.com/redis/ioredis)、[JWT](https://github.com/auth0/node-jsonwebtoken)
- 权限认证:基于 JWT,支持多终端认证
- 动态权限菜单:多方式权限控制,灵活高效
- 支持接口限流
- 提供代码生成器,一键生成前后端代码,加速开发效率
---
## 📚 项目文档
👉 本项目详细文档请访问:
🌐 [在线文档](https://carole007.github.io/carole-admin/)
📂 [README.md](./docs/README.md)
================================================
FILE: carole.sql
================================================
/*
Navicat Premium Dump SQL
Source Server : mysql8
Source Server Type : MySQL
Source Server Version : 80404 (8.4.4)
Source Host : localhost:3306
Source Schema : carole
Target Server Type : MySQL
Target Server Version : 80404 (8.4.4)
File Encoding : 65001
Date: 04/07/2025 17:07:50
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for gen_table
-- ----------------------------
DROP TABLE IF EXISTS `gen_table`;
CREATE TABLE `gen_table` (
`table_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '编号',
`table_name` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '表名称',
`table_comment` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '表描述',
`sub_table_name` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '关联子表的表名',
`sub_table_fk_name` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '子表关联的外键名',
`class_name` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '实体类名称',
`tpl_category` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT 'crud' COMMENT '使用的模板(crud单表操作 tree树表操作)',
`tpl_web_type` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '前端模板类型(element-ui模版 element-plus模版)',
`package_name` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '生成包路径',
`module_name` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '生成模块名',
`business_name` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '生成业务名',
`function_name` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '生成功能名',
`function_author` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '生成功能作者',
`gen_type` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '0' COMMENT '生成代码方式(0zip压缩包 1自定义路径)',
`gen_path` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '/' COMMENT '生成路径(不填默认项目路径)',
`options` varchar(1000) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '其它生成选项',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`table_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=117 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='代码生成业务表';
-- ----------------------------
-- Records of gen_table
-- ----------------------------
BEGIN;
INSERT INTO `gen_table` (`table_id`, `table_name`, `table_comment`, `sub_table_name`, `sub_table_fk_name`, `class_name`, `tpl_category`, `tpl_web_type`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `gen_type`, `gen_path`, `options`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (107, 'sys_logininfor', '系统访问记录', NULL, NULL, 'SysLogininfor', 'crud', 'element-plus', 'admin', 'system', 'logininfor', '系统访问记录', 'carole', '0', '/', NULL, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16', NULL);
INSERT INTO `gen_table` (`table_id`, `table_name`, `table_comment`, `sub_table_name`, `sub_table_fk_name`, `class_name`, `tpl_category`, `tpl_web_type`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `gen_type`, `gen_path`, `options`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (108, 'sys_menu', '菜单权限表', NULL, NULL, 'SysMenu', 'crud', 'element-plus', 'admin', 'system', 'menu', '菜单权限表', 'carole', '0', '/', NULL, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16', NULL);
INSERT INTO `gen_table` (`table_id`, `table_name`, `table_comment`, `sub_table_name`, `sub_table_fk_name`, `class_name`, `tpl_category`, `tpl_web_type`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `gen_type`, `gen_path`, `options`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (109, 'sys_notice', '通知公告表', NULL, NULL, 'SysNotice', 'crud', 'element-plus', 'admin', 'system', 'notice', '通知公告表', 'carole', '0', '/', NULL, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16', NULL);
INSERT INTO `gen_table` (`table_id`, `table_name`, `table_comment`, `sub_table_name`, `sub_table_fk_name`, `class_name`, `tpl_category`, `tpl_web_type`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `gen_type`, `gen_path`, `options`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (110, 'sys_post', '岗位信息表', NULL, NULL, 'SysPost', 'crud', 'element-plus', 'admin', 'system', 'post', '岗位信息表', 'carole', '0', '/', NULL, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16', NULL);
INSERT INTO `gen_table` (`table_id`, `table_name`, `table_comment`, `sub_table_name`, `sub_table_fk_name`, `class_name`, `tpl_category`, `tpl_web_type`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `gen_type`, `gen_path`, `options`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (111, 'sys_role', '角色信息表', NULL, NULL, 'SysRole', 'crud', 'element-plus', 'admin', 'system', 'role', '角色信息表', 'carole', '0', '/', NULL, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16', NULL);
INSERT INTO `gen_table` (`table_id`, `table_name`, `table_comment`, `sub_table_name`, `sub_table_fk_name`, `class_name`, `tpl_category`, `tpl_web_type`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `gen_type`, `gen_path`, `options`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (112, 'sys_user', '用户信息表', NULL, NULL, 'SysUser', 'crud', 'element-plus', 'admin', 'system', 'user', '用户信息表', 'carole', '0', '/', NULL, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16', NULL);
INSERT INTO `gen_table` (`table_id`, `table_name`, `table_comment`, `sub_table_name`, `sub_table_fk_name`, `class_name`, `tpl_category`, `tpl_web_type`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `gen_type`, `gen_path`, `options`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (113, 'sys_config', '参数配置表', NULL, NULL, 'SysConfig', 'crud', 'element-plus', 'admin', 'system', 'config', '参数配置表', 'carole', '0', '/', NULL, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26', NULL);
INSERT INTO `gen_table` (`table_id`, `table_name`, `table_comment`, `sub_table_name`, `sub_table_fk_name`, `class_name`, `tpl_category`, `tpl_web_type`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `gen_type`, `gen_path`, `options`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (114, 'sys_dept', '部门表', NULL, NULL, 'SysDept', 'crud', 'element-plus', 'admin', 'system', 'dept', '部门表', 'carole', '0', '/', NULL, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26', NULL);
INSERT INTO `gen_table` (`table_id`, `table_name`, `table_comment`, `sub_table_name`, `sub_table_fk_name`, `class_name`, `tpl_category`, `tpl_web_type`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `gen_type`, `gen_path`, `options`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (115, 'sys_dict_data', '字典数据表', NULL, NULL, 'SysDictData', 'crud', 'element-plus', 'admin', 'system', 'data', '字典数据表', 'carole', '0', '/', NULL, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26', NULL);
INSERT INTO `gen_table` (`table_id`, `table_name`, `table_comment`, `sub_table_name`, `sub_table_fk_name`, `class_name`, `tpl_category`, `tpl_web_type`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `gen_type`, `gen_path`, `options`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (116, 'sys_dict_type', '字典类型表', NULL, NULL, 'SysDictType', 'crud', 'element-plus', 'admin', 'system', 'type', '字典类型表', 'carole', '0', '/', NULL, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26', NULL);
COMMIT;
-- ----------------------------
-- Table structure for gen_table_column
-- ----------------------------
DROP TABLE IF EXISTS `gen_table_column`;
CREATE TABLE `gen_table_column` (
`column_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '编号',
`table_id` int unsigned DEFAULT NULL COMMENT '归属表编号',
`column_name` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '列名称',
`column_comment` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '列描述',
`column_type` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '列类型',
`java_type` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 'JAVA类型',
`java_field` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 'JAVA字段名',
`is_pk` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '是否主键(1是)',
`is_increment` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '是否自增(1是)',
`is_required` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '是否必填(1是)',
`is_insert` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '是否为插入字段(1是)',
`is_edit` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '是否编辑字段(1是)',
`is_list` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '是否列表字段(1是)',
`is_query` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '是否查询字段(1是)',
`query_type` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT 'EQ' COMMENT '查询方式(等于、不等于、大于、小于、范围)',
`html_type` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)',
`dict_type` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '字典类型',
`sort` int DEFAULT NULL COMMENT '排序',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`column_id`) USING BTREE,
KEY `gen_table_column_table_id_idx` (`table_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1300 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='代码生成业务表字段';
-- ----------------------------
-- Records of gen_table_column
-- ----------------------------
BEGIN;
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1175, 107, 'info_id', '访问ID', 'int(10) unsigned', 'Number', 'infoId', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1176, 107, 'user_name', '用户账号', 'varchar(50)', 'String', 'userName', '0', '0', '0', '1', '1', '1', '1', 'LIKE', 'input', '', 2, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1177, 107, 'ipaddr', '登录IP地址', 'varchar(128)', 'String', 'ipaddr', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1178, 107, 'login_location', '登录地点', 'varchar(255)', 'String', 'loginLocation', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 4, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1179, 107, 'browser', '浏览器类型', 'varchar(50)', 'String', 'browser', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 5, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1180, 107, 'os', '操作系统', 'varchar(50)', 'String', 'os', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 6, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1181, 107, 'status', '登录状态(0失败,1成功)', 'char(1)', 'String', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 7, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1182, 107, 'msg', '提示消息', 'varchar(255)', 'String', 'msg', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 8, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1183, 107, 'login_time', '访问时间', 'varchar(25)', 'String', 'loginTime', '0', '0', '0', '1', '1', '1', '1', 'BETWEEN', 'datetime', '', 9, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1184, 108, 'menu_id', '菜单ID', 'int(10) unsigned', 'Number', 'menuId', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1185, 108, 'menu_name', '菜单名称', 'varchar(50)', 'String', 'menuName', '0', '0', '1', '1', '1', '1', '1', 'LIKE', 'input', '', 2, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1186, 108, 'parent_id', '父菜单ID', 'int(10) unsigned', 'Number', 'parentId', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 3, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1187, 108, 'order_num', '显示顺序', 'int(11)', 'Number', 'orderNum', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 4, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1188, 108, 'path', '路由地址', 'varchar(200)', 'String', 'path', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 5, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1189, 108, 'component', '组件路径', 'varchar(255)', 'String', 'component', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 6, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1190, 108, 'query', '路由参数', 'varchar(255)', 'String', 'query', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 7, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1191, 108, 'is_frame', '是否为外链(0否 1是)', 'int(11)', 'Number', 'isFrame', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 8, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1192, 108, 'is_cache', '是否缓存(0不缓存 1缓存)', 'int(11)', 'Number', 'isCache', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 9, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1193, 108, 'menu_type', '菜单类型(M目录 C菜单 F按钮)', 'char(1)', 'String', 'menuType', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'select', '', 10, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1194, 108, 'visible', '菜单状态(0隐藏 1显示)', 'char(1)', 'String', 'visible', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 11, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1195, 108, 'status', '菜单状态(0停用 1正常)', 'char(1)', 'String', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 12, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1196, 108, 'perms', '权限标识', 'varchar(100)', 'String', 'perms', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 13, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1197, 108, 'icon', '菜单图标', 'varchar(100)', 'String', 'icon', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 14, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1198, 108, 'create_by', '创建者', 'varchar(64)', 'String', 'createBy', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 15, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1199, 108, 'create_time', '创建时间', 'varchar(25)', 'String', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'BETWEEN', 'datetime', '', 16, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1200, 108, 'update_by', '更新者', 'varchar(64)', 'String', 'updateBy', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 17, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1201, 108, 'update_time', '更新时间', 'varchar(25)', 'String', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'BETWEEN', 'datetime', '', 18, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1202, 108, 'remark', '备注', 'varchar(500)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'textarea', '', 19, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1203, 109, 'notice_id', '公告ID', 'int(11)', 'Number', 'noticeId', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1204, 109, 'notice_title', '公告标题', 'varchar(50)', 'String', 'noticeTitle', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1205, 109, 'notice_type', '公告类型(1通知 2公告)', 'char(1)', 'String', 'noticeType', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'select', '', 3, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1206, 109, 'notice_content', '公告内容', 'mediumtext', 'String', 'noticeContent', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'editor', '', 4, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1207, 109, 'status', '公告状态(0关闭 1正常)', 'char(1)', 'String', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 5, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1208, 109, 'create_by', '创建者', 'varchar(64)', 'String', 'createBy', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 6, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1209, 109, 'create_time', '创建时间', 'varchar(25)', 'String', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'BETWEEN', 'datetime', '', 7, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1210, 109, 'update_by', '更新者', 'varchar(64)', 'String', 'updateBy', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 8, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1211, 109, 'update_time', '更新时间', 'varchar(25)', 'String', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'BETWEEN', 'datetime', '', 9, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1212, 109, 'remark', '备注', 'varchar(255)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'input', '', 10, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1213, 110, 'post_id', '岗位ID', 'int(10) unsigned', 'Number', 'postId', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1214, 110, 'post_code', '岗位编码', 'varchar(64)', 'String', 'postCode', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1215, 110, 'post_name', '岗位名称', 'varchar(50)', 'String', 'postName', '0', '0', '1', '1', '1', '1', '1', 'LIKE', 'input', '', 3, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1216, 110, 'post_sort', '显示顺序', 'int(11)', 'Number', 'postSort', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 4, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1217, 110, 'status', '状态(0停用 1正常)', 'char(1)', 'String', 'status', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'radio', '', 5, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1218, 110, 'create_by', '创建者', 'varchar(64)', 'String', 'createBy', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 6, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1219, 110, 'create_time', '创建时间', 'varchar(25)', 'String', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'BETWEEN', 'datetime', '', 7, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1220, 110, 'update_by', '更新者', 'varchar(64)', 'String', 'updateBy', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 8, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1221, 110, 'update_time', '更新时间', 'varchar(25)', 'String', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'BETWEEN', 'datetime', '', 9, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1222, 110, 'remark', '备注', 'varchar(500)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'textarea', '', 10, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1223, 111, 'role_id', '角色ID', 'int(10) unsigned', 'Number', 'roleId', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1224, 111, 'role_name', '角色名称', 'varchar(30)', 'String', 'roleName', '0', '0', '1', '1', '1', '1', '1', 'LIKE', 'input', '', 2, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1225, 111, 'role_key', '角色权限字符串', 'varchar(100)', 'String', 'roleKey', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 3, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1226, 111, 'role_sort', '显示顺序', 'int(11)', 'Number', 'roleSort', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 4, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1227, 111, 'data_scope', '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅个人权限)', 'char(1)', 'String', 'dataScope', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 5, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1228, 111, 'menu_check_strictly', '菜单树选择项是否关联显示', 'tinyint(11)', 'Number', 'menuCheckStrictly', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 6, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1229, 111, 'dept_check_strictly', '部门树选择项是否关联显示', 'tinyint(11)', 'Number', 'deptCheckStrictly', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 7, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1230, 111, 'status', '角色状态(0停用 1正常)', 'char(1)', 'String', 'status', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'radio', '', 8, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1231, 111, 'create_by', '创建者', 'varchar(64)', 'String', 'createBy', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 9, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1232, 111, 'create_time', '创建时间', 'varchar(25)', 'String', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'BETWEEN', 'datetime', '', 10, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1233, 111, 'update_by', '更新者', 'varchar(64)', 'String', 'updateBy', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 11, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1234, 111, 'update_time', '更新时间', 'varchar(25)', 'String', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'BETWEEN', 'datetime', '', 12, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1235, 111, 'remark', '备注', 'varchar(500)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'textarea', '', 13, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1236, 112, 'user_id', '用户ID', 'int(10) unsigned', 'Number', 'userId', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1237, 112, 'dept_id', '部门ID', 'int(10) unsigned', 'Number', 'deptId', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 2, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1238, 112, 'user_name', '用户账号', 'varchar(30)', 'String', 'userName', '0', '0', '1', '1', '1', '1', '1', 'LIKE', 'input', '', 3, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1239, 112, 'nick_name', '用户昵称', 'varchar(30)', 'String', 'nickName', '0', '0', '1', '1', '1', '1', '1', 'LIKE', 'input', '', 4, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1240, 112, 'user_type', '用户类型(00系统用户)', 'varchar(2)', 'String', 'userType', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'select', '', 5, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1241, 112, 'email', '用户邮箱', 'varchar(50)', 'String', 'email', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 6, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1242, 112, 'phonenumber', '手机号码', 'varchar(11)', 'String', 'phonenumber', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 7, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1243, 112, 'sex', '用户性别(0男 1女 2未知)', 'char(1)', 'String', 'sex', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'select', '', 8, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1244, 112, 'avatar', '头像地址', 'varchar(100)', 'String', 'avatar', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 9, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1245, 112, 'password', '密码', 'varchar(100)', 'String', 'password', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 10, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1246, 112, 'status', '帐号状态(0停用,1正常 )', 'char(1)', 'String', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 11, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1247, 112, 'login_ip', '最后登录IP', 'varchar(128)', 'String', 'loginIp', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 12, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1248, 112, 'login_date', '最后登录时间', 'varchar(25)', 'String', 'loginDate', '0', '0', '0', '1', '1', '1', '1', 'BETWEEN', 'datetime', '', 13, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1249, 112, 'create_by', '创建者', 'varchar(64)', 'String', 'createBy', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 14, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1250, 112, 'create_time', '创建时间', 'varchar(25)', 'String', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'BETWEEN', 'datetime', '', 15, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1251, 112, 'update_by', '更新者', 'varchar(64)', 'String', 'updateBy', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 16, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1252, 112, 'update_time', '更新时间', 'varchar(25)', 'String', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'BETWEEN', 'datetime', '', 17, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1253, 112, 'remark', '备注', 'varchar(500)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'textarea', '', 18, 'admin', '2024-06-16 14:05:16', 'admin', '2024-06-16 14:05:16');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1254, 113, 'config_id', '参数主键', 'int(11)', 'Number', 'configId', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1255, 113, 'config_name', '参数名称', 'varchar(100)', 'String', 'configName', '0', '0', '0', '1', '1', '1', '1', 'LIKE', 'input', '', 2, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1256, 113, 'config_key', '参数键名', 'varchar(100)', 'String', 'configKey', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1257, 113, 'config_value', '参数键值', 'varchar(500)', 'String', 'configValue', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'textarea', '', 4, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1258, 113, 'config_type', '系统内置(Y是 N否)', 'char(1)', 'String', 'configType', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'select', '', 5, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1259, 113, 'create_by', '创建者', 'varchar(64)', 'String', 'createBy', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 6, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1260, 113, 'create_time', '创建时间', 'varchar(25)', 'String', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'BETWEEN', 'datetime', '', 7, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1261, 113, 'update_by', '更新者', 'varchar(64)', 'String', 'updateBy', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 8, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1262, 113, 'update_time', '更新时间', 'varchar(25)', 'String', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'BETWEEN', 'datetime', '', 9, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1263, 113, 'remark', '备注', 'varchar(500)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'textarea', '', 10, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1264, 114, 'dept_id', '部门id', 'int(10) unsigned', 'Number', 'deptId', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1265, 114, 'parent_id', '父部门id', 'int(10) unsigned', 'Number', 'parentId', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 2, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1266, 114, 'ancestors', '祖级列表', 'varchar(50)', 'String', 'ancestors', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1267, 114, 'dept_name', '部门名称', 'varchar(30)', 'String', 'deptName', '0', '0', '0', '1', '1', '1', '1', 'LIKE', 'input', '', 4, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1268, 114, 'order_num', '显示顺序', 'int(11)', 'Number', 'orderNum', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 5, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1269, 114, 'leader', '负责人', 'varchar(20)', 'String', 'leader', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 6, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1270, 114, 'phone', '联系电话', 'varchar(11)', 'String', 'phone', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 7, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1271, 114, 'email', '邮箱', 'varchar(50)', 'String', 'email', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 8, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1272, 114, 'status', '部门状态(0停用,1正常)', 'char(1)', 'String', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 9, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1273, 114, 'create_by', '创建者', 'varchar(64)', 'String', 'createBy', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 10, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1274, 114, 'create_time', '创建时间', 'varchar(25)', 'String', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'BETWEEN', 'datetime', '', 11, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1275, 114, 'update_by', '更新者', 'varchar(64)', 'String', 'updateBy', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 12, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1276, 114, 'update_time', '更新时间', 'varchar(25)', 'String', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'BETWEEN', 'datetime', '', 13, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1277, 115, 'dict_code', '字典编码', 'int(10) unsigned', 'Number', 'dictCode', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1278, 115, 'dict_sort', '字典排序', 'int(11)', 'Number', 'dictSort', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 2, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1279, 115, 'dict_label', '字典标签', 'varchar(100)', 'String', 'dictLabel', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1280, 115, 'dict_value', '字典键值', 'varchar(100)', 'String', 'dictValue', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 4, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1281, 115, 'dict_type', '字典类型', 'varchar(100)', 'String', 'dictType', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'select', '', 5, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1282, 115, 'css_class', '样式属性(其他样式扩展)', 'varchar(100)', 'String', 'cssClass', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 6, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1283, 115, 'list_class', '表格回显样式', 'varchar(100)', 'String', 'listClass', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 7, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1284, 115, 'is_default', '是否默认(Y是 N否)', 'char(1)', 'String', 'isDefault', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 8, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1285, 115, 'status', '状态(0停用 1正常)', 'char(1)', 'String', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 9, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1286, 115, 'create_by', '创建者', 'varchar(64)', 'String', 'createBy', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 10, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1287, 115, 'create_time', '创建时间', 'varchar(25)', 'String', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'BETWEEN', 'datetime', '', 11, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1288, 115, 'update_by', '更新者', 'varchar(64)', 'String', 'updateBy', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 12, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1289, 115, 'update_time', '更新时间', 'varchar(25)', 'String', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'BETWEEN', 'datetime', '', 13, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1290, 115, 'remark', '备注', 'varchar(500)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'textarea', '', 14, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1291, 116, 'dict_id', '字典主键', 'int(10) unsigned', 'Number', 'dictId', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1292, 116, 'dict_name', '字典名称', 'varchar(100)', 'String', 'dictName', '0', '0', '0', '1', '1', '1', '1', 'LIKE', 'input', '', 2, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1293, 116, 'dict_type', '字典类型', 'varchar(100)', 'String', 'dictType', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'select', '', 3, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1294, 116, 'status', '状态(0停用,1正常)', 'char(1)', 'String', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 4, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1295, 116, 'create_by', '创建者', 'varchar(64)', 'String', 'createBy', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 5, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1296, 116, 'create_time', '创建时间', 'varchar(25)', 'String', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'BETWEEN', 'datetime', '', 6, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1297, 116, 'update_by', '更新者', 'varchar(64)', 'String', 'updateBy', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 7, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1298, 116, 'update_time', '更新时间', 'varchar(25)', 'String', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'BETWEEN', 'datetime', '', 8, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
INSERT INTO `gen_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `java_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `query_type`, `html_type`, `dict_type`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (1299, 116, 'remark', '备注', 'varchar(500)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'textarea', '', 9, 'admin', '2024-06-16 14:05:26', 'admin', '2024-06-16 14:05:26');
COMMIT;
-- ----------------------------
-- Table structure for sys_config
-- ----------------------------
DROP TABLE IF EXISTS `sys_config`;
CREATE TABLE `sys_config` (
`config_id` int NOT NULL AUTO_INCREMENT COMMENT '参数主键',
`config_name` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '参数名称',
`config_key` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '参数键名',
`config_value` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '参数键值',
`config_type` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT 'N' COMMENT '系统内置(Y是 N否)',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`config_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='参数配置表';
-- ----------------------------
-- Records of sys_config
-- ----------------------------
BEGIN;
INSERT INTO `sys_config` (`config_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', '2023-12-18 14:59:08', '', NULL, '初始化密码 123456');
INSERT INTO `sys_config` (`config_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (4, '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', '2023-12-18 14:59:08', 'admin', '2024-06-06 20:03:46', '是否开启验证码功能(true开启,false关闭)');
INSERT INTO `sys_config` (`config_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (6, '用户登录-黑名单列表', 'sys.login.blackIPList', '1.1.1.1', 'Y', 'admin', '2023-12-18 14:59:08', 'admin', '2024-06-05 20:24:10', '设置登录IP黑名单限制,多个匹配项以;分隔,支持匹配(*通配、网段)');
COMMIT;
-- ----------------------------
-- Table structure for sys_dept
-- ----------------------------
DROP TABLE IF EXISTS `sys_dept`;
CREATE TABLE `sys_dept` (
`dept_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '部门id',
`parent_id` int unsigned DEFAULT '0' COMMENT '父部门id',
`ancestors` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '祖级列表',
`dept_name` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '部门名称',
`order_num` int DEFAULT '0' COMMENT '显示顺序',
`leader` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '负责人',
`phone` varchar(11) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '联系电话',
`email` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '邮箱',
`status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '1' COMMENT '部门状态(0停用,1正常)',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`dept_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=205 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='部门表';
-- ----------------------------
-- Records of sys_dept
-- ----------------------------
BEGIN;
INSERT INTO `sys_dept` (`dept_id`, `parent_id`, `ancestors`, `dept_name`, `order_num`, `leader`, `phone`, `email`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (100, 0, '0', '全国总部', 0, 'carole', '15888888888', 'admin@carole.top', '1', 'admin', '2023-12-18 14:59:00', 'admin', '2023-12-19 11:51:14');
INSERT INTO `sys_dept` (`dept_id`, `parent_id`, `ancestors`, `dept_name`, `order_num`, `leader`, `phone`, `email`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (101, 100, '0,100', '深圳总公司', 1, 'carole', '15888888888', 'admin@carole.top', '1', 'admin', '2023-12-18 14:59:00', 'admin', '2023-12-19 11:51:25');
INSERT INTO `sys_dept` (`dept_id`, `parent_id`, `ancestors`, `dept_name`, `order_num`, `leader`, `phone`, `email`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (103, 101, '0,100,101', '研发部门', 1, 'carole', '15888888888', 'admin@carole.top', '1', 'admin', '2023-12-18 14:59:00', '', NULL);
INSERT INTO `sys_dept` (`dept_id`, `parent_id`, `ancestors`, `dept_name`, `order_num`, `leader`, `phone`, `email`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (104, 101, '0,100,101', '市场部门', 2, 'carole', '15888888888', 'admin@carole.top', '1', 'admin', '2023-12-18 14:59:00', '', NULL);
INSERT INTO `sys_dept` (`dept_id`, `parent_id`, `ancestors`, `dept_name`, `order_num`, `leader`, `phone`, `email`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (105, 101, '0,100,101', '测试部门', 3, 'carole', '15888888888', 'admin@carole.top', '1', 'admin', '2023-12-18 14:59:00', '', NULL);
INSERT INTO `sys_dept` (`dept_id`, `parent_id`, `ancestors`, `dept_name`, `order_num`, `leader`, `phone`, `email`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES (106, 101, '0,100,101', '财务部门', 2, 'carole', '15888888888', 'admin@carole.top', '1', 'admin', '2023-12-18 14:59:00', 'admin', '2024-06-10 12:39:55');
COMMIT;
-- ----------------------------
-- Table structure for sys_dict_data
-- ----------------------------
DROP TABLE IF EXISTS `sys_dict_data`;
CREATE TABLE `sys_dict_data` (
`dict_code` int unsigned NOT NULL AUTO_INCREMENT COMMENT '字典编码',
`dict_sort` int DEFAULT '0' COMMENT '字典排序',
`dict_label` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '字典标签',
`dict_value` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '字典键值',
`dict_type` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '字典类型',
`css_class` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '样式属性(其他样式扩展)',
`list_class` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '表格回显样式',
`is_default` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT 'N' COMMENT '是否默认(Y是 N否)',
`status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '1' COMMENT '状态(0停用 1正常)',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`dict_code`) USING BTREE,
KEY `sys_dict_data_dict_type_idx` (`dict_type`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=124 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='字典数据表';
-- ----------------------------
-- Records of sys_dict_data
-- ----------------------------
BEGIN;
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1, 1, '男', '0', 'sys_user_sex', '', '', 'Y', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '性别男');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2, 2, '女', '1', 'sys_user_sex', '', '', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '性别女');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (3, 3, '未知', '2', 'sys_user_sex', '', '', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '性别未知');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (4, 1, '显示', '1', 'sys_show_hide', '', 'primary', 'Y', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '显示菜单');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (5, 2, '隐藏', '0', 'sys_show_hide', '', 'danger', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '隐藏菜单');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (6, 1, '正常', '1', 'sys_normal_disable', '', 'primary', 'Y', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '正常状态');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (7, 2, '停用', '0', 'sys_normal_disable', '', 'danger', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '停用状态');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (8, 1, '正常', '1', 'sys_job_status', '', 'primary', 'Y', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '正常状态');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (9, 2, '暂停', '0', 'sys_job_status', '', 'danger', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '停用状态');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (10, 1, '默认', 'DEFAULT', 'sys_job_group', '', '', 'Y', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '默认分组');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (11, 2, '系统', 'SYSTEM', 'sys_job_group', '', '', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '系统分组');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (12, 1, '是', 'Y', 'sys_yes_no', '', 'primary', 'Y', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '系统默认是');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (13, 2, '否', 'N', 'sys_yes_no', '', 'danger', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '系统默认否');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (14, 1, '通知', '1', 'sys_notice_type', '', 'warning', 'Y', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '通知');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (15, 2, '公告', '2', 'sys_notice_type', '', 'success', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '公告');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (16, 1, '正常', '1', 'sys_notice_status', '', 'primary', 'Y', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '正常状态');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (17, 2, '关闭', '0', 'sys_notice_status', '', 'danger', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '关闭状态');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (18, 99, '其他', '0', 'sys_oper_type', '', 'info', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '其他操作');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (19, 1, '新增', '1', 'sys_oper_type', '', 'info', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '新增操作');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (20, 2, '修改', '2', 'sys_oper_type', '', 'info', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '修改操作');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (21, 3, '删除', '3', 'sys_oper_type', '', 'danger', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '删除操作');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (22, 4, '授权', '4', 'sys_oper_type', '', 'primary', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '授权操作');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (23, 5, '导出', '5', 'sys_oper_type', '', 'warning', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '导出操作');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (24, 6, '导入', '6', 'sys_oper_type', '', 'warning', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '导入操作');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (25, 7, '强退', '7', 'sys_oper_type', '', 'danger', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '强退操作');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (26, 8, '生成代码', '8', 'sys_oper_type', '', 'warning', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '生成操作');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (27, 9, '清空数据', '9', 'sys_oper_type', '', 'danger', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '清空操作');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (28, 1, '成功', '1', 'sys_common_status', '', 'primary', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '正常状态');
INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (29, 2, '失败', '0', 'sys_common_status', '', 'danger', 'N', '1', 'admin', '2023-12-18 14:59:07', '', NULL, '停用状态');
COMMIT;
-- ----------------------------
-- Table structure for sys_dict_type
-- ----------------------------
DROP TABLE IF EXISTS `sys_dict_type`;
CREATE TABLE `sys_dict_type` (
`dict_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '字典主键',
`dict_name` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '字典名称',
`dict_type` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '字典类型',
`status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '1' COMMENT '状态(0停用,1正常)',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`dict_id`) USING BTREE,
UNIQUE KEY `dict_type` (`dict_type`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=118 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='字典类型表';
-- ----------------------------
-- Records of sys_dict_type
-- ----------------------------
BEGIN;
INSERT INTO `sys_dict_type` (`dict_id`, `dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1, '用户性别', 'sys_user_sex', '1', 'admin', '2023-12-18 14:59:07', 'admin', '2024-01-16 00:00:00', '用户性别列表');
INSERT INTO `sys_dict_type` (`dict_id`, `dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2, '菜单状态', 'sys_show_hide', '1', 'admin', '2023-12-18 14:59:07', 'admin', '2024-01-16 00:00:00', '菜单状态列表');
INSERT INTO `sys_dict_type` (`dict_id`, `dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (3, '系统开关', 'sys_normal_disable', '1', 'admin', '2023-12-18 14:59:07', 'admin', '2024-01-16 00:00:00', '系统开关列表');
INSERT INTO `sys_dict_type` (`dict_id`, `dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (4, '任务状态', 'sys_job_status', '1', 'admin', '2023-12-18 14:59:07', 'admin', '2024-01-16 00:00:00', '任务状态列表');
INSERT INTO `sys_dict_type` (`dict_id`, `dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (5, '任务分组', 'sys_job_group', '1', 'admin', '2023-12-18 14:59:07', 'admin', '2024-01-16 00:00:00', '任务分组列表');
INSERT INTO `sys_dict_type` (`dict_id`, `dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (6, '系统是否', 'sys_yes_no', '1', 'admin', '2023-12-18 14:59:07', 'admin', '2024-01-16 00:00:00', '系统是否列表');
INSERT INTO `sys_dict_type` (`dict_id`, `dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (7, '通知类型', 'sys_notice_type', '1', 'admin', '2023-12-18 14:59:07', 'admin', '2024-01-16 00:00:00', '通知类型列表');
INSERT INTO `sys_dict_type` (`dict_id`, `dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (8, '通知状态', 'sys_notice_status', '1', 'admin', '2023-12-18 14:59:07', 'admin', '2024-01-16 00:00:00', '通知状态列表');
INSERT INTO `sys_dict_type` (`dict_id`, `dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (9, '操作类型', 'sys_oper_type', '1', 'admin', '2023-12-18 14:59:07', 'admin', '2024-01-16 00:00:00', '操作类型列表');
INSERT INTO `sys_dict_type` (`dict_id`, `dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (10, '系统状态', 'sys_common_status', '1', 'admin', '2023-12-18 14:59:07', 'admin', '2024-01-16 00:00:00', '登录状态列表');
COMMIT;
-- ----------------------------
-- Table structure for sys_logininfor
-- ----------------------------
DROP TABLE IF EXISTS `sys_logininfor`;
CREATE TABLE `sys_logininfor` (
`info_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '访问ID',
`user_name` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '用户账号',
`ipaddr` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '登录IP地址',
`login_location` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '登录地点',
`browser` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '浏览器类型',
`os` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '操作系统',
`status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '1' COMMENT '登录状态(0失败,1成功)',
`msg` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '提示消息',
`login_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '访问时间',
PRIMARY KEY (`info_id`) USING BTREE,
KEY `idx_sys_logininfor_s` (`status`) USING BTREE,
KEY `idx_sys_logininfor_lt` (`login_time`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=355 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='系统访问记录';
-- ----------------------------
-- Records of sys_logininfor
-- ----------------------------
BEGIN;
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (260, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-05 10:13:04');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (261, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-05 10:26:49');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (262, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '用户不存在/密码错误', '2024-06-05 11:14:49');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (263, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-05 11:14:55');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (264, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-05 11:15:02');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (265, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-05 11:15:08');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (266, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-05 20:19:51');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (267, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-05 20:23:02');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (268, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-05 20:23:09');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (269, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-05 20:23:18');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (270, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-05 20:23:27');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (271, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-05 20:23:34');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (272, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-05 20:23:45');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (273, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', 'ip:127.0.0.1被封禁', '2024-06-05 20:24:02');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (274, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-05 21:23:49');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (275, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '用户不存在/密码错误', '2024-06-05 21:27:55');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (276, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-05 21:28:07');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (277, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-05 21:28:13');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (278, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '用户不存在/密码错误', '2024-06-05 21:39:50');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (279, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-05 21:40:01');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (280, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-05 21:42:49');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (281, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '用户不存在/密码错误', '2024-06-06 08:38:07');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (282, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '用户不存在/密码错误', '2024-06-06 08:38:13');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (283, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-06 08:38:27');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (284, 'admin', '127.0.0.1', '内网IP', 'Chrome 120', 'Windows 10', '0', '验证码错误!', '2024-06-06 15:09:09');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (285, 'admin', '127.0.0.1', '内网IP', 'Chrome 120', 'Windows 10', '0', '验证码错误!', '2024-06-06 15:09:14');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (286, 'admin', '127.0.0.1', '内网IP', 'Chrome 120', 'Windows 10', '0', '验证码错误!', '2024-06-06 15:09:16');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (287, 'admin', '127.0.0.1', '内网IP', 'Chrome 120', 'Windows 10', '0', '验证码错误!', '2024-06-06 15:09:18');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (288, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-07 15:35:29');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (289, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-07 15:39:11');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (290, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '用户不存在/密码错误', '2024-06-07 15:39:16');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (291, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-07 15:39:28');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (292, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '用户不存在/密码错误', '2024-06-07 15:42:45');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (293, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-07 15:43:16');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (294, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-07 15:43:23');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (295, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-07 15:46:04');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (296, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-07 15:47:56');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (297, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-07 15:53:44');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (298, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-07 16:22:49');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (299, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-07 16:22:58');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (300, 'test2', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-07 16:47:27');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (301, 'test2', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-07 16:47:34');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (302, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-07 20:19:38');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (303, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-07 20:19:48');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (304, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-08 13:53:25');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (305, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-08 13:53:39');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (306, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-08 13:53:45');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (307, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 10:59:44');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (308, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 11:00:07');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (309, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 11:01:54');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (310, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 11:02:42');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (311, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 11:03:37');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (312, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-10 13:35:32');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (313, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 13:35:41');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (314, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 14:51:52');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (315, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-10 15:03:14');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (316, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '密码不正确', '2024-06-10 15:03:22');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (317, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 15:03:33');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (318, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-10 15:20:14');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (319, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 15:20:21');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (320, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-10 15:21:24');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (321, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 15:21:29');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (322, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 15:53:15');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (323, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-10 15:56:40');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (324, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 15:56:49');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (325, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 18:12:33');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (326, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '密码不正确', '2024-06-10 18:14:24');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (327, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-10 18:17:58');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (328, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-10 18:18:02');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (329, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '密码不正确', '2024-06-10 18:18:10');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (330, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-10 18:37:48');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (331, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 18:37:53');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (332, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-10 18:38:22');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (333, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 08:37:46');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (334, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 08:38:36');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (335, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 08:39:30');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (336, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 08:48:50');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (337, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-11 09:05:23');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (338, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 09:05:29');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (339, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 09:07:52');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (340, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 09:29:37');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (341, 'test', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 09:53:13');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (342, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 10:24:10');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (343, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 15:11:36');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (344, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 15:37:20');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (345, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 16:57:29');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (346, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '0', '验证码错误!', '2024-06-11 18:40:48');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (347, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-11 18:40:55');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (348, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-12 12:15:46');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (349, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-12 12:19:56');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (350, 'admin', '127.0.0.1', '内网IP', 'Chrome 125', 'Windows 10', '1', '登录成功', '2024-06-12 12:21:38');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (351, 'admin', '127.0.0.1', '内网IP', 'Chrome 126', 'Windows 10', '1', '登录成功', '2024-06-14 21:27:00');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (352, 'admin', '127.0.0.1', '内网IP', 'Chrome 126', 'Windows 10', '1', '登录成功', '2024-06-16 13:54:15');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (353, 'admin', '127.0.0.1', '内网IP', 'Chrome 137', 'macOS Catalina', '0', '密码不正确', '2025-07-04 15:14:33');
INSERT INTO `sys_logininfor` (`info_id`, `user_name`, `ipaddr`, `login_location`, `browser`, `os`, `status`, `msg`, `login_time`) VALUES (354, 'admin', '127.0.0.1', '内网IP', 'Chrome 137', 'macOS Catalina', '1', '登录成功', '2025-07-04 15:14:51');
COMMIT;
-- ----------------------------
-- Table structure for sys_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_menu`;
CREATE TABLE `sys_menu` (
`menu_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
`menu_name` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '菜单名称',
`parent_id` int unsigned DEFAULT '0' COMMENT '父菜单ID',
`order_num` int DEFAULT '0' COMMENT '显示顺序',
`path` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '路由地址',
`component` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '组件路径',
`query` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '路由参数',
`is_frame` int DEFAULT '0' COMMENT '是否为外链(0否 1是)',
`is_cache` int DEFAULT '1' COMMENT '是否缓存(0不缓存 1缓存)',
`menu_type` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '菜单类型(M目录 C菜单 F按钮)',
`visible` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '1' COMMENT '菜单状态(0隐藏 1显示)',
`status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '1' COMMENT '菜单状态(0停用 1正常)',
`perms` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '权限标识',
`icon` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '#' COMMENT '菜单图标',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '备注',
PRIMARY KEY (`menu_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2052 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='菜单权限表';
-- ----------------------------
-- Records of sys_menu
-- ----------------------------
BEGIN;
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1, '系统管理', 0, 1, 'system', NULL, '', 0, 1, 'M', '1', '1', '', 'system', 'admin', '2023-12-18 14:59:03', '', NULL, '系统管理目录');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2, '系统监控', 0, 2, 'monitor', NULL, '', 0, 1, 'M', '1', '1', '', 'monitor', 'admin', '2023-12-18 14:59:03', '', NULL, '系统监控目录');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (3, '系统工具', 0, 3, 'tool', NULL, '', 0, 1, 'M', '1', '1', '', 'tool', 'admin', '2023-12-18 14:59:03', '', NULL, '系统工具目录');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (100, '用户管理', 1, 1, 'user', 'system/user/index', '', 0, 1, 'C', '1', '1', 'system:user:list', 'user', 'admin', '2023-12-18 14:59:03', '', NULL, '用户管理菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (101, '角色管理', 1, 2, 'role', 'system/role/index', '', 0, 1, 'C', '1', '1', 'system:role:list', 'peoples', 'admin', '2023-12-18 14:59:03', '', NULL, '角色管理菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (102, '菜单管理', 1, 3, 'menu', 'system/menu/index', '', 0, 1, 'C', '1', '1', 'system:menu:list', 'tree-table', 'admin', '2023-12-18 14:59:03', '', NULL, '菜单管理菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (103, '部门管理', 1, 4, 'dept', 'system/dept/index', '', 0, 1, 'C', '1', '1', 'system:dept:list', 'tree', 'admin', '2023-12-18 14:59:03', '', NULL, '部门管理菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (104, '岗位管理', 1, 5, 'post', 'system/post/index', '', 0, 1, 'C', '1', '1', 'system:post:list', 'post', 'admin', '2023-12-18 14:59:03', '', NULL, '岗位管理菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (105, '字典管理', 1, 6, 'dict', 'system/dict/index', '', 0, 1, 'C', '1', '1', 'system:dict:list', 'dict', 'admin', '2023-12-18 14:59:03', '', NULL, '字典管理菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (106, '参数设置', 1, 7, 'config', 'system/config/index', '', 0, 1, 'C', '1', '1', 'system:config:list', 'edit', 'admin', '2023-12-18 14:59:03', '', NULL, '参数设置菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (107, '通知公告', 1, 8, 'notice', 'system/notice/index', '', 0, 1, 'C', '1', '1', 'system:notice:list', 'message', 'admin', '2023-12-18 14:59:03', '', NULL, '通知公告菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (108, '日志管理', 1, 9, 'log', '', '', 0, 1, 'M', '1', '1', '', 'log', 'admin', '2023-12-18 14:59:03', '', NULL, '日志管理菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (109, '在线用户', 2, 1, 'online', 'monitor/online/index', '', 0, 1, 'C', '1', '1', 'monitor:online:list', 'online', 'admin', '2024-05-22 17:50:50', '', NULL, '在线用户菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (112, '服务监控', 2, 4, 'server', 'monitor/server/index', '', 0, 1, 'C', '1', '1', 'monitor:server:list', 'server', 'admin', '2023-12-18 14:59:03', '', NULL, '服务监控菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (116, '代码生成', 3, 2, 'gen', 'tool/gen/index', '', 0, 1, 'C', '1', '1', 'tool:gen:list', 'code', 'admin', '2023-12-18 14:59:03', '', NULL, '代码生成菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (501, '登录日志', 108, 2, 'logininfor', 'monitor/logininfor/index', '', 0, 1, 'C', '1', '1', 'monitor:logininfor:list', 'logininfor', 'admin', '2023-12-18 14:59:03', '', NULL, '登录日志菜单');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1000, '用户查询', 100, 1, '', '', '', 0, 1, 'F', '1', '1', 'system:user:query', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1001, '用户新增', 100, 2, '', '', '', 0, 1, 'F', '1', '1', 'system:user:add', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1002, '用户修改', 100, 3, '', '', '', 0, 1, 'F', '1', '1', 'system:user:edit', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1003, '用户删除', 100, 4, '', '', '', 0, 1, 'F', '1', '1', 'system:user:remove', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1004, '用户导出', 100, 5, '', '', '', 0, 1, 'F', '1', '1', 'system:user:export', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1007, '角色查询', 101, 1, '', '', '', 0, 1, 'F', '1', '1', 'system:role:query', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1008, '角色新增', 101, 2, '', '', '', 0, 1, 'F', '1', '1', 'system:role:add', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1009, '角色修改', 101, 3, '', '', '', 0, 1, 'F', '1', '1', 'system:role:edit', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1010, '角色删除', 101, 4, '', '', '', 0, 1, 'F', '1', '1', 'system:role:remove', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1011, '角色导出', 101, 5, '', '', '', 0, 1, 'F', '1', '1', 'system:role:export', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1012, '菜单查询', 102, 1, '', '', '', 0, 1, 'F', '1', '1', 'system:menu:query', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1013, '菜单新增', 102, 2, '', '', '', 0, 1, 'F', '1', '1', 'system:menu:add', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1014, '菜单修改', 102, 3, '', '', '', 0, 1, 'F', '1', '1', 'system:menu:edit', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1015, '菜单删除', 102, 4, '', '', '', 0, 1, 'F', '1', '1', 'system:menu:remove', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1016, '部门查询', 103, 1, '', '', '', 0, 1, 'F', '1', '1', 'system:dept:query', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1017, '部门新增', 103, 2, '', '', '', 0, 1, 'F', '1', '1', 'system:dept:add', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1018, '部门修改', 103, 3, '', '', '', 0, 1, 'F', '1', '1', 'system:dept:edit', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1019, '部门删除', 103, 4, '', '', '', 0, 1, 'F', '1', '1', 'system:dept:remove', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1020, '岗位查询', 104, 1, '', '', '', 0, 1, 'F', '1', '1', 'system:post:query', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1021, '岗位新增', 104, 2, '', '', '', 0, 1, 'F', '1', '1', 'system:post:add', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1022, '岗位修改', 104, 3, '', '', '', 0, 1, 'F', '1', '1', 'system:post:edit', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1023, '岗位删除', 104, 4, '', '', '', 0, 1, 'F', '1', '1', 'system:post:remove', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1024, '岗位导出', 104, 5, '', '', '', 0, 1, 'F', '1', '1', 'system:post:export', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1025, '字典查询', 105, 1, '#', '', '', 0, 1, 'F', '1', '1', 'system:dict:query', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1026, '字典新增', 105, 2, '#', '', '', 0, 1, 'F', '1', '1', 'system:dict:add', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1027, '字典修改', 105, 3, '#', '', '', 0, 1, 'F', '1', '1', 'system:dict:edit', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1028, '字典删除', 105, 4, '#', '', '', 0, 1, 'F', '1', '1', 'system:dict:remove', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1029, '字典导出', 105, 5, '#', '', '', 0, 1, 'F', '1', '1', 'system:dict:export', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1030, '参数查询', 106, 1, '#', '', '', 0, 1, 'F', '1', '1', 'system:config:query', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1031, '参数新增', 106, 2, '#', '', '', 0, 1, 'F', '1', '1', 'system:config:add', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1032, '参数修改', 106, 3, '#', '', '', 0, 1, 'F', '1', '1', 'system:config:edit', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1033, '参数删除', 106, 4, '#', '', '', 0, 1, 'F', '1', '1', 'system:config:remove', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1034, '参数导出', 106, 5, '#', '', '', 0, 1, 'F', '1', '1', 'system:config:export', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1035, '公告查询', 107, 1, '#', '', '', 0, 1, 'F', '1', '1', 'system:notice:query', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1036, '公告新增', 107, 2, '#', '', '', 0, 1, 'F', '1', '1', 'system:notice:add', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1037, '公告修改', 107, 3, '#', '', '', 0, 1, 'F', '1', '1', 'system:notice:edit', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1038, '公告删除', 107, 4, '#', '', '', 0, 1, 'F', '1', '1', 'system:notice:remove', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1042, '登录查询', 501, 1, '#', '', '', 0, 1, 'F', '1', '1', 'monitor:logininfor:query', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1043, '登录删除', 501, 2, '#', '', '', 0, 1, 'F', '1', '1', 'monitor:logininfor:remove', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1044, '日志导出', 501, 3, '#', '', '', 0, 1, 'F', '1', '1', 'monitor:logininfor:export', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1046, '在线查询', 109, 1, '#', '', '', 0, 1, 'F', '1', '1', 'monitor:online:query', '#', 'admin', '2024-05-22 17:50:50', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1047, '批量强退', 109, 2, '#', '', '', 0, 1, 'F', '1', '1', 'monitor:online:batchLogout', '#', 'admin', '2024-05-22 17:50:50', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1055, '生成查询', 116, 1, '#', '', '', 0, 1, 'F', '1', '1', 'tool:gen:query', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1056, '生成修改', 116, 2, '#', '', '', 0, 1, 'F', '1', '1', 'tool:gen:edit', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1057, '生成删除', 116, 3, '#', '', '', 0, 1, 'F', '1', '1', 'tool:gen:remove', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1058, '导入代码', 116, 4, '#', '', '', 0, 1, 'F', '1', '1', 'tool:gen:import', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1059, '预览代码', 116, 5, '#', '', '', 0, 1, 'F', '1', '1', 'tool:gen:preview', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1060, '生成代码', 116, 6, '#', '', '', 0, 1, 'F', '1', '1', 'tool:gen:code', '#', 'admin', '2023-12-18 14:59:03', '', NULL, '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2032, '接口文档', 3, 3, 'swagger', 'tool/swagger/index', NULL, 0, 1, 'C', '1', '1', NULL, 'documentation', 'admin', '2024-06-05 19:03:55', 'admin', '2024-06-05 19:14:40', '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2035, '缓存监控', 2, 2, 'cache', 'monitor/cache/index', NULL, 0, 1, 'C', '1', '1', 'monitor:cache:list', 'redis', 'admin', '2024-06-05 20:55:04', 'admin', '2024-06-05 21:03:09', '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2051, '配置信息修改', 0, 0, 'serverconfig', 'system/config/edit', NULL, 0, 1, 'C', '1', '1', 'system:serverconfig:menu', 'documentation', 'admin', '2025-07-04 16:10:04', 'admin', '2025-07-04 16:22:37', '');
COMMIT;
-- ----------------------------
-- Table structure for sys_notice
-- ----------------------------
DROP TABLE IF EXISTS `sys_notice`;
CREATE TABLE `sys_notice` (
`notice_id` int NOT NULL AUTO_INCREMENT COMMENT '公告ID',
`notice_title` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '公告标题',
`notice_type` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '公告类型(1通知 2公告)',
`notice_content` mediumtext CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci COMMENT '公告内容',
`status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '1' COMMENT '公告状态(0关闭 1正常)',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`notice_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='通知公告表';
-- ----------------------------
-- Records of sys_notice
-- ----------------------------
BEGIN;
INSERT INTO `sys_notice` (`notice_id`, `notice_title`, `notice_type`, `notice_content`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (10, '测试', '1', 'hello
', '1', 'admin', '2024-06-05 20:30:23', 'admin', '2024-06-05 20:30:23', NULL);
COMMIT;
-- ----------------------------
-- Table structure for sys_post
-- ----------------------------
DROP TABLE IF EXISTS `sys_post`;
CREATE TABLE `sys_post` (
`post_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '岗位ID',
`post_code` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '岗位编码',
`post_name` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '岗位名称',
`post_sort` int NOT NULL COMMENT '显示顺序',
`status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '1' COMMENT '状态(0停用 1正常)',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`post_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='岗位信息表';
-- ----------------------------
-- Records of sys_post
-- ----------------------------
BEGIN;
INSERT INTO `sys_post` (`post_id`, `post_code`, `post_name`, `post_sort`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1, 'ceo', '董事长', 1, '1', 'admin', '2023-12-18 14:59:02', '', NULL, '');
INSERT INTO `sys_post` (`post_id`, `post_code`, `post_name`, `post_sort`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2, 'se', '项目经理', 2, '1', 'admin', '2023-12-18 14:59:02', '', NULL, '');
INSERT INTO `sys_post` (`post_id`, `post_code`, `post_name`, `post_sort`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (3, 'hr', '人力资源', 3, '1', 'admin', '2023-12-18 14:59:02', '', NULL, '');
INSERT INTO `sys_post` (`post_id`, `post_code`, `post_name`, `post_sort`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (4, 'user', '普通员工', 4, '1', 'admin', '2023-12-18 14:59:02', '', NULL, '');
COMMIT;
-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`role_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '角色ID',
`role_name` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '角色名称',
`role_key` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '角色权限字符串',
`role_sort` int NOT NULL COMMENT '显示顺序',
`data_scope` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '5' COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅个人权限)',
`menu_check_strictly` tinyint DEFAULT '1' COMMENT '菜单树选择项是否关联显示',
`dept_check_strictly` tinyint DEFAULT '1' COMMENT '部门树选择项是否关联显示',
`status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '1' COMMENT '角色状态(0停用 1正常)',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`role_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='角色信息表';
-- ----------------------------
-- Records of sys_role
-- ----------------------------
BEGIN;
INSERT INTO `sys_role` (`role_id`, `role_name`, `role_key`, `role_sort`, `data_scope`, `menu_check_strictly`, `dept_check_strictly`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1, '超级管理员', 'admin', 1, '1', 1, 1, '1', 'admin', '2023-12-18 14:59:03', '', NULL, '超级管理员');
INSERT INTO `sys_role` (`role_id`, `role_name`, `role_key`, `role_sort`, `data_scope`, `menu_check_strictly`, `dept_check_strictly`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2, '普通角色', 'common', 2, '2', 1, 1, '1', 'admin', '2023-12-18 14:59:03', 'admin', '2024-06-07 20:34:41', '普通角色');
COMMIT;
-- ----------------------------
-- Table structure for sys_role_dept
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_dept`;
CREATE TABLE `sys_role_dept` (
`role_id` int unsigned NOT NULL COMMENT '角色ID',
`dept_id` int unsigned NOT NULL COMMENT '部门ID',
PRIMARY KEY (`role_id`,`dept_id`) USING BTREE,
KEY `sys_role_dept_dept_id_idx` (`dept_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='角色和部门关联表';
-- ----------------------------
-- Records of sys_role_dept
-- ----------------------------
BEGIN;
INSERT INTO `sys_role_dept` (`role_id`, `dept_id`) VALUES (2, 100);
INSERT INTO `sys_role_dept` (`role_id`, `dept_id`) VALUES (2, 101);
INSERT INTO `sys_role_dept` (`role_id`, `dept_id`) VALUES (2, 103);
INSERT INTO `sys_role_dept` (`role_id`, `dept_id`) VALUES (2, 104);
INSERT INTO `sys_role_dept` (`role_id`, `dept_id`) VALUES (2, 105);
INSERT INTO `sys_role_dept` (`role_id`, `dept_id`) VALUES (2, 106);
COMMIT;
-- ----------------------------
-- Table structure for sys_role_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_menu`;
CREATE TABLE `sys_role_menu` (
`role_id` int unsigned NOT NULL COMMENT '角色ID',
`menu_id` int unsigned NOT NULL COMMENT '菜单ID',
PRIMARY KEY (`role_id`,`menu_id`) USING BTREE,
KEY `sys_role_menu_menu_id_idx` (`menu_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='角色和菜单关联表';
-- ----------------------------
-- Records of sys_role_menu
-- ----------------------------
BEGIN;
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 2);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 3);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 100);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 101);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 102);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 103);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 104);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 105);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 106);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 107);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 108);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 112);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 116);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 501);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1000);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1007);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1012);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1016);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1020);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1025);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1030);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1035);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1042);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 1055);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 2032);
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (2, 2035);
COMMIT;
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`user_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`dept_id` int unsigned DEFAULT NULL COMMENT '部门ID',
`user_name` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '用户账号',
`nick_name` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '用户昵称',
`user_type` varchar(2) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '00' COMMENT '用户类型(00系统用户)',
`email` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '用户邮箱',
`phonenumber` varchar(11) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '手机号码',
`sex` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)',
`avatar` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '头像地址',
`password` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '密码',
`status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '1' COMMENT '帐号状态(0停用,1正常 )',
`login_ip` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '最后登录IP',
`login_date` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '最后登录时间',
`create_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '创建者',
`create_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '更新者',
`update_time` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`user_id`) USING BTREE,
KEY `sys_user_dept_id_idx` (`dept_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=125 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='用户信息表';
-- ----------------------------
-- Records of sys_user
-- ----------------------------
BEGIN;
INSERT INTO `sys_user` (`user_id`, `dept_id`, `user_name`, `nick_name`, `user_type`, `email`, `phonenumber`, `sex`, `avatar`, `password`, `status`, `login_ip`, `login_date`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1, 103, 'admin', 'admin', '00', 'admin@carole.top', '18888888888', '0', '', 'e5fa720ab8006315ad95dd38736675b3e67604e099f19d644c503b604e9222bd', '1', '127.0.0.1', '2023-12-21 15:19:31', 'admin', '2023-12-18 14:59:02', '', '2024-01-20 21:49:45', '管理员');
INSERT INTO `sys_user` (`user_id`, `dept_id`, `user_name`, `nick_name`, `user_type`, `email`, `phonenumber`, `sex`, `avatar`, `password`, `status`, `login_ip`, `login_date`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2, 103, 'test', 'test', '00', 'test@carole.top', '18888888888', '0', '', 'e7e266243c001eb54353a87b890206dc3fe8af383a7e90a5577d609a97e87a9f', '1', '127.0.0.1', '2023-12-21 15:19:31', 'admin', '2024-06-07 16:47:07', 'admin', '2024-06-07 17:09:14', 'test');
COMMIT;
-- ----------------------------
-- Table structure for sys_user_post
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_post`;
CREATE TABLE `sys_user_post` (
`user_id` int unsigned NOT NULL COMMENT '用户ID',
`post_id` int unsigned NOT NULL COMMENT '岗位ID',
PRIMARY KEY (`user_id`,`post_id`) USING BTREE,
KEY `sys_user_post_post_id_idx` (`post_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='用户与岗位关联表';
-- ----------------------------
-- Records of sys_user_post
-- ----------------------------
BEGIN;
INSERT INTO `sys_user_post` (`user_id`, `post_id`) VALUES (1, 1);
COMMIT;
-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`user_id` int unsigned NOT NULL COMMENT '用户ID',
`role_id` int unsigned NOT NULL COMMENT '角色ID',
PRIMARY KEY (`user_id`,`role_id`) USING BTREE,
KEY `sys_user_role_role_id_idx` (`role_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='用户和角色关联表';
-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
BEGIN;
INSERT INTO `sys_user_role` (`user_id`, `role_id`) VALUES (1, 1);
INSERT INTO `sys_user_role` (`user_id`, `role_id`) VALUES (2, 2);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
================================================
FILE: docs/.nojekyll
================================================
================================================
FILE: docs/README.md
================================================
Carole-Admin
一款基于 Nestjs+Vue前后端分离的后台框架
# 介绍
## 平台简介
`carole-admin` 是一款[Nestjs](https://nestjs.com/)+[Prisma](https://www.prisma.io/)+[Vue](https://vuejs.org/)+[Vite](https://vitejs.dev/)前后端分离的全栈快速开发平台, 前端基于[若依](https://github.com/yangzongzhuan/RuoYi-Vue3)。
- 前端采用[Vue3](https://vuejs.org/)、[Element-Plus](https://element-plus.org/)、[Vite](https://vitejs.dev/)。
- 后端采用[Nest](https://nestjs.com/)、[Prisma](https://www.prisma.io/)、[ioredis](https://github.com/redis/ioredis) & [Jwt](https://github.com/auth0/node-jsonwebtoken)。
- 权限认证使用[Jwt](https://github.com/auth0/node-jsonwebtoken),支持多终端认证系统。
- 支持加载动态权限菜单,多方式轻松权限控制。
- 支持接口限流
- 高效率开发,使用代码生成器可以一键生成前后端代码。
## 项目
> 演示地址:[https://carole-admin-demo.carole.top](https://carole-admin-demo.carole.top)
>
> 默认有两个用户: admin的密码为carole test的密码为123456
>
> github:
>
## 内置功能
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
2. 部门管理:配置系统组织机构。
3. 岗位管理:配置系统用户所属担任职务。
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
7. 参数管理:对系统动态配置常用参数。
8. 通知公告:系统通知公告信息发布维护。
9. 登录日志:系统登录日志记录查询包含登录异常。
10. 代码生成:前后端代码的生成(js、vue、sql)支持CRUD下载 。
11. 系统接口:根据业务代码自动生成相关的api接口文档。
12. 在线用户:当前系统中活跃用户状态监控。
13. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
14. 缓存监控:对系统的缓存信息查询,命令统计等。
## 演示图
|  |  |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
|  |  |
|  |  |
|  |  |
|  |  |
|  |  |
|  |  |
|  |  |
| | |
# 文档
## 主要文件结构
```
server #系统后端
front #系统前端
server/src目录
├─admin #系统管理模块
│ ├─gen #代码生成
│ └─system #系统代码
│ └─admin.module.ts #系统模块配置
├─common #工具类
│ ├─decorator #自定义注解
│ ├─filter #异常处理
│ ├─guard
│ │ ├─permission #权限校验
│ ├─middleware #中间件
│ │ └─auth #身份校验
│ ├─pipe #自定义管道
│ ├─prisma-client #prisma客户端
│ ├─result #返回对象
│ ├─service
│ │ ├─auth #身份相关处理逻辑
│ │ ├─gen #代码生成逻辑
│ │ │ └─gen-template #代码模板
│ └─utils #通用工具
├─prisma
│ └─schema #数据库模型定义
│ └─schema.prisma #prisma主文件
├─schedule #定时任务
├─.env #环境变量配置, 密码
├─main.ts #主文件
├─config.ts #系统配置文件
├─config-production.json #系统生产配置文件
├─config-development.json #系统开发配置文件
├─app.module.ts #系统主模块
```
## 开发指南
详细的开发指南请参考以下文档:
- [安装指南](install.md) - 安装使用详解
- [配置说明](config.md) - 系统配置文件详解
- [开发指南](guide.md) - 包含权限控制、Prisma使用、代码生成等详细说明
- [常见问题](faq.md) - 常见问题解答
## 部署指南
关于如何部署系统,请参考[部署指南](guide.md?id=部署)。
================================================
FILE: docs/_coverpage.md
================================================
# Carole-Admin
> 一款基于 Nestjs+Vue 前后端分离的后台框架
- 🚀 高效开发,一键生成前后端代码
- 🔒 完善的权限管理和认证系统
- 🛠️ 丰富的内置功能和组件
- 📱 响应式设计,支持多终端访问
[GitHub](https://github.com/Carole007/carole-admin)
[演示站点](https://carole-admin-demo.carole.top)
[开始使用](#介绍)
================================================
FILE: docs/_navbar.md
================================================
* [首页](/)
* 文档
* [安装指南](/install.md)
* [配置说明](/config.md)
* [开发指南](/guide.md)
* [代码生成](code_gen.md)
* [部署指南](guide.md?id=部署)
* [常见问题](/faq.md)
* 链接
* [GitHub](https://github.com/Carole007/carole-admin)
* [演示站点](https://carole-admin-demo.carole.top)
* 相关技术
* [NestJS](https://nestjs.com/)
* [Prisma](https://www.prisma.io/)
* [Vue3](https://vuejs.org/)
* [Element Plus](https://element-plus.org/)
================================================
FILE: docs/_sidebar.md
================================================
* [首页](README.md)
* [安装指南](install.md)
* [配置说明](config.md)
* [开发指南](guide.md)
* [代码生成](code_gen.md)
* [部署指南](guide.md?id=部署)
* [常见问题](faq.md)
================================================
FILE: docs/code_gen.md
================================================
# 代码生成的使用
> 本篇文章介绍carole-admin系统的代码生成器使用
>
> 这里演示一个用户管理crud
## 前置准备
```sql
-- 建表
CREATE TABLE `test_user` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户账号',
`password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码',
`nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '昵称',
`avatar` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '头像',
`status` char(1) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '状态(0禁用,1正常)',
`create_time` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '注册时间',
`update_time` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='测试用户表';
-- 插入数据
INSERT INTO `test_user` (`id`, `username`, `password`, `nickname`, `avatar`, `status`, `create_time`, `update_time`) VALUES (1, 'Steve', 'U4GC3q7QRo', 'Liao Wai Lam', NULL, '1', '2022-12-15 08:24:00', '2001-02-06');
INSERT INTO `test_user` (`id`, `username`, `password`, `nickname`, `avatar`, `status`, `create_time`, `update_time`) VALUES (2, 'Sarah', '1oQl45QK1b', 'Kwong Tin Lok', NULL, '0', '2020-08-02 06:48:56', '2024-02-02');
INSERT INTO `test_user` (`id`, `username`, `password`, `nickname`, `avatar`, `status`, `create_time`, `update_time`) VALUES (3, 'Jose', 'JvVL0dC243', 'Tong Ka Ming', NULL, '1', '2007-10-03 09:13:04', '2009-08-16');
INSERT INTO `test_user` (`id`, `username`, `password`, `nickname`, `avatar`, `status`, `create_time`, `update_time`) VALUES (4, 'Matthew', 'qAEgP7NxFY', 'Kwok Ka Keung', NULL, '0', '2012-04-07 15:29:30', '2021-02-25');
INSERT INTO `test_user` (`id`, `username`, `password`, `nickname`, `avatar`, `status`, `create_time`, `update_time`) VALUES (5, 'Ronald', '2qME1z0UhZ', 'Choi Tsz Ching', NULL, '1', '2006-04-08 01:21:21', '2010-01-29');
INSERT INTO `test_user` (`id`, `username`, `password`, `nickname`, `avatar`, `status`, `create_time`, `update_time`) VALUES (6, 'Ellen', 'FRuTzGFgWj', 'Yip Sze Yu', NULL, '1', '2012-04-21 17:20:16', '2003-12-24');
INSERT INTO `test_user` (`id`, `username`, `password`, `nickname`, `avatar`, `status`, `create_time`, `update_time`) VALUES (7, 'Shirley', 'pouCHlM5jm', 'Yue Kar Yan', NULL, '1', '2011-03-13 21:45:26', '2003-12-02');
```
## 导入表
- 登录系统,进入系统工具-代码生成,点击导入,勾选需要生成的表,点击确定。


## 字典添加
这里我们用户有两种状态(禁用,正常),咋们可以使用字典进行管理,后期进行添加修改比较方便,比如再添加一个状态为封禁。
1. 添加字典类型


2. 点击字典类型,为此类型添加数据




## 修改代码生成配置
点击左侧菜单-> 系统工具 -> 代码生成 修改刚才添加的表

### 修改字段信息
这里按照自己的业务需求设置即可,用户状态选择单选或者下拉,字典类型选择刚才新建的那个。

### 修改生成信息

#### 💡 **注意事项**
系统admin模块中已存在默认的`/system/user`,因此建议在生成业务代码时:
- 将业务名修改为 `user1` 或其他不冲突的名称。
- 或者修改子系统名,以避免接口 URL 冲突。
生成的菜单信息中 `name` 默认使用业务名,请务必确保名称不与现有菜单重复。
如果业务名与已有模块(如 `user`)重复,可以选择:
✅ 修改业务名后生成代码
✅ 或直接生成代码并执行菜单创建 SQL,再通过菜单管理手动修改菜单路由地址
此外,如果将代码生成到独立的模块目录中(不用默认的admin模块),也可避免路径冲突。
这里主要演示此类场景的处理方式。
这里我们修改子系统名和业务名 点击提交

## 添加菜单和权限
> 如果你已经有此表对应的菜单,不需要再执行
- 点击这个小眼睛图标查看代码

- 复制sql代码

- 执行sql

粘贴刚才复制的sql代码,执行

执行完毕刷新网页可看到菜单已添加

修改菜单图标


接下来完成代码导入
## 生成prisma模型
> 因为这个表是新建的,没有prisma模型,所以需要生成
> 如果你已经有这表的模型了,可以不用生成
1. cd到server目录 执行server目录下的 `驼峰生成prisma的model.bat`或者驼峰生成prisma的model.sh ` ./驼峰生成prisma的model.sh `

1. 生成完毕后,会在prisma里生成一个文件,introspected.prisma,我们可以自己改名移动到schema里面,或者把model复制粘贴到schema里面的某个文件中(记得删除文件),这里我就改为test移动到schema里面。


## 下载&导入代码
1. 下载代码
这里我们点击右边的下载图标即可

2. 解压得到,node就是后端的代码,vue前端代码

> 建议大家使用git管理代码,防止代码丢失,导入代码时会覆盖代码
### 导入后端代码
> 如果您使用了eslint,请格式化代码
>
> 如果你生成时没有用默认的admin模块,请确保已存在你填写的模块,没有的话:执行`nest g mo 模块名`生成模块
进入node目录, 复制整个模块到 覆盖项目server/src
> 一定要选择合并覆盖 而不是替换该目录。

在代码生成的模块中,我们刚才选择的是默认的admin模块,注册service和controller

如果serice或controller类名冲突,我们可以手动改下类名,或者修改代码生成的基本信息实体类配置
### 导入前端代码
进入下载的压缩文件vue目录, 复制代码到 front/src 合并覆盖

## 刷新页面查看效果
>若出现500错误,重启一下后端服务
### 默认查询

### 测试修改


本期教程结束。
================================================
FILE: docs/config.md
================================================
## ⚙️ 配置说明
> ⚠️ **重要说明**
如果 JSON 配置文件中存在 `Config` 里的 配置项,它将覆盖默认的 `Config` 对象对应的键值,请修改对应JSON文件确保配置生效!
- 修改时请遵循开发环境优先,编辑对应的开发或生产 JSON 文件。
- 如果 JSON 文件中未包含某个 key,则该 key 的值将使用 `config.ts` 中的默认配置。
**Carole-Admin** 的配置主要分为两部分:
1. **主配置文件**
文件路径:`server/src/config.ts`
- 包含系统的主要配置项。
- 对应的 `config-development.json` 和 `config-production.json` 文件分别用于开发环境和生产环境配置。
- 可在 `config.ts` 中修改:
```ts
const runMode: 'development' | 'production' = 'development'
```
用于加载对应的配置文件,并覆盖 `Config` 对象的内容。
2. **环境变量文件**
文件路径:`server/src/.env`
- 包含数据库连接信息、以及自定义一些私密参数。
## 主配置文件详解
`config.ts` 文件包含了系统的大部分配置项,下面是各配置项的详细说明:
```typescript
import * as dotenv from 'dotenv'
import { join } from 'path'
import { watch } from 'fs'
import { readJsonFile } from './common/utils'
dotenv.config({ path: join(__dirname, `.env`) })
//运行模式,根据不同的模式加载不同的配置文件 development=>开发环境 production=>生产环境
export let runMode: 'development' | 'production' = 'development'
const config_file_path = join(__dirname, `config-${runMode}.json`)
/* 根据运行模式加载文件后,会覆盖默认配置
可直接修改对应的json文件 config-${runMode}.json 或者删除json文件中对应的key,默认就使用下面的配置。
后台提供了默认的配置文件修改,Config也会自动加载修改后的配置。 */
export const Config = {
//服务器的HTTP端口,默认为3000
port: 3000,
//# 应用的访问路径前缀
contextPath: '/v1',
swagger: {
//是否启用swagger
enable: true,
//接口文档路径
prefix: '/api'
},
captcha: {
//验证码类型 math或text
mode: 'math',
//验证码过期时间
expiresIn: 60 * 2
},
//配置文件列表,管理后台可快捷编辑同步Config数据 注意:开发环境运行在dist目录,修改的也是dist里面的配置文件
//根据业务可能会有多个配置文件
ConfigFileMap: {
production_config: {
desc: '生产环境配置',
filePath: join(__dirname, './config-production.json')
},
dev_config: {
desc: '开发环境配置',
filePath: join(__dirname, './config-production.json')
}
},
//接口限流 2分钟内同一个接口允许60次请求
rateLimit: {
//数据存储在redis or memory
storage: 'redis',
ttl: 2 * 60 * 1000,
limit: 60
},
crypto: {
//密码加密秘钥
psdSecret: 'carole123456'
},
token: {
// token加密秘钥
secret: 'carole123456',
//过期时间秒
expiresIn: 60 * 60 * 24
},
prisma: {
//是否显示执行的sql指令
logEnable: false,
//显示那些日志
log: ['query', 'info', 'warn', 'error'] as any
},
//redis连接配置
redis: {
//主机地址
host: '127.0.0.1',
//端口
port: 6379,
//数据库
db: 5,
//密码
password: ''
},
upload: {
//上传文件存储基目录 请设置一个绝对路径
path: join(__dirname, 'uploads'),
config: {
img: {
fileSize: 2 * 1024 * 1024,
files: 1,
fieldSize: 0.5 * 1024 * 1024,
fields: 100,
fieldNameSize: 100,
parts: 100,
headerPairs: 100
},
file: {
fileSize: 100 * 1024 * 1024,
files: 10,
fieldSize: 0.5 * 1024 * 1024,
fields: 100,
fieldNameSize: 100,
parts: 100,
headerPairs: 100
}
}
},
//生成配置
gen: {
//作者
author: 'carole',
//默认生成模块
packageName: 'admin',
//子模块目录
moduleName: 'system',
//是否去除表前缀,默认是false
autoRemovePre: false,
//表前缀(生成类名不会包含表前缀,多个用逗号分隔)
tablePrefix: ['sys_']
},
//邮件发送配置
mail: {
//是否启用邮箱
enable: false,
//超时设置, 30秒未发送邮件,则返回失败
timeout: 30 * 1000,
config: {
//邮箱服务器 qq:smtp.qq.com 网易: smtp.163.com
host: '',
//端口
port: 465,
auth: {
//用户名
user: '',
//密码
pass: ''
},
// 端口465设置true, 其他false
secure: true,
tls: {
//建立 TLS 连接时是否应该拒绝未经授权的服务器证书
rejectUnauthorized: false
}
}
}
}
initConfig()
export function initConfig() {
let data = readJsonFile(config_file_path)
if (data) {
for (let k in data) {
Config[k] = data[k]
}
}
}
// 监听config文件变化
watch(config_file_path, (eventType, filename) => {
if (eventType === 'change') {
try {
initConfig()
console.log('config已更新')
} catch (err) {
console.log('更新config失败:', err)
}
}
})
//是否开发环境
export function isDevelopment() {
return runMode === 'development'
}
//是否生产环境
export function isProduction() {
return runMode === 'production'
}
```
## 后台修改配置
> 注意:开发模式修改的是dist下的文件
>
> 修改后会同步更新Conifg
>

================================================
FILE: docs/faq.md
================================================
# 常见问题解答 (FAQ)
本文档收集了使用 Carole-Admin 系统时可能遇到的常见问题及其解决方案。
## 安装与配置问题
### Q: 执行 `npx prisma generate` 时失败怎么办?
**A:** 这通常是由于网络问题导致的。可以尝试以下解决方案:
1. 多次执行该命令
2. 使用代理或更换网络环境
### Q: 如何修改默认的数据库连接?
**A:** 编辑 `server/src/.env` 文件中的 `DATABASE_URL` 变量:
```
DATABASE_URL="mysql://用户名:密码@主机:端口/数据库名?charset=utf8mb4"
```
### Q: 如何修改系统的默认端口?
**A:** 编辑 `server/src/config.ts` 文件中的 `port` 配置项:
```typescript
port: 3000, // 修改为你需要的端口
```
### Q: 修改了密码加密秘钥后,无法登录系统怎么办?
**A:** 修改密码加密秘钥后,需要重新生成用户密码并更新数据库:
1. 执行 `server/test/password.js` 脚本生成新密码
2. 使用生成的密码更新数据库中的用户密码
```bash
node server/test/password.js
```
## Prisma 相关问题
### Q: 如何处理 Prisma 中的日期时区问题?
**A:** Prisma 中日期类型字段插入时可能存在时差问题。建议将数据库中的日期类型改为字符串类型,并在插入/更新时手动设置时间:
```typescript
// 插入数据时
const nowDate = () => dayjs().format('YYYY-MM-DD');
await prisma.user.create({
data: {
// ...其他字段
createTime: nowDate(),
updateTime: nowDate(),
},
});
```
### Q: 如何处理 BigInt 类型在 JSON 中的序列化问题?
**A:** 当数据库使用 `bigint` 类型时,在 JSON 序列化时可能会出现问题。可以通过扩展 `BigInt` 的 `toJSON` 方法解决:
```typescript
// 在应用启动时添加
BigInt.prototype.toJSON = function() {
return this.toString();
};
```
或者在查询时将 BigInt 转换为字符串:
```typescript
const result = await prisma.table.findMany();
return result.map(item => ({
...item,
bigIntField: item.bigIntField.toString(),
}));
```
### Q: 如何在 Prisma 中使用事务?
**A:** Prisma 提供了 `$transaction` 方法来支持事务操作:
```typescript
const [result1, result2] = await prisma.$transaction([
prisma.user.create({ data: { name: 'Alice' } }),
prisma.post.create({ data: { title: 'Hello World' } }),
]);
```
对于更复杂的事务逻辑,可以使用交互式事务:
```typescript
const result = await prisma.$transaction(async (tx) => {
// 使用 tx 代替 prisma 执行查询
const user = await tx.user.create({ data: { name: 'Alice' } });
// 基于第一个查询的结果执行第二个查询
const post = await tx.post.create({
data: {
title: 'Hello World',
authorId: user.id,
},
});
return { user, post };
});
```
## 代码生成问题
### Q: 代码生成时找不到表怎么办?
**A:** 确保以下几点:
1. 表已经在数据库中创建
2. 数据库连接配置正确
3. 在 Prisma schema 中已经定义了对应的模型
4. 模型名称使用 PascalCase 命名,并正确设置了 `@@map` 映射到表名
### Q: 生成的代码中字段名与数据库不一致怎么办?
**A:** 这通常是因为 Prisma 模型中的字段映射配置不正确。确保在模型中使用 `@map` 注解正确映射字段名:
```typescript
model User {
id Int @id @default(autoincrement())
firstName String @map("first_name")
lastName String @map("last_name")
@@map("sys_user")
}
```
### Q: 如何自定义生成的代码模板?
**A:** 代码生成模板位于 `server/src/common/service/gen/gen-template` 目录下。你可以根据需要修改这些模板文件,但请注意保留模板中的变量占位符。
## 部署与性能问题
### Q: 如何优化系统性能?
**A:** 可以考虑以下优化措施:
1. **数据库优化**:
- 为常用查询添加索引
- 优化复杂查询
- 使用数据库连接池
2. **缓存策略**:
- 使用 Redis 缓存频繁访问的数据
- 实现适当的缓存失效策略
3. **代码优化**:
- 避免 N+1 查询问题
- 使用批量操作代替循环单个操作
- 优化大型响应的数据结构
4. **服务器配置**:
- 增加服务器资源(CPU、内存)
- 使用负载均衡分发请求
- 配置适当的 Node.js 内存限制
## 其他问题
### Q: 如何扩展现有功能?
**A:** 扩展现有功能的最佳实践:
1. **遵循模块化原则**:
- 创建新的模块来封装相关功能
- 使用依赖注入来集成现有服务
2. **扩展而非修改**:
- 尽量不直接修改核心代码
- 使用继承或组合模式扩展现有类
3. **保持一致的代码风格**:
- 遵循项目的命名约定和结构
- 编写单元测试验证新功能
### Q: 如何贡献代码?
**A:** 欢迎通过以下方式贡献代码:
1. Fork 项目仓库
2. 创建功能分支
3. 提交更改
4. 确保代码通过测试
5. 提交 Pull Request
请确保您的代码符合项目的编码规范,并包含适当的文档和测试。
### Q: 在哪里可以获取更多帮助?
**A:** 如果您有其他问题,可以通过以下渠道获取帮助:
1. 查阅项目文档
2. 在 GitHub 仓库中提交 Issue
3. 加入社区讨论组
4. 联系项目维护者
---
如果您的问题未在此 FAQ 中列出,请在 GitHub 仓库中提交 Issue,我们会尽快回复并更新此 FAQ。
================================================
FILE: docs/guide.md
================================================
# 开发指南
本文档提供了 Carole-Admin 系统的开发指南,帮助开发者更好地使用和扩展系统。
## 权限控制
Carole-Admin 提供了两种权限注解用于控制接口访问:`@RequireRole` 和 `@RequirePermission`。
### @RequireRole
`@RequireRole` 注解用于配置接口要求用户拥有指定角色才可访问。
| 参数 | 类型 | 描述 |
| ----- | ------ | ---- |
| value | String | 角色 |
示例:以下代码表示必须拥有 `admin` 角色才可访问
```typescript
@RequireRole("admin")
async test() {
return Result.ok()
}
```
### @RequirePermission
`@RequirePermission` 注解用于配置接口要求用户拥有指定权限才可访问。
| 参数 | 类型 | 描述 |
| ----- | ------ | ---- |
| value | String | 权限 |
示例:以下代码表示必须拥有 `system:user:remove` 权限才可访问
```typescript
@RequirePermission("system:user:remove")
async test() {
return Result.ok()
}
```
## Prisma 相关
[Prisma 官方文档](https://www.prisma.io/docs/getting-started)
### Prisma 脚本功能
项目提供了两个 Prisma 相关的 bat 脚本:
#### 更新 prisma 的 model.bat
- 此脚本用于当你已经编写好 Prisma 的 model 文件,但数据库结构发生了更改时。它可以同步数据库的最新结构到 Prisma 的 schema 文件中。
- 相当于执行 `npx prisma db pull && npx prisma generate`
#### 驼峰生成 prisma 的 model.bat
- 此脚本用于从数据库中生成 Prisma 的 model 定义,适用于数据库表没有在 Prisma 中的 model 定义过。(代码生成模板会使用驼峰命名法,并自动添加字段和表的 map 映射关系。)
- 生成之后会在 src/prisma 目录中有个 `introspected.prisma` 文件,可以更改名字并移动到 `src/prisma/schema` 里面。
### Prisma 使用注意事项
- 项目打包时,可以在 schema.prisma 里的 binaryTargets 添加目标平台
- 确保 model 都写好表和字段的映射关系,使用 @@map 映射表,@Map 映射字段
- model 名称使用 PascalCase 命名,如 test -> Test, sys_config -> SysConfig
示例:
```javascript
model SysConfig {
configId Int @id @default(autoincrement()) @map("config_id")
configName String? @default("") @map("config_name") @db.VarChar(100)
configKey String? @default("") @map("config_key") @db.VarChar(100)
configValue String? @default("") @map("config_value") @db.VarChar(500)
configType String? @default("N") @map("config_type") @db.Char(1)
createBy String? @default("") @map("create_by") @db.VarChar(64)
createTime String? @map("create_time") @db.VarChar(25)
updateBy String? @default("") @map("update_by") @db.VarChar(64)
updateTime String? @map("update_time") @db.VarChar(25)
remark String? @map("remark") @db.VarChar(500)
@@map("sys_config")
}
```
- Prisma 中日期类型字段插入时存在时差问题
> 解决办法:把 SQL 中的日期类型改成字符串,插入更新时手动设置时间
- 处理 BigInt 类型数据时,可以使用以下方法解决 JSON 转换问题:
```javascript
BigInt.prototype.toJSON = function () {
return this.toString()
}
```
## 代码生成使用
代码生成器是 Carole-Admin 的核心功能之一,可以大幅提高开发效率。
详细教程:[代码生成器使用教程](code_gen.md)
### 使用步骤
1. 在 prisma\schema 写好对应表的 Model,字段名驼峰映射
2. 登录系统(系统工具 -> 代码生成 -> 导入对应表)
3. 在代码生成列表中找到需要的表(可预览、编辑、同步、删除生成配置)
4. 点击生成代码获取 `carole.zip`,执行 `sql` 文件生成菜单权限,按照包内目录结构复制到自己的项目中
5. 修改对应模块的 module.ts 文件,在 providers 中注册生成的 Service,controllers 注册生成的 Controller 类
### 代码生成功能
代码生成支持以下功能:
- **预览**:对生成的代码提前预览,防止出现一些不符合预期的情况。
- **同步**:对原表的字段进行同步,包括新增、删除、修改的字段处理。
- **修改**:对生成的代码基本信息、字段信息、生成信息做一系列的调整。
### 生成代码结构
生成的代码包括:
- 前端:Vue 组件、API 调用、路由配置
- 后端:Controller、Service、DTO 类
- SQL:菜单权限配置
## 定时任务
Carole-Admin 使用 [@nestjs/schedule](https://docs.nestjs.com/techniques/task-scheduling#task-scheduling) 实现定时任务功能。
### 使用方法
在 `server\src\schedule\index.ts` 中添加需要执行的方法并加上 @Cron 注解并携带 cron 表达式即可。
示例:
```typescript
// cron任务,每隔两秒执行一次
@Cron('*/2 * * * * *')
testCron() {
console.log("cron excute...")
}
```
### Cron 表达式说明
Cron 表达式由 6 个部分组成,从左到右依次为:
```
* * * * * *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ │
│ │ │ │ │ └ 星期几 (0 - 7) (0 或 7 是星期日)
│ │ │ │ └───── 月份 (1 - 12)
│ │ │ └────────── 日期 (1 - 31)
│ │ └─────────────── 小时 (0 - 23)
│ └──────────────────── 分钟 (0 - 59)
└───────────────────────── 秒 (0 - 59, 可选)
```
常用表达式:
- `* * * * * *` - 每秒执行
- `0 * * * * *` - 每分钟开始时执行
- `0 0 * * * *` - 每小时开始时执行
- `0 0 0 * * *` - 每天午夜执行
- `0 0 12 * * *` - 每天中午 12 点执行
## 接口限流
Carole-Admin 使用 [@nestjs/throttler](https://docs.nestjs.com/security/rate-limiting#multiple-throttler-definitions) 实现接口限流功能。
### 全局限流配置
默认所有接口 2 分钟内都只允许 60 次请求,可以在 config.ts 里面配置 rateLimit:
```typescript
rateLimit: {
// 数据存储在 redis 或 memory
storage: "redis",
// 时间窗口(毫秒)
ttl: 2 * 60 * 1000,
// 在时间窗口内允许的最大请求次数
limit: 60,
},
```
### 单个接口限流
使用 `@Throttle` 注解可以为单个接口配置限流规则:
```typescript
// 1个小时之内只能请求8次
@Throttle({
default: {
limit: 8,
ttl: 1000 * 60 * 60
}
})
async test1() {
return Result.ok()
}
// 5s内只能请求一次
@Throttle({
default: {
limit: 1,
ttl: 1000 * 5
}
})
async test2() {
return Result.ok()
}
```
### 用户级别限流
使用 `@ThrottleUser()` 注解可以对用户进行限流:
```typescript
// 用户1天只能请求一次
@ThrottleUser()
@Throttle({
default: {
limit: 1,
ttl: 1000 * 60 * 60 * 24
}
})
async test3() {
return Result.ok()
}
```
## 请求跳过登录验证
在某些情况下,您可能需要允许某些接口无需登录即可访问(如公开 API、健康检查等)。
修改 `server\src\app.module.ts` 文件:
```typescript
.exclude('/test(.*)', '/a') // 排除 /test 开头和 /a 的路由
.forRoutes('*') // 应用到所有路由
.forRoutes('/admin(*)') // 应用到所有 /admin 开头的路由
```
支持通配符:
- `/test(.*)` - 排除所有以 `/test` 开头的路由
- `*` - 应用到所有路由
- `/admin(*)` - 应用到所有以 `/admin` 开头的路由
## 使用 Redis
Carole-Admin 封装了 Redis 工具类,提供了常用的 Redis 操作方法。
### Redis 工具类
文件位置:`server\src\common\utils\redisUtils.ts`
该工具类封装了一个 Redis 连接池,提供了常用的 Redis 操作方法。
### 使用方法
```typescript
import { redisUtils } from '@/common/utils/redisUtils' // 导入
// 使用直接调用方法即可
const r = await redisUtils.get('demo')
await redisUtils.set('demo', 'hello world!', 10) // 过期时间秒为单位 10s过期
```
### 主要方法
- `get(key)` - 获取键值
- `set(key, value, expireTime)` - 设置键值,可选过期时间
- `del(key)` - 删除键
- `exists(key)` - 检查键是否存在
- `expire(key, seconds)` - 设置过期时间
- `ttl(key)` - 获取剩余过期时间
- `keys(pattern)` - 获取匹配模式的所有键
- 更多方法请查看源码
## 请求参数验证
Carole-Admin 使用 [class-validator](https://github.com/typestack/class-validator) 进行请求参数验证。
### 使用场景
使用类定义参数的模型规则,请求时会对参数做校验,不通过直接返回错误,以及自动删除不在类中的字段,更加安全方便。
例如,对于用户修改接口,如果只允许修改 nickname、age 和 email,但用户恶意传入了 password,使用参数验证可以自动过滤掉不允许的字段。
### 使用方法
1. 定义 DTO 类:
```typescript
export class CreateDictDataDto extends BaseDomain {
@ApiProperty({ description: '字典类型' })
@IsNotEmpty({ message: '字典类型不能为空' })
@IsString()
dictType: string
@ApiProperty({ description: '数据标签' })
@IsNotEmpty({ message: '数据标签不能为空' })
@IsString()
dictLabel: string
@ApiProperty({ description: '数据键值' })
@IsNotEmpty({ message: '数据键值不能为空' })
@IsString()
dictValue?: string
@ApiProperty({ description: '样式属性' })
@IsOptional()
cssClass?: string
@ApiProperty({ description: '回显样式' })
@IsOptional()
listClass?: string
@ApiProperty({ description: '显示排序' })
@IsNotEmpty({ message: '排序值不能为空' })
@Transform(v => +v.value)
@IsNumber()
dictSort: number
@ApiProperty({ description: '字典状态(0停用,1正常)' })
@IsOptional()
status?: string = '1'
}
```
2. 在 Controller 中使用:
```typescript
@Post()
async create(@Body() createDto: CreateDictDataDto) {
// createDto 已经经过验证,可以安全使用
return this.service.create(createDto);
}
```
### 注意事项
在 `server\src\app.module.ts` 中设置了 `whiteList: true`,会自动删除不在 DTO 类中的字段:
```typescript
app.useGlobalPipes(
new ValidationPipe({
whitelist: true, // 自动删除不在 DTO 类中的字段
transform: true, // 自动转换类型
forbidNonWhitelisted: false // 不允许未在白名单中的属性
})
)
```
因此,如果你使用了类来修饰参数类型,某个参数不想要验证,请务必加上 `@IsOptional()` 注解,标识可选的,否则这个字段会被直接删除掉。
## 发送邮件
Carole-Admin 提供了邮件发送功能,可用于系统通知、密码重置等场景。
### 配置邮件服务
1. 根据运行环境,修改 `config-[development|production].json` 文件中的邮箱配置:
```typescript
"mail": {
"enable": true, // 设置为 true 启用邮件服务
"timeout": 30000, //发送超时
"config": {
"host": "smtp.example.com",
"port": 465,
"auth": { "user": "用户名", "pass": "密码" },
"secure": true,
"tls": { "rejectUnauthorized": false }
}
}
```
### 使用邮件服务
系统提供了邮件工具类 `server\src\common\utils\email.ts`,可以直接参考该文件使用:
## 部署
本节介绍如何将 Carole-Admin 系统部署到生产环境。
### 后端部署
> 建议在config-production.json中 关闭 swagger 文档 `"swagger": { "enable": false }`
>
> 后台管理中修改用户密码,删除默认测试账号
1. 准备 Prisma 引擎:
[查看平台的引擎](https://www.prisma.io/docs/orm/reference/prisma-schema-reference#binarytargets-options)
```bash
cd server
# 方法一:在本地生成目标平台的引擎
# 在 schema.prisma 文件中添加目标平台
# generator client {
# provider = "prisma-client-js"
# binaryTargets = ["native", "linux-musl", "debian-openssl-1.1.x"]
# }
npx prisma generate
# 方法二:在服务器上生成引擎
# 将源代码上传到服务器,然后执行
npx prisma generate
```
2. 构建后端应用:
```bash
# 在本地或服务器上构建
npm run build
```
3. 准备部署文件:
```bash
# 将 package.json 复制到 dist 目录
cp package.json dist/
```
4. 部署到服务器:
```bash
# 上传 dist 目录到服务器
cd dist
# 在服务器上安装依赖
npm install
# 修改为生产环境配置
.env
# 修改config.ts运行模式为production,并修改config-production.json相关配置
export let runMode: "development" | "production" = "production";
# 使用 PM2 启动应用
- 安装PM2 npm install -g pm2
pm2 start main.js --name carole-admin
```
### 前端部署
1. 构建前端应用:
```bash
cd front
# 修改生产环境 API 地址(如需)
# 编辑 .env.production 文件
# 构建生产版本
npm run build:prod
```
2. 部署到 Web 服务器:
```bash
# 上传 dist 目录到服务器
```
3. 配置 Nginx:
```nginx
#server块添加以下内容
location / {
try_files $uri $uri/ /index.html;
}
```
================================================
FILE: docs/index.html
================================================
Carole-Admin - 基于 Nestjs+Vue 的后台框架
加载中...
================================================
FILE: docs/install.md
================================================
# 安装指南
本文档提供了 Carole-Admin 的基本安装步骤,帮助您快速搭建开发环境。更详细的配置和使用说明请参考[开发指南](guide.md)。
## 环境准备
在开始安装之前,请确保您的系统满足以下要求:
- **Node.js**: v20.12.0 或更高版本
- **MySQL**: 8.0.12 或更高版本
- **Redis**: 最新稳定版
您可以使用以下命令检查您的 Node.js 版本:
```bash
node -v
```
## 下载项目
```bash
# 克隆项目
git clone https://github.com/Carole007/carole-admin.git
# 进入项目目录
cd carole-admin
```
## 数据库配置
1. 创建一个名为 `carole` 的数据库 (可自定义数据库名称)
> 记得修改 `server/src/.env` 文件中的 `DATABASE_URL` 变量配置
2. 导入项目根目录下的 SQL 文件
## 快速启动
### 后端配置
```typescript
# 进入后端目录
cd server
# 安装依赖
npm install
# 生成 Prisma 客户端
npx prisma generate
# 配置环境变量
# 编辑 server/src/.env 文件,配置数据库连接信息
DATABASE_URL="mysql://root:root@localhost:3306/carole" #url格式 mysql://用户名:密码@ip:端口/数据库?参数charset=utf8mb4
# 修改相关配置
server/src/config-development.json
//redis连接信息
"redis": { "host": "127.0.0.1", "port": 6379, "db": 5, "password": "" },
//文件上传路径
"upload": {
"path": "/Users/carole/carole-admin/upload",
}
```
### 前端配置
```bash
# 进入前端目录
cd ../front
# 安装依赖
npm install
```
### 启动服务
```bash
# 启动后端服务
cd server
npm run start:dev
# 启动前端服务
cd ../front
npm run dev
```
## 访问系统
启动成功后,您可以通过以下地址访问系统:
- 前端页面:
- 后端 API:
## 默认账户
系统默认提供了两个账户:
- 管理员账户:用户名 `admin`,密码 `carole`
- 测试账户:用户名 `test`,密码 `123456`
## 更多配置
关于更详细的配置说明,请参考:
- [配置说明](config.md) - 系统配置文件详解
- [开发指南](guide.md) - 包含权限控制、Prisma 使用、代码生成等详细说明
- [常见问题](faq.md) - 常见问题解答
================================================
FILE: front/LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2018 RuoYi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: front/README.md
================================================
## 开始
```bash
# 克隆项目
git clone https://github.com/Carole007/carole-admin.git
# 进入项目目录
cd carole-admin/front
# 安装依赖
npm i
# 启动服务
npm run dev
# 构建测试环境 npm run build:stage
# 构建生产环境 npm run build:prod
# 前端访问地址 http://localhost:3001
```
================================================
FILE: front/bin/build.bat
================================================
@echo off
echo.
echo [��Ϣ] ���Web���̣�����dist�ļ���
echo.
%~d0
cd %~dp0
cd ..
npm run build:prod
pause
================================================
FILE: front/bin/package.bat
================================================
@echo off
echo.
echo [��Ϣ] ��װWeb���̣�����node_modules�ļ���
echo.
%~d0
cd %~dp0
cd ..
npm i --registry=https://registry.npmmirror.com
pause
================================================
FILE: front/bin/run-web.bat
================================================
@echo off
echo.
echo [��Ϣ] ʹ�� Vite �������� Web ���̡�
echo.
%~d0
cd %~dp0
cd ..
npm run dev
pause
================================================
FILE: front/html/ie.html
================================================
请升级您的浏览器
请升级您的浏览器,以便我们更好的为您提供服务!
您正在使用 Internet Explorer 的早期版本(IE11以下版本或使用该内核的浏览器)。这意味着在升级浏览器前,您将无法访问此网站。
请注意:微软公司对Windows XP 及 Internet Explorer 早期版本的支持已经结束
自 2016 年 1 月 12 日起,Microsoft 不再为 IE 11 以下版本提供相应支持和更新。没有关键的浏览器安全更新,您的电脑可能易受有害病毒、间谍软件和其他恶意软件的攻击,它们可以窃取或损害您的业务数据和信息。请参阅 微软对 Internet Explorer 早期版本的支持将于 2016 年 1 月 12 日结束的说明 。
您可以选择更先进的浏览器
推荐使用以下浏览器的最新版本。如果您的电脑已有以下浏览器的最新版本则直接使用该浏览器访问即可。
================================================
FILE: front/index.html
================================================
carole管理系统
================================================
FILE: front/package.json
================================================
{
"name": "carole-admin",
"version": "1.0.0",
"description": "carole管理系统",
"license": "MIT",
"type": "module",
"scripts": {
"dev": "vite",
"build:prod": "vite build",
"build:stage": "vite build --mode staging",
"preview": "vite preview"
},
"dependencies": {
"@element-plus/icons-vue": "2.3.1",
"@guolao/vue-monaco-editor": "^1.5.5",
"@vueup/vue-quill": "1.2.0",
"@vueuse/core": "10.6.1",
"axios": "0.27.2",
"echarts": "5.4.3",
"element-plus": "2.4.3",
"file-saver": "2.0.5",
"fuse.js": "6.6.2",
"highlight.js": "^11.9.0",
"js-cookie": "3.0.5",
"jsencrypt": "3.3.2",
"nprogress": "0.2.0",
"pinia": "2.1.7",
"vue": "3.3.9",
"vue-cropper": "1.1.1",
"vue-router": "4.2.5"
},
"devDependencies": {
"@vitejs/plugin-vue": "4.5.0",
"@vue/compiler-sfc": "3.3.9",
"sass": "1.69.5",
"unplugin-auto-import": "0.17.1",
"unplugin-vue-setup-extend-plus": "1.0.0",
"vite": "5.0.4",
"vite-plugin-compression": "0.5.1",
"vite-plugin-svg-icons": "2.0.1"
}
}
================================================
FILE: front/src/App.vue
================================================
================================================
FILE: front/src/api/login.js
================================================
import request from '@/utils/request'
// 登录方法
export function login(username, password, code, uuid) {
const data = {
username,
password,
code,
uuid
}
return request({
url: '/login',
headers: {
isToken: false,
repeatSubmit: false
},
method: 'post',
data: data
})
}
// 获取用户详细信息
export function getInfo() {
return request({
url: '/getInfo',
method: 'get'
})
}
// 退出方法
export function logout() {
return request({
url: '/logout',
method: 'post'
})
}
// 获取验证码
export function getCodeImg() {
return request({
url: '/captchaImage',
headers: {
isToken: false
},
method: 'get',
timeout: 20000
})
}
================================================
FILE: front/src/api/menu.js
================================================
import request from '@/utils/request'
// 获取路由
export const getRouters = () => {
return request({
url: '/getRouters',
method: 'get'
})
}
================================================
FILE: front/src/api/monitor/cache.js
================================================
import request from '@/utils/request'
// 查询缓存详细
export function getCache() {
return request({
url: '/monitor/cache',
method: 'get'
})
}
// 查询缓存名称列表
export function listCacheName() {
return request({
url: '/monitor/cache/getNames',
method: 'get'
})
}
// 查询缓存键名列表
export function listCacheKey(cacheName) {
return request({
url: '/monitor/cache/getKeys/' + cacheName,
method: 'get'
})
}
// 查询缓存内容
export function getCacheValue(cacheName, cacheKey) {
return request({
url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
method: 'get'
})
}
// 清理指定名称缓存
export function clearCacheName(cacheName) {
return request({
url: '/monitor/cache/clearCacheName/' + cacheName,
method: 'delete'
})
}
// 清理指定键名缓存
export function clearCacheKey(cacheKey) {
return request({
url: '/monitor/cache/clearCacheKey/' + cacheKey,
method: 'delete'
})
}
// 清理全部缓存
export function clearCacheAll() {
return request({
url: '/monitor/cache/clearCacheAll',
method: 'delete'
})
}
================================================
FILE: front/src/api/monitor/logininfor.js
================================================
import request from '@/utils/request'
// 查询登录日志列表
export function list(query) {
return request({
url: '/monitor/logininfor/list',
method: 'get',
params: query
})
}
// 删除登录日志
export function delLogininfor(infoId) {
return request({
url: '/monitor/logininfor/' + infoId,
method: 'delete'
})
}
// 解锁用户登录状态
export function unlockLogininfor(userName) {
return request({
url: '/monitor/logininfor/unlock/' + userName,
method: 'get'
})
}
// 清空登录日志
export function cleanLogininfor() {
return request({
url: '/monitor/logininfor/clean',
method: 'delete'
})
}
================================================
FILE: front/src/api/monitor/online.js
================================================
import request from '@/utils/request'
// 查询在线用户列表
export function list(query) {
return request({
url: '/monitor/online/list',
method: 'get',
params: query
})
}
// 强退用户
export function forceLogout(tokenId) {
return request({
url: '/monitor/online/' + tokenId,
method: 'delete'
})
}
================================================
FILE: front/src/api/monitor/server.js
================================================
import request from '@/utils/request'
// 获取服务信息
export function getServer() {
return request({
url: '/monitor/server',
method: 'get'
})
}
================================================
FILE: front/src/api/system/config.js
================================================
import request from '@/utils/request'
// 查询参数列表
export function listConfig(query) {
return request({
url: '/system/config/list',
method: 'get',
params: query
})
}
// 查询参数详细
export function getConfig(configId) {
return request({
url: '/system/config/' + configId,
method: 'get'
})
}
// 根据参数键名查询参数值
export function getConfigKey(configKey) {
return request({
url: '/system/config/configKey/' + configKey,
method: 'get'
})
}
// 新增参数配置
export function addConfig(data) {
return request({
url: '/system/config',
method: 'post',
data: data
})
}
// 修改参数配置
export function updateConfig(data) {
return request({
url: '/system/config',
method: 'put',
data: data
})
}
// 删除参数配置
export function delConfig(configId) {
return request({
url: '/system/config/' + configId,
method: 'delete'
})
}
// 刷新参数缓存
export function refreshCache() {
return request({
url: '/system/config/refreshCache',
method: 'delete'
})
}
/** 获取所有 Filekey 列表 */
export function getKeys() {
return request({
url: '/system/config/getFileKeys',
method: 'get',
})
}
/** 根据 key 获取文件数据 */
export function getInfoByKey(key) {
return request({
url: '/system/config/getConfigInfo',
method: 'get',
params: { key }
})
}
/** 根据 key 修改文件数据 */
export function updateInfoByKey(key, data) {
return request({
url: '/system/config/serverConfig',
method: 'post',
params: { key },
data
})
}
================================================
FILE: front/src/api/system/dept.js
================================================
import request from '@/utils/request'
// 查询部门列表
export function listDept(query) {
return request({
url: '/system/dept/list',
method: 'get',
params: query
})
}
// 查询部门列表(排除节点)
export function listDeptExcludeChild(deptId) {
return request({
url: '/system/dept/list/exclude/' + deptId,
method: 'get'
})
}
// 查询部门详细
export function getDept(deptId) {
return request({
url: '/system/dept/' + deptId,
method: 'get'
})
}
// 新增部门
export function addDept(data) {
return request({
url: '/system/dept',
method: 'post',
data: data
})
}
// 修改部门
export function updateDept(data) {
return request({
url: '/system/dept',
method: 'put',
data: data
})
}
// 删除部门
export function delDept(deptId) {
return request({
url: '/system/dept/' + deptId,
method: 'delete'
})
}
================================================
FILE: front/src/api/system/dict/data.js
================================================
import request from '@/utils/request'
// 查询字典数据列表
export function listData(query) {
return request({
url: '/system/dict/data/list',
method: 'get',
params: query
})
}
// 查询字典数据详细
export function getData(dictCode) {
return request({
url: '/system/dict/data/' + dictCode,
method: 'get'
})
}
// 根据字典类型查询字典数据信息
export function getDicts(dictType) {
return request({
url: '/system/dict/data/type/' + dictType,
method: 'get'
})
}
// 新增字典数据
export function addData(data) {
return request({
url: '/system/dict/data',
method: 'post',
data: data
})
}
// 修改字典数据
export function updateData(data) {
return request({
url: '/system/dict/data',
method: 'put',
data: data
})
}
// 删除字典数据
export function delData(dictCode) {
return request({
url: '/system/dict/data/' + dictCode,
method: 'delete'
})
}
================================================
FILE: front/src/api/system/dict/type.js
================================================
import request from '@/utils/request'
// 查询字典类型列表
export function listType(query) {
return request({
url: '/system/dict/type/list',
method: 'get',
params: query
})
}
// 查询字典类型详细
export function getType(dictId) {
return request({
url: '/system/dict/type/' + dictId,
method: 'get'
})
}
// 新增字典类型
export function addType(data) {
return request({
url: '/system/dict/type',
method: 'post',
data: data
})
}
// 修改字典类型
export function updateType(data) {
return request({
url: '/system/dict/type',
method: 'put',
data: data
})
}
// 删除字典类型
export function delType(dictId) {
return request({
url: '/system/dict/type/' + dictId,
method: 'delete'
})
}
// 刷新字典缓存
export function refreshCache() {
return request({
url: '/system/dict/type/refreshCache',
method: 'delete'
})
}
// 获取字典选择框列表
export function optionselect() {
return request({
url: '/system/dict/type/optionselect',
method: 'get'
})
}
================================================
FILE: front/src/api/system/menu.js
================================================
import request from '@/utils/request'
// 查询菜单列表
export function listMenu(query) {
return request({
url: '/system/menu/list',
method: 'get',
params: query
})
}
// 查询菜单详细
export function getMenu(menuId) {
return request({
url: '/system/menu/' + menuId,
method: 'get'
})
}
// 查询菜单下拉树结构
export function treeselect() {
return request({
url: '/system/menu/treeselect',
method: 'get'
})
}
// 根据角色ID查询菜单下拉树结构
export function roleMenuTreeselect(roleId) {
return request({
url: '/system/menu/roleMenuTreeselect/' + roleId,
method: 'get'
})
}
// 新增菜单
export function addMenu(data) {
return request({
url: '/system/menu',
method: 'post',
data: data
})
}
// 修改菜单
export function updateMenu(data) {
return request({
url: '/system/menu',
method: 'put',
data: data
})
}
// 删除菜单
export function delMenu(menuId) {
return request({
url: '/system/menu/' + menuId,
method: 'delete'
})
}
================================================
FILE: front/src/api/system/notice.js
================================================
import request from '@/utils/request'
// 查询公告列表
export function listNotice(query) {
return request({
url: '/system/notice/list',
method: 'get',
params: query
})
}
// 查询公告详细
export function getNotice(noticeId) {
return request({
url: '/system/notice/' + noticeId,
method: 'get'
})
}
// 新增公告
export function addNotice(data) {
return request({
url: '/system/notice',
method: 'post',
data: data
})
}
// 修改公告
export function updateNotice(data) {
return request({
url: '/system/notice',
method: 'put',
data: data
})
}
// 删除公告
export function delNotice(noticeId) {
return request({
url: '/system/notice/' + noticeId,
method: 'delete'
})
}
================================================
FILE: front/src/api/system/post.js
================================================
import request from '@/utils/request'
// 查询岗位列表
export function listPost(query) {
return request({
url: '/system/post/list',
method: 'get',
params: query
})
}
// 查询岗位详细
export function getPost(postId) {
return request({
url: '/system/post/' + postId,
method: 'get'
})
}
// 新增岗位
export function addPost(data) {
return request({
url: '/system/post',
method: 'post',
data: data
})
}
// 修改岗位
export function updatePost(data) {
return request({
url: '/system/post',
method: 'put',
data: data
})
}
// 删除岗位
export function delPost(postId) {
return request({
url: '/system/post/' + postId,
method: 'delete'
})
}
================================================
FILE: front/src/api/system/role.js
================================================
import request from '@/utils/request'
// 查询角色列表
export function listRole(query) {
return request({
url: '/system/role/list',
method: 'get',
params: query
})
}
// 查询角色详细
export function getRole(roleId) {
return request({
url: '/system/role/' + roleId,
method: 'get'
})
}
// 新增角色
export function addRole(data) {
return request({
url: '/system/role',
method: 'post',
data: data
})
}
// 修改角色
export function updateRole(data) {
return request({
url: '/system/role',
method: 'put',
data: data
})
}
// 角色数据权限
export function dataScope(data) {
return request({
url: '/system/role/dataScope',
method: 'put',
data: data
})
}
// 角色状态修改
export function changeRoleStatus(roleId, status) {
const data = {
roleId,
status
}
return request({
url: '/system/role/changeStatus',
method: 'put',
data: data
})
}
// 删除角色
export function delRole(roleId) {
return request({
url: '/system/role/' + roleId,
method: 'delete'
})
}
// 查询角色已授权用户列表
export function allocatedUserList(query) {
return request({
url: '/system/role/authUser/allocatedList',
method: 'get',
params: query
})
}
// 查询角色未授权用户列表
export function unallocatedUserList(query) {
return request({
url: '/system/role/authUser/unallocatedList',
method: 'get',
params: query
})
}
// 取消用户授权角色
export function authUserCancel(data) {
return request({
url: '/system/role/authUser/cancel',
method: 'put',
data: data
})
}
// 批量取消用户授权角色
export function authUserCancelAll(data) {
return request({
url: '/system/role/authUser/cancelAll',
method: 'put',
params: data
})
}
// 授权用户选择
export function authUserSelectAll(data) {
return request({
url: '/system/role/authUser/selectAll',
method: 'put',
params: data
})
}
// 根据角色ID查询部门树结构
export function deptTreeSelect(roleId) {
return request({
url: '/system/role/deptTree/' + roleId,
method: 'get'
})
}
================================================
FILE: front/src/api/system/user.js
================================================
import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi";
// 查询用户列表
export function listUser(query) {
return request({
url: '/system/user/list',
method: 'get',
params: query
})
}
// 查询用户详细
export function getUser(userId) {
return request({
url: '/system/user/' + parseStrEmpty(userId),
method: 'get'
})
}
// 新增用户
export function addUser(data) {
return request({
url: '/system/user',
method: 'post',
data: data
})
}
// 修改用户
export function updateUser(data) {
return request({
url: '/system/user',
method: 'put',
data: data
})
}
// 删除用户
export function delUser(userId) {
return request({
url: '/system/user/' + userId,
method: 'delete'
})
}
// 用户密码重置
export function resetUserPwd(userId, password) {
const data = {
userId,
password
}
return request({
url: '/system/user/resetPwd',
method: 'put',
data: data
})
}
// 用户状态修改
export function changeUserStatus(userId, status) {
const data = {
userId,
status
}
return request({
url: '/system/user/changeStatus',
method: 'put',
data: data
})
}
// 查询用户个人信息
export function getUserProfile() {
return request({
url: '/system/user/profile',
method: 'get'
})
}
// 修改用户个人信息
export function updateUserProfile(data) {
return request({
url: '/system/user/profile',
method: 'put',
data: data
})
}
// 用户密码重置
export function updateUserPwd(oldPassword, newPassword) {
const data = {
oldPassword,
newPassword
}
return request({
url: '/system/user/profile/updatePwd',
method: 'put',
params: data
})
}
// 用户头像上传
export function uploadAvatar(data) {
return request({
url: '/system/user/profile/avatar',
method: 'post',
data: data
})
}
// 查询授权角色
export function getAuthRole(userId) {
return request({
url: '/system/user/authRole/' + userId,
method: 'get'
})
}
// 保存授权角色
export function updateAuthRole(data) {
return request({
url: '/system/user/authRole',
method: 'put',
params: data
})
}
// 查询部门下拉树结构
export function deptTreeSelect() {
return request({
url: '/system/user/deptTree',
method: 'get'
})
}
================================================
FILE: front/src/api/tool/gen.js
================================================
import request from '@/utils/request'
// 查询生成表数据
export function listTable(query) {
return request({
url: '/tool/gen/list',
method: 'get',
params: query
})
}
// 查询db数据库列表
export function listDbTable(query) {
return request({
url: '/tool/gen/db/list',
method: 'get',
params: query
})
}
// 查询表详细信息
export function getGenTable(tableId) {
return request({
url: '/tool/gen/' + tableId,
method: 'get'
})
}
// 修改代码生成信息
export function updateGenTable(data) {
return request({
url: '/tool/gen',
method: 'put',
data: data
})
}
// 导入表
export function importTable(data) {
return request({
url: '/tool/gen/importTable',
method: 'post',
params: data
})
}
// 预览生成代码
export function previewTable(tableId) {
return request({
url: '/tool/gen/preview/' + tableId,
method: 'get'
})
}
// 删除表数据
export function delTable(tableId) {
return request({
url: '/tool/gen/' + tableId,
method: 'delete'
})
}
// 生成代码(自定义路径)
export function genCode(tableName) {
return request({
url: '/tool/gen/genCode/' + tableName,
method: 'get'
})
}
// 同步数据库
export function synchDb(tableName) {
return request({
url: '/tool/gen/synchDb/' + tableName,
method: 'get'
})
}
// 执行sql
export function excuteSql(data) {
return request({
url: '/tool/gen/excute',
method: 'post',
data
})
}
================================================
FILE: front/src/assets/styles/btn.scss
================================================
@import './variables.module.scss';
@mixin colorBtn($color) {
background: $color;
&:hover {
color: $color;
&:before,
&:after {
background: $color;
}
}
}
.blue-btn {
@include colorBtn($blue)
}
.light-blue-btn {
@include colorBtn($light-blue)
}
.red-btn {
@include colorBtn($red)
}
.pink-btn {
@include colorBtn($pink)
}
.green-btn {
@include colorBtn($green)
}
.tiffany-btn {
@include colorBtn($tiffany)
}
.yellow-btn {
@include colorBtn($yellow)
}
.pan-btn {
font-size: 14px;
color: #fff;
padding: 14px 36px;
border-radius: 8px;
border: none;
outline: none;
transition: 600ms ease all;
position: relative;
display: inline-block;
&:hover {
background: #fff;
&:before,
&:after {
width: 100%;
transition: 600ms ease all;
}
}
&:before,
&:after {
content: '';
position: absolute;
top: 0;
right: 0;
height: 2px;
width: 0;
transition: 400ms ease all;
}
&::after {
right: inherit;
top: inherit;
left: 0;
bottom: 0;
}
}
.custom-button {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #fff;
color: #fff;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: 0;
margin: 0;
padding: 10px 15px;
font-size: 14px;
border-radius: 4px;
}
================================================
FILE: front/src/assets/styles/element-ui.scss
================================================
// cover some element-ui styles
.el-breadcrumb__inner,
.el-breadcrumb__inner a {
font-weight: 400 !important;
}
.el-upload {
input[type="file"] {
display: none !important;
}
}
.el-upload__input {
display: none;
}
.cell {
.el-tag {
margin-right: 0px;
}
}
.small-padding {
.cell {
padding-left: 5px;
padding-right: 5px;
}
}
.fixed-width {
.el-button--mini {
padding: 7px 10px;
width: 60px;
}
}
.status-col {
.cell {
padding: 0 10px;
text-align: center;
.el-tag {
margin-right: 0px;
}
}
}
// to fixed https://github.com/ElemeFE/element/issues/2461
.el-dialog {
transform: none;
left: 0;
position: relative;
margin: 0 auto;
}
// refine element ui upload
.upload-container {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
height: 200px;
}
}
}
// dropdown
.el-dropdown-menu {
a {
display: block
}
}
// fix date-picker ui bug in filter-item
.el-range-editor.el-input__inner {
display: inline-flex !important;
}
// to fix el-date-picker css style
.el-range-separator {
box-sizing: content-box;
}
.el-menu--collapse
> div
> .el-submenu
> .el-submenu__title
.el-submenu__icon-arrow {
display: none;
}
.el-dropdown .el-dropdown-link{
color: var(--el-color-primary) !important;
}
================================================
FILE: front/src/assets/styles/index.scss
================================================
@import './variables.module.scss';
@import './mixin.scss';
@import './transition.scss';
@import './element-ui.scss';
@import './sidebar.scss';
@import './btn.scss';
@import './ruoyi.scss';
body {
height: 100%;
margin: 0;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
}
label {
font-weight: 700;
}
html {
height: 100%;
box-sizing: border-box;
}
#app {
height: 100%;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
.no-padding {
padding: 0px !important;
}
.padding-content {
padding: 4px 0;
}
a:focus,
a:active {
outline: none;
}
a,
a:focus,
a:hover {
cursor: pointer;
color: inherit;
text-decoration: none;
}
div:focus {
outline: none;
}
.fr {
float: right;
}
.fl {
float: left;
}
.pr-5 {
padding-right: 5px;
}
.pl-5 {
padding-left: 5px;
}
.block {
display: block;
}
.pointer {
cursor: pointer;
}
.inlineBlock {
display: block;
}
.clearfix {
&:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
}
aside {
background: #eef1f6;
padding: 8px 24px;
margin-bottom: 20px;
border-radius: 2px;
display: block;
line-height: 32px;
font-size: 16px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
color: #2c3e50;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
a {
color: #337ab7;
cursor: pointer;
&:hover {
color: rgb(32, 160, 255);
}
}
}
//main-container全局样式
.app-container {
padding: 20px;
}
.components-container {
margin: 30px 50px;
position: relative;
}
.pagination-container {
margin-top: 30px;
}
.text-center {
text-align: center
}
.sub-navbar {
height: 50px;
line-height: 50px;
position: relative;
width: 100%;
text-align: right;
padding-right: 20px;
transition: 600ms ease position;
background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
.subtitle {
font-size: 20px;
color: #fff;
}
&.draft {
background: #d0d0d0;
}
&.deleted {
background: #d0d0d0;
}
}
.link-type,
.link-type:focus {
color: #337ab7;
cursor: pointer;
&:hover {
color: rgb(32, 160, 255);
}
}
.filter-container {
padding-bottom: 10px;
.filter-item {
display: inline-block;
vertical-align: middle;
margin-bottom: 10px;
}
}
================================================
FILE: front/src/assets/styles/mixin.scss
================================================
@mixin clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
@mixin scrollBar {
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
@mixin relative {
position: relative;
width: 100%;
height: 100%;
}
@mixin pct($pct) {
width: #{$pct};
position: relative;
margin: 0 auto;
}
@mixin triangle($width, $height, $color, $direction) {
$width: $width/2;
$color-border-style: $height solid $color;
$transparent-border-style: $width solid transparent;
height: 0;
width: 0;
@if $direction==up {
border-bottom: $color-border-style;
border-left: $transparent-border-style;
border-right: $transparent-border-style;
}
@else if $direction==right {
border-left: $color-border-style;
border-top: $transparent-border-style;
border-bottom: $transparent-border-style;
}
@else if $direction==down {
border-top: $color-border-style;
border-left: $transparent-border-style;
border-right: $transparent-border-style;
}
@else if $direction==left {
border-right: $color-border-style;
border-top: $transparent-border-style;
border-bottom: $transparent-border-style;
}
}
================================================
FILE: front/src/assets/styles/ruoyi.scss
================================================
/**
* 通用css样式布局处理
* Copyright (c) 2019 ruoyi
*/
/** 基础通用 **/
.pt5 {
padding-top: 5px;
}
.pr5 {
padding-right: 5px;
}
.pb5 {
padding-bottom: 5px;
}
.mt5 {
margin-top: 5px;
}
.mr5 {
margin-right: 5px;
}
.mb5 {
margin-bottom: 5px;
}
.mb8 {
margin-bottom: 8px;
}
.ml5 {
margin-left: 5px;
}
.mt10 {
margin-top: 10px;
}
.mr10 {
margin-right: 10px;
}
.mb10 {
margin-bottom: 10px;
}
.ml10 {
margin-left: 10px;
}
.mt20 {
margin-top: 20px;
}
.mr20 {
margin-right: 20px;
}
.mb20 {
margin-bottom: 20px;
}
.ml20 {
margin-left: 20px;
}
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
font-family: inherit;
font-weight: 500;
line-height: 1.1;
color: inherit;
}
.el-form .el-form-item__label {
font-weight: 700;
}
.el-dialog:not(.is-fullscreen) {
margin-top: 6vh !important;
}
.el-dialog.scrollbar .el-dialog__body {
overflow: auto;
overflow-x: hidden;
max-height: 70vh;
padding: 10px 20px 0;
}
.el-table {
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
th {
word-break: break-word;
background-color: #f8f8f9 !important;
color: #515a6e;
height: 40px !important;
font-size: 13px;
}
}
.el-table__body-wrapper {
.el-button [class*="el-icon-"] + span {
margin-left: 1px;
}
}
}
/** 表单布局 **/
.form-header {
font-size:15px;
color:#6379bb;
border-bottom:1px solid #ddd;
margin:8px 10px 25px 10px;
padding-bottom:5px
}
/** 表格布局 **/
.pagination-container {
position: relative;
height: 25px;
margin-bottom: 10px;
margin-top: 15px;
padding: 10px 20px !important;
}
.el-dialog .pagination-container {
position: static !important;
}
/* tree border */
.tree-border {
margin-top: 5px;
border: 1px solid #e5e6e7;
background: #FFFFFF none;
border-radius:4px;
width: 100%;
}
.pagination-container .el-pagination {
right: 0;
position: absolute;
}
@media ( max-width : 768px) {
.pagination-container .el-pagination > .el-pagination__jump {
display: none !important;
}
.pagination-container .el-pagination > .el-pagination__sizes {
display: none !important;
}
}
.el-table .fixed-width .el-button--small {
padding-left: 0;
padding-right: 0;
width: inherit;
}
/** 表格更多操作下拉样式 */
.el-table .el-dropdown-link {
cursor: pointer;
color: #409EFF;
margin-left: 10px;
}
.el-table .el-dropdown, .el-icon-arrow-down {
font-size: 12px;
}
.el-tree-node__content > .el-checkbox {
margin-right: 8px;
}
.list-group-striped > .list-group-item {
border-left: 0;
border-right: 0;
border-radius: 0;
padding-left: 0;
padding-right: 0;
}
.list-group {
padding-left: 0px;
list-style: none;
}
.list-group-item {
border-bottom: 1px solid #e7eaec;
border-top: 1px solid #e7eaec;
margin-bottom: -1px;
padding: 11px 0px;
font-size: 13px;
}
.pull-right {
float: right !important;
}
.el-card__header {
padding: 14px 15px 7px !important;
min-height: 40px;
}
.el-card__body {
padding: 15px 20px 20px 20px !important;
}
.card-box {
padding-right: 15px;
padding-left: 15px;
margin-bottom: 10px;
}
/* button color */
.el-button--cyan.is-active,
.el-button--cyan:active {
background: #20B2AA;
border-color: #20B2AA;
color: #FFFFFF;
}
.el-button--cyan:focus,
.el-button--cyan:hover {
background: #48D1CC;
border-color: #48D1CC;
color: #FFFFFF;
}
.el-button--cyan {
background-color: #20B2AA;
border-color: #20B2AA;
color: #FFFFFF;
}
/* text color */
.text-navy {
color: #1ab394;
}
.text-primary {
color: inherit;
}
.text-success {
color: #1c84c6;
}
.text-info {
color: #23c6c8;
}
.text-warning {
color: #f8ac59;
}
.text-danger {
color: #ed5565;
}
.text-muted {
color: #888888;
}
/* image */
.img-circle {
border-radius: 50%;
}
.img-lg {
width: 120px;
height: 120px;
}
.avatar-upload-preview {
position: absolute;
top: 50%;
transform: translate(50%, -50%);
width: 200px;
height: 200px;
border-radius: 50%;
box-shadow: 0 0 4px #ccc;
overflow: hidden;
}
/* 拖拽列样式 */
.sortable-ghost{
opacity: .8;
color: #fff!important;
background: #42b983!important;
}
/* 表格右侧工具栏样式 */
.top-right-btn {
margin-left: auto;
}
================================================
FILE: front/src/assets/styles/sidebar.scss
================================================
#app {
.main-container {
height: 100%;
transition: margin-left .28s;
margin-left: $base-sidebar-width;
position: relative;
}
.sidebarHide {
margin-left: 0!important;
}
.sidebar-container {
-webkit-transition: width .28s;
transition: width 0.28s;
width: $base-sidebar-width !important;
background-color: $base-menu-background;
height: 100%;
position: fixed;
font-size: 0px;
top: 0;
bottom: 0;
left: 0;
z-index: 1001;
overflow: hidden;
-webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
box-shadow: 2px 0 6px rgba(0,21,41,.35);
// reset element-ui css
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
}
.scrollbar-wrapper {
overflow-x: hidden !important;
}
.el-scrollbar__bar.is-vertical {
right: 0px;
}
.el-scrollbar {
height: 100%;
}
&.has-logo {
.el-scrollbar {
height: calc(100% - 50px);
}
}
.is-horizontal {
display: none;
}
a {
display: inline-block;
width: 100%;
overflow: hidden;
}
.svg-icon {
margin-right: 16px;
}
.el-menu {
border: none;
height: 100%;
width: 100% !important;
}
.el-menu-item, .menu-title {
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: nowrap !important;
}
.el-menu-item .el-menu-tooltip__trigger {
display: inline-block !important;
}
// menu hover
.sub-menu-title-noDropdown,
.el-sub-menu__title {
&:hover {
background-color: rgba(0, 0, 0, 0.06) !important;
}
}
& .theme-dark .is-active > .el-sub-menu__title {
color: $base-menu-color-active !important;
}
& .nest-menu .el-sub-menu>.el-sub-menu__title,
& .el-sub-menu .el-menu-item {
min-width: $base-sidebar-width !important;
&:hover {
background-color: rgba(0, 0, 0, 0.06) !important;
}
}
& .theme-dark .nest-menu .el-sub-menu>.el-sub-menu__title,
& .theme-dark .el-sub-menu .el-menu-item {
background-color: $base-sub-menu-background !important;
&:hover {
background-color: $base-sub-menu-hover !important;
}
}
}
.hideSidebar {
.sidebar-container {
width: 54px !important;
}
.main-container {
margin-left: 54px;
}
.sub-menu-title-noDropdown {
padding: 0 !important;
position: relative;
.el-tooltip {
padding: 0 !important;
.svg-icon {
margin-left: 20px;
}
}
}
.el-sub-menu {
overflow: hidden;
&>.el-sub-menu__title {
padding: 0 !important;
.svg-icon {
margin-left: 20px;
}
}
}
.el-menu--collapse {
.el-sub-menu {
&>.el-sub-menu__title {
&>span {
height: 0;
width: 0;
overflow: hidden;
visibility: hidden;
display: inline-block;
}
&>i {
height: 0;
width: 0;
overflow: hidden;
visibility: hidden;
display: inline-block;
}
}
}
}
}
.el-menu--collapse .el-menu .el-sub-menu {
min-width: $base-sidebar-width !important;
}
// mobile responsive
.mobile {
.main-container {
margin-left: 0px;
}
.sidebar-container {
transition: transform .28s;
width: $base-sidebar-width !important;
}
&.hideSidebar {
.sidebar-container {
pointer-events: none;
transition-duration: 0.3s;
transform: translate3d(-$base-sidebar-width, 0, 0);
}
}
}
.withoutAnimation {
.main-container,
.sidebar-container {
transition: none;
}
}
}
// when menu collapsed
.el-menu--vertical {
&>.el-menu {
.svg-icon {
margin-right: 16px;
}
}
.nest-menu .el-sub-menu>.el-sub-menu__title,
.el-menu-item {
&:hover {
// you can use $sub-menuHover
background-color: rgba(0, 0, 0, 0.06) !important;
}
}
// the scroll bar appears when the sub-menu is too long
>.el-menu--popup {
max-height: 100vh;
overflow-y: auto;
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
}
================================================
FILE: front/src/assets/styles/transition.scss
================================================
// global transition css
/* fade */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.28s;
}
.fade-enter,
.fade-leave-active {
opacity: 0;
}
/* fade-transform */
.fade-transform--move,
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all .5s;
}
.fade-transform-enter {
opacity: 0;
transform: translateX(-30px);
}
.fade-transform-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* breadcrumb transition */
.breadcrumb-enter-active,
.breadcrumb-leave-active {
transition: all .5s;
}
.breadcrumb-enter,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(20px);
}
.breadcrumb-move {
transition: all .5s;
}
.breadcrumb-leave-active {
position: absolute;
}
================================================
FILE: front/src/assets/styles/variables.module.scss
================================================
// base color
$blue: #324157;
$light-blue: #3A71A8;
$red: #C03639;
$pink: #E65D6E;
$green: #30B08F;
$tiffany: #4AB7BD;
$yellow: #FEC171;
$panGreen: #30B08F;
// 默认菜单主题风格
$base-menu-color: #bfcbd9;
$base-menu-color-active: #f4f4f5;
$base-menu-background: #304156;
$base-logo-title-color: #ffffff;
$base-menu-light-color: rgba(0, 0, 0, 0.7);
$base-menu-light-background: #ffffff;
$base-logo-light-title-color: #001529;
$base-sub-menu-background: #1f2d3d;
$base-sub-menu-hover: #001528;
// 自定义暗色菜单风格
/**
$base-menu-color:hsla(0,0%,100%,.65);
$base-menu-color-active:#fff;
$base-menu-background:#001529;
$base-logo-title-color: #ffffff;
$base-menu-light-color:rgba(0,0,0,.70);
$base-menu-light-background:#ffffff;
$base-logo-light-title-color: #001529;
$base-sub-menu-background:#000c17;
$base-sub-menu-hover:#001528;
*/
$--color-primary: #409EFF;
$--color-success: #67C23A;
$--color-warning: #E6A23C;
$--color-danger: #F56C6C;
$--color-info: #909399;
$base-sidebar-width: 200px;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuColor: $base-menu-color;
menuLightColor: $base-menu-light-color;
menuColorActive: $base-menu-color-active;
menuBackground: $base-menu-background;
menuLightBackground: $base-menu-light-background;
subMenuBackground: $base-sub-menu-background;
subMenuHover: $base-sub-menu-hover;
sideBarWidth: $base-sidebar-width;
logoTitleColor: $base-logo-title-color;
logoLightTitleColor: $base-logo-light-title-color;
primaryColor: $--color-primary;
successColor: $--color-success;
dangerColor: $--color-danger;
infoColor: $--color-info;
warningColor: $--color-warning;
}
================================================
FILE: front/src/components/Breadcrumb/index.vue
================================================
{{ item.meta.title }}
{{ item.meta.title }}
================================================
FILE: front/src/components/Crontab/day.vue
================================================
日,允许的通配符[, - * ? / L W]
不指定
周期从
-
日
从
号开始,每
日执行一次
每月
号最近的那个工作日
本月最后一天
指定
================================================
FILE: front/src/components/Crontab/hour.vue
================================================
小时,允许的通配符[, - * /]
周期从
-
时
从
时开始,每
小时执行一次
指定
================================================
FILE: front/src/components/Crontab/index.vue
================================================
================================================
FILE: front/src/components/Crontab/min.vue
================================================
分钟,允许的通配符[, - * /]
周期从
-
分钟
从
分钟开始, 每
分钟执行一次
指定
================================================
FILE: front/src/components/Crontab/month.vue
================================================
月,允许的通配符[, - * /]
周期从
-
月
从
月开始,每
月月执行一次
指定
================================================
FILE: front/src/components/Crontab/result.vue
================================================
================================================
FILE: front/src/components/Crontab/second.vue
================================================
秒,允许的通配符[, - * /]
周期从
-
秒
从
秒开始,每
秒执行一次
指定
================================================
FILE: front/src/components/Crontab/week.vue
================================================
周,允许的通配符[, - * ? / L #]
不指定
周期从
{{item.value}}
-
{{item.value}}
第
周的
本月最后一个
指定
================================================
FILE: front/src/components/Crontab/year.vue
================================================
不填,允许的通配符[, - * /]
每年
周期从
-
从
年开始,每
年执行一次
指定
================================================
FILE: front/src/components/DictTag/index.vue
================================================
{{ item.label + " " }}
{{ item.label + " " }}
{{ unmatchArray | handleArray }}
================================================
FILE: front/src/components/Editor/index.vue
================================================
$emit('update:modelValue', content)"
:options="options"
:style="styles"
/>
================================================
FILE: front/src/components/FileList/index.vue
================================================
================================================
FILE: front/src/components/FileUpload/index.vue
================================================
选取文件
请上传
大小不超过 {{ fileSize }}MB
格式为 {{ fileType.join("/") }}
的文件
{{ getFileName(file.name) }}
删除
================================================
FILE: front/src/components/Hamburger/index.vue
================================================
================================================
FILE: front/src/components/HeaderSearch/index.vue
================================================
================================================
FILE: front/src/components/IconSelect/index.vue
================================================
================================================
FILE: front/src/components/IconSelect/requireIcons.js
================================================
let icons = []
const modules = import.meta.glob('./../../assets/icons/svg/*.svg');
for (const path in modules) {
const p = path.split('assets/icons/svg/')[1].split('.svg')[0];
icons.push(p);
}
export default icons
================================================
FILE: front/src/components/ImagePreview/index.vue
================================================
未上传
================================================
FILE: front/src/components/ImageUpload/index.vue
================================================
请上传
大小不超过 {{ fileSize }}MB
格式为 {{ fileType.join("/") }}
的文件
================================================
FILE: front/src/components/Pagination/index.vue
================================================
================================================
FILE: front/src/components/ParentView/index.vue
================================================
================================================
FILE: front/src/components/RightToolbar/index.vue
================================================
================================================
FILE: front/src/components/Screenfull/index.vue
================================================
================================================
FILE: front/src/components/SizeSelect/index.vue
================================================
================================================
FILE: front/src/components/SvgIcon/index.vue
================================================
================================================
FILE: front/src/components/SvgIcon/svgicon.js
================================================
import * as components from '@element-plus/icons-vue'
export default {
install: (app) => {
for (const key in components) {
const componentConfig = components[key];
app.component(componentConfig.name, componentConfig);
}
},
};
================================================
FILE: front/src/components/TopNav/index.vue
================================================
{{ item.meta.title }}
更多菜单
{{ item.meta.title }}
================================================
FILE: front/src/components/TreeSelect/index.vue
================================================
================================================
FILE: front/src/components/iFrame/index.vue
================================================
================================================
FILE: front/src/directive/common/copyText.js
================================================
/**
* v-copyText 复制文本内容
* Copyright (c) 2022 ruoyi
*/
export default {
beforeMount(el, { value, arg }) {
if (arg === "callback") {
el.$copyCallback = value;
} else {
el.$copyValue = value;
const handler = () => {
copyTextToClipboard(el.$copyValue);
if (el.$copyCallback) {
el.$copyCallback(el.$copyValue);
}
};
el.addEventListener("click", handler);
el.$destroyCopy = () => el.removeEventListener("click", handler);
}
}
}
function copyTextToClipboard(input, { target = document.body } = {}) {
const element = document.createElement('textarea');
const previouslyFocusedElement = document.activeElement;
element.value = input;
// Prevent keyboard from showing on mobile
element.setAttribute('readonly', '');
element.style.contain = 'strict';
element.style.position = 'absolute';
element.style.left = '-9999px';
element.style.fontSize = '12pt'; // Prevent zooming on iOS
const selection = document.getSelection();
const originalRange = selection.rangeCount > 0 && selection.getRangeAt(0);
target.append(element);
element.select();
// Explicit selection workaround for iOS
element.selectionStart = 0;
element.selectionEnd = input.length;
let isSuccess = false;
try {
isSuccess = document.execCommand('copy');
} catch { }
element.remove();
if (originalRange) {
selection.removeAllRanges();
selection.addRange(originalRange);
}
// Get the focus back on the previously focused element, if any
if (previouslyFocusedElement) {
previouslyFocusedElement.focus();
}
return isSuccess;
}
================================================
FILE: front/src/directive/index.js
================================================
import hasRole from './permission/hasRole'
import hasPermi from './permission/hasPermi'
import copyText from './common/copyText'
export default function directive(app){
app.directive('hasRole', hasRole)
app.directive('hasPermi', hasPermi)
app.directive('copyText', copyText)
}
================================================
FILE: front/src/directive/permission/hasPermi.js
================================================
/**
* v-hasPermi 操作权限处理
* Copyright (c) 2019 ruoyi
*/
import useUserStore from '@/store/modules/user'
export default {
mounted(el, binding, vnode) {
const { value } = binding
const all_permission = "*:*:*";
const permissions = useUserStore().permissions
if (value && value instanceof Array && value.length > 0) {
const permissionFlag = value
const hasPermissions = permissions.some(permission => {
return all_permission === permission || permissionFlag.includes(permission)
})
if (!hasPermissions) {
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error(`请设置操作权限标签值`)
}
}
}
================================================
FILE: front/src/directive/permission/hasRole.js
================================================
/**
* v-hasRole 角色权限处理
* Copyright (c) 2019 ruoyi
*/
import useUserStore from '@/store/modules/user'
export default {
mounted(el, binding, vnode) {
const { value } = binding
const super_admin = "admin";
const roles = useUserStore().roles
if (value && value instanceof Array && value.length > 0) {
const roleFlag = value
const hasRole = roles.some(role => {
return super_admin === role || roleFlag.includes(role)
})
if (!hasRole) {
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error(`请设置角色权限标签值`)
}
}
}
================================================
FILE: front/src/layout/components/AppMain.vue
================================================
================================================
FILE: front/src/layout/components/IframeToggle/index.vue
================================================
================================================
FILE: front/src/layout/components/InnerLink/index.vue
================================================
================================================
FILE: front/src/layout/components/Navbar.vue
================================================
================================================
FILE: front/src/layout/components/Settings/index.vue
================================================
主题风格设置
主题颜色
系统布局配置
开启 TopNav
开启 Tags-Views
固定 Header
显示 Logo
动态标题
保存配置
重置配置
================================================
FILE: front/src/layout/components/Sidebar/Link.vue
================================================
================================================
FILE: front/src/layout/components/Sidebar/Logo.vue
================================================
================================================
FILE: front/src/layout/components/Sidebar/SidebarItem.vue
================================================
================================================
FILE: front/src/layout/components/Sidebar/index.vue
================================================
================================================
FILE: front/src/layout/components/TagsView/ScrollPane.vue
================================================
================================================
FILE: front/src/layout/components/TagsView/index.vue
================================================
{{ tag.title }}
================================================
FILE: front/src/layout/components/index.js
================================================
export { default as AppMain } from './AppMain'
export { default as Navbar } from './Navbar'
export { default as Settings } from './Settings'
export { default as TagsView } from './TagsView/index.vue'
================================================
FILE: front/src/layout/index.vue
================================================
================================================
FILE: front/src/main.js
================================================
import { createApp } from 'vue'
import Cookies from 'js-cookie'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import locale from 'element-plus/es/locale/lang/zh-cn'
import '@/assets/styles/index.scss' // global css
import App from './App'
import store from './store'
import router from './router'
import directive from './directive' // directive
// 注册指令
import plugins from './plugins' // plugins
import { download } from '@/utils/request'
// svg图标
import 'virtual:svg-icons-register'
import SvgIcon from '@/components/SvgIcon'
import elementIcons from '@/components/SvgIcon/svgicon'
import './permission' // permission control
import { useDict } from '@/utils/dict'
import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi'
// 分页组件
import Pagination from '@/components/Pagination'
// 自定义表格工具组件
import RightToolbar from '@/components/RightToolbar'
// 富文本组件
import Editor from "@/components/Editor"
// 文件上传组件
import FileUpload from "@/components/FileUpload"
// 图片上传组件
import ImageUpload from "@/components/ImageUpload"
// 图片预览组件
import ImagePreview from "@/components/ImagePreview"
// 自定义树选择组件
import TreeSelect from '@/components/TreeSelect'
// 字典标签组件
import DictTag from '@/components/DictTag'
//文件列表显示组件
import FileList from "@/components/FileList"
//文件编辑
import { install as VueMonacoEditorPlugin } from '@guolao/vue-monaco-editor'
const app = createApp(App)
app.use(VueMonacoEditorPlugin, {
paths: {
vs: 'https://unpkg.com/monaco-editor@0.43.0/min/vs'
},
})
// 全局方法挂载
app.config.globalProperties.useDict = useDict
app.config.globalProperties.download = download
app.config.globalProperties.parseTime = parseTime
app.config.globalProperties.resetForm = resetForm
app.config.globalProperties.handleTree = handleTree
app.config.globalProperties.addDateRange = addDateRange
app.config.globalProperties.selectDictLabel = selectDictLabel
app.config.globalProperties.selectDictLabels = selectDictLabels
// 全局组件挂载
app.component('DictTag', DictTag)
app.component('Pagination', Pagination)
app.component('TreeSelect', TreeSelect)
app.component('FileUpload', FileUpload)
app.component('ImageUpload', ImageUpload)
app.component('ImagePreview', ImagePreview)
app.component('RightToolbar', RightToolbar)
app.component('Editor', Editor)
app.component('FileList', FileList)
app.use(router)
app.use(store)
app.use(plugins)
app.use(elementIcons)
app.component('svg-icon', SvgIcon)
directive(app)
// 使用element-plus 并且设置全局的大小
app.use(ElementPlus, {
locale: locale,
// 支持 large、default、small
size: Cookies.get('size') || 'default'
})
app.mount('#app')
================================================
FILE: front/src/permission.js
================================================
import router from './router'
import { ElMessage } from 'element-plus'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import { isHttp } from '@/utils/validate'
import { isRelogin } from '@/utils/request'
import useUserStore from '@/store/modules/user'
import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission'
NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/register'];
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
to.meta.title && useSettingsStore().setTitle(to.meta.title)
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
if (useUserStore().roles.length === 0) {
isRelogin.show = true
// 判断当前用户是否已拉取完user_info信息
useUserStore().getInfo().then(() => {
isRelogin.show = false
usePermissionStore().generateRoutes().then(accessRoutes => {
// 根据roles权限生成可访问的路由表
accessRoutes.forEach(route => {
if (!isHttp(route.path)) {
router.addRoute(route) // 动态添加可访问路由表
}
})
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
}).catch(err => {
useUserStore().logOut().then(() => {
ElMessage.error(err)
next({ path: '/' })
})
})
} else {
next()
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})
================================================
FILE: front/src/plugins/auth.js
================================================
import useUserStore from '@/store/modules/user'
function authPermission(permission) {
const all_permission = "*:*:*";
const permissions = useUserStore().permissions
if (permission && permission.length > 0) {
return permissions.some(v => {
return all_permission === v || v === permission
})
} else {
return false
}
}
function authRole(role) {
const super_admin = "admin";
const roles = useUserStore().roles
if (role && role.length > 0) {
return roles.some(v => {
return super_admin === v || v === role
})
} else {
return false
}
}
export default {
// 验证用户是否具备某权限
hasPermi(permission) {
return authPermission(permission);
},
// 验证用户是否含有指定权限,只需包含其中一个
hasPermiOr(permissions) {
return permissions.some(item => {
return authPermission(item)
})
},
// 验证用户是否含有指定权限,必须全部拥有
hasPermiAnd(permissions) {
return permissions.every(item => {
return authPermission(item)
})
},
// 验证用户是否具备某角色
hasRole(role) {
return authRole(role);
},
// 验证用户是否含有指定角色,只需包含其中一个
hasRoleOr(roles) {
return roles.some(item => {
return authRole(item)
})
},
// 验证用户是否含有指定角色,必须全部拥有
hasRoleAnd(roles) {
return roles.every(item => {
return authRole(item)
})
}
}
================================================
FILE: front/src/plugins/cache.js
================================================
const sessionCache = {
set (key, value) {
if (!sessionStorage) {
return
}
if (key != null && value != null) {
sessionStorage.setItem(key, value)
}
},
get (key) {
if (!sessionStorage) {
return null
}
if (key == null) {
return null
}
return sessionStorage.getItem(key)
},
setJSON (key, jsonValue) {
if (jsonValue != null) {
this.set(key, JSON.stringify(jsonValue))
}
},
getJSON (key) {
const value = this.get(key)
if (value != null) {
return JSON.parse(value)
}
},
remove (key) {
sessionStorage.removeItem(key);
}
}
const localCache = {
set (key, value) {
if (!localStorage) {
return
}
if (key != null && value != null) {
localStorage.setItem(key, value)
}
},
get (key) {
if (!localStorage) {
return null
}
if (key == null) {
return null
}
return localStorage.getItem(key)
},
setJSON (key, jsonValue) {
if (jsonValue != null) {
this.set(key, JSON.stringify(jsonValue))
}
},
getJSON (key) {
const value = this.get(key)
if (value != null) {
return JSON.parse(value)
}
},
remove (key) {
localStorage.removeItem(key);
}
}
export default {
/**
* 会话级缓存
*/
session: sessionCache,
/**
* 本地缓存
*/
local: localCache
}
================================================
FILE: front/src/plugins/download.js
================================================
import axios from 'axios'
import { ElLoading, ElMessage } from 'element-plus'
import { saveAs } from 'file-saver'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { blobValidate } from '@/utils/ruoyi'
const baseURL = import.meta.env.VITE_APP_BASE_API
let downloadLoadingInstance;
export default {
name(name, isDelete = true) {
let url = baseURL + encodeURIComponent(name)
axios({
method: 'get',
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then((res) => {
const isBlob = blobValidate(res.data);
if (isBlob) {
const blob = new Blob([res.data])
this.saveAs(blob)
} else {
this.printErrMsg(res.data);
}
})
},
resource(resource) {
let url = baseURL + encodeURIComponent(resource);
axios({
method: 'get',
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then((res) => {
const isBlob = blobValidate(res.data);
if (isBlob) {
const blob = new Blob([res.data])
this.saveAs(blob)
} else {
this.printErrMsg(res.data);
}
})
},
zip(url, name) {
url = baseURL + url
downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
axios({
method: 'get',
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then((res) => {
const isBlob = blobValidate(res.data);
if (isBlob) {
const blob = new Blob([res.data], { type: 'application/zip' })
this.saveAs(blob, name)
} else {
this.printErrMsg(res.data);
}
downloadLoadingInstance.close();
}).catch((r) => {
console.error(r)
ElMessage.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close();
})
},
saveAs(text, name, opts) {
saveAs(text, name, opts);
},
async printErrMsg(data) {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
ElMessage.error(errMsg);
}
}
================================================
FILE: front/src/plugins/index.js
================================================
import tab from './tab'
import auth from './auth'
import cache from './cache'
import modal from './modal'
import download from './download'
export default function installPlugins(app){
// 页签操作
app.config.globalProperties.$tab = tab
// 认证对象
app.config.globalProperties.$auth = auth
// 缓存对象
app.config.globalProperties.$cache = cache
// 模态框对象
app.config.globalProperties.$modal = modal
// 下载文件
app.config.globalProperties.$download = download
}
================================================
FILE: front/src/plugins/modal.js
================================================
import { ElMessage, ElMessageBox, ElNotification, ElLoading } from 'element-plus'
let loadingInstance;
export default {
// 消息提示
msg(content) {
ElMessage.info(content)
},
// 错误消息
msgError(content) {
ElMessage.error(content)
},
// 成功消息
msgSuccess(content) {
ElMessage.success(content)
},
// 警告消息
msgWarning(content) {
ElMessage.warning(content)
},
// 弹出提示
alert(content) {
ElMessageBox.alert(content, "系统提示")
},
// 错误提示
alertError(content) {
ElMessageBox.alert(content, "系统提示", { type: 'error' })
},
// 成功提示
alertSuccess(content) {
ElMessageBox.alert(content, "系统提示", { type: 'success' })
},
// 警告提示
alertWarning(content) {
ElMessageBox.alert(content, "系统提示", { type: 'warning' })
},
// 通知提示
notify(content) {
ElNotification.info(content)
},
// 错误通知
notifyError(content) {
ElNotification.error(content);
},
// 成功通知
notifySuccess(content) {
ElNotification.success(content)
},
// 警告通知
notifyWarning(content) {
ElNotification.warning(content)
},
// 确认窗体
confirm(content) {
return ElMessageBox.confirm(content, "系统提示", {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: "warning",
})
},
// 提交内容
prompt(content) {
return ElMessageBox.prompt(content, "系统提示", {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: "warning",
})
},
// 打开遮罩层
loading(content) {
loadingInstance = ElLoading.service({
lock: true,
text: content,
background: "rgba(0, 0, 0, 0.7)",
})
},
// 关闭遮罩层
closeLoading() {
loadingInstance.close();
}
}
================================================
FILE: front/src/plugins/tab.js
================================================
import useTagsViewStore from '@/store/modules/tagsView'
import router from '@/router'
export default {
// 刷新当前tab页签
refreshPage(obj) {
const { path, query, matched } = router.currentRoute.value;
if (obj === undefined) {
matched.forEach((m) => {
if (m.components && m.components.default && m.components.default.name) {
if (!['Layout', 'ParentView'].includes(m.components.default.name)) {
obj = { name: m.components.default.name, path: path, query: query };
}
}
});
}
return useTagsViewStore().delCachedView(obj).then(() => {
const { path, query } = obj
router.replace({
path: '/redirect' + path,
query: query
})
})
},
// 关闭当前tab页签,打开新页签
closeOpenPage(obj) {
useTagsViewStore().delView(router.currentRoute.value);
if (obj !== undefined) {
return router.push(obj);
}
},
// 关闭指定tab页签
closePage(obj) {
if (obj === undefined) {
return useTagsViewStore().delView(router.currentRoute.value).then(({ visitedViews }) => {
const latestView = visitedViews.slice(-1)[0]
if (latestView) {
return router.push(latestView.fullPath)
}
return router.push('/');
});
}
return useTagsViewStore().delView(obj);
},
// 关闭所有tab页签
closeAllPage() {
return useTagsViewStore().delAllViews();
},
// 关闭左侧tab页签
closeLeftPage(obj) {
return useTagsViewStore().delLeftTags(obj || router.currentRoute.value);
},
// 关闭右侧tab页签
closeRightPage(obj) {
return useTagsViewStore().delRightTags(obj || router.currentRoute.value);
},
// 关闭其他tab页签
closeOtherPage(obj) {
return useTagsViewStore().delOthersViews(obj || router.currentRoute.value);
},
// 打开tab页签
openPage(url) {
return router.push(url);
},
// 修改tab页签
updatePage(obj) {
return useTagsViewStore().updateVisitedView(obj);
}
}
================================================
FILE: front/src/router/index.js
================================================
import { createWebHistory, createRouter } from 'vue-router'
/* Layout */
import Layout from '@/layout'
/**
* Note: 路由配置项
*
* hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1
* alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
* // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面
* // 若你想不管路由下面的 children 声明的个数都显示你的根路由
* // 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由
* redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
* name:'router-name' // 设定路由的名字,一定要填写不然使用时会出现各种问题
* query: '{"id": 1, "name": "ry"}' // 访问路由的默认传递参数
* roles: ['admin', 'common'] // 访问路由的角色权限
* permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限
* meta : {
noCache: true // 如果设置为true,则不会被 缓存(默认 false)
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg
breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示
activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。
}
*/
// 公共路由
export const constantRoutes = [
{
path: '/redirect',
component: Layout,
hidden: true,
children: [
{
path: '/redirect/:path(.*)',
component: () => import('@/views/redirect/index.vue')
}
]
},
{
path: '/login',
component: () => import('@/views/login'),
hidden: true
},
{
path: "/:pathMatch(.*)*",
component: () => import('@/views/error/404'),
hidden: true
},
{
path: '/401',
component: () => import('@/views/error/401'),
hidden: true
},
{
path: '',
component: Layout,
redirect: '/index',
children: [
{
path: '/index',
component: () => import('@/views/index'),
name: 'Index',
meta: { title: '首页', icon: 'dashboard', affix: true,noCache: false }
}
]
},
{
path: '/user',
component: Layout,
hidden: true,
redirect: 'noredirect',
children: [
{
path: 'profile',
component: () => import('@/views/system/user/profile/index'),
name: 'Profile',
meta: { title: '个人中心', icon: 'user' }
}
]
}
]
// 动态路由,基于用户权限动态去加载
export const dynamicRoutes = [
{
path: '/system/user-auth',
component: Layout,
hidden: true,
permissions: ['system:user:edit'],
children: [
{
path: 'role/:userId(\\d+)',
component: () => import('@/views/system/user/authRole'),
name: 'AuthRole',
meta: { title: '分配角色', activeMenu: '/system/user' }
}
]
},
{
path: '/system/role-auth',
component: Layout,
hidden: true,
permissions: ['system:role:edit'],
children: [
{
path: 'user/:roleId(\\d+)',
component: () => import('@/views/system/role/authUser'),
name: 'AuthUser',
meta: { title: '分配用户', activeMenu: '/system/role' }
}
]
},
{
path: '/system/dict-data',
component: Layout,
hidden: true,
permissions: ['system:dict:list'],
children: [
{
path: 'index/:dictId(\\d+)',
component: () => import('@/views/system/dict/data'),
name: 'Data',
meta: { title: '字典数据', activeMenu: '/system/dict' }
}
]
},
{
path: '/tool/gen-edit',
component: Layout,
hidden: true,
permissions: ['tool:gen:edit'],
children: [
{
path: 'index/:tableId(\\d+)',
component: () => import('@/views/tool/gen/editTable'),
name: 'GenEdit',
meta: { title: '修改生成配置', activeMenu: '/tool/gen' }
}
]
}
]
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
},
});
export default router;
================================================
FILE: front/src/settings.js
================================================
export default {
/**
* 网页标题
*/
title: import.meta.env.VITE_APP_TITLE,
/**
* 侧边栏主题 深色主题theme-dark,浅色主题theme-light
*/
sideTheme: 'theme-light',
/**
* 是否系统布局配置
*/
showSettings: true,
/**
* 是否显示顶部导航
*/
topNav: false,
/**
* 是否显示 tagsView
*/
tagsView: true,
/**
* 是否固定头部
*/
fixedHeader: false,
/**
* 是否显示logo
*/
sidebarLogo: true,
/**
* 是否显示动态标题
*/
dynamicTitle: false,
/**
* @type {string | array} 'production' | ['production', 'development']
* @description Need show err logs component.
* The default is only used in the production env
* If you want to also use it in dev, you can pass ['production', 'development']
*/
errorLog: 'production'
}
================================================
FILE: front/src/store/index.js
================================================
const store = createPinia()
export default store
================================================
FILE: front/src/store/modules/app.js
================================================
import Cookies from 'js-cookie'
const useAppStore = defineStore(
'app',
{
state: () => ({
sidebar: {
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
withoutAnimation: false,
hide: false
},
device: 'desktop',
size: Cookies.get('size') || 'default'
}),
actions: {
toggleSideBar(withoutAnimation) {
if (this.sidebar.hide) {
return false;
}
this.sidebar.opened = !this.sidebar.opened
this.sidebar.withoutAnimation = withoutAnimation
if (this.sidebar.opened) {
Cookies.set('sidebarStatus', 1)
} else {
Cookies.set('sidebarStatus', 0)
}
},
closeSideBar({ withoutAnimation }) {
Cookies.set('sidebarStatus', 0)
this.sidebar.opened = false
this.sidebar.withoutAnimation = withoutAnimation
},
toggleDevice(device) {
this.device = device
},
setSize(size) {
this.size = size;
Cookies.set('size', size)
},
toggleSideBarHide(status) {
this.sidebar.hide = status
}
}
})
export default useAppStore
================================================
FILE: front/src/store/modules/dict.js
================================================
const useDictStore = defineStore(
'dict',
{
state: () => ({
dict: new Array()
}),
actions: {
// 获取字典
getDict(_key) {
if (_key == null && _key == "") {
return null;
}
try {
for (let i = 0; i < this.dict.length; i++) {
if (this.dict[i].key == _key) {
return this.dict[i].value;
}
}
} catch (e) {
return null;
}
},
// 设置字典
setDict(_key, value) {
if (_key !== null && _key !== "") {
this.dict.push({
key: _key,
value: value
});
}
},
// 删除字典
removeDict(_key) {
var bln = false;
try {
for (let i = 0; i < this.dict.length; i++) {
if (this.dict[i].key == _key) {
this.dict.splice(i, 1);
return true;
}
}
} catch (e) {
bln = false;
}
return bln;
},
// 清空字典
cleanDict() {
this.dict = new Array();
},
// 初始字典
initDict() {
}
}
})
export default useDictStore
================================================
FILE: front/src/store/modules/permission.js
================================================
import auth from '@/plugins/auth'
import router, { constantRoutes, dynamicRoutes } from '@/router'
import { getRouters } from '@/api/menu'
import Layout from '@/layout/index'
import ParentView from '@/components/ParentView'
import InnerLink from '@/layout/components/InnerLink'
// 匹配views里面所有的.vue文件
const modules = import.meta.glob('./../../views/**/*.vue')
const usePermissionStore = defineStore(
'permission',
{
state: () => ({
routes: [],
addRoutes: [],
defaultRoutes: [],
topbarRouters: [],
sidebarRouters: []
}),
actions: {
setRoutes(routes) {
this.addRoutes = routes
this.routes = constantRoutes.concat(routes)
},
setDefaultRoutes(routes) {
this.defaultRoutes = constantRoutes.concat(routes)
},
setTopbarRoutes(routes) {
this.topbarRouters = routes
},
setSidebarRouters(routes) {
this.sidebarRouters = routes
},
generateRoutes(roles) {
return new Promise(resolve => {
// 向后端请求路由数据
getRouters().then(res => {
const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data))
const defaultData = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
const defaultRoutes = filterAsyncRouter(defaultData)
const asyncRoutes = filterDynamicRoutes(dynamicRoutes)
asyncRoutes.forEach(route => { router.addRoute(route) })
this.setRoutes(rewriteRoutes)
this.setSidebarRouters(constantRoutes.concat(sidebarRoutes))
this.setDefaultRoutes(sidebarRoutes)
this.setTopbarRoutes(defaultRoutes)
resolve(rewriteRoutes)
})
})
}
}
})
// 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
return asyncRouterMap.filter(route => {
if (type && route.children) {
route.children = filterChildren(route.children)
}
if (route.component) {
// Layout ParentView 组件特殊处理
if (route.component === 'Layout') {
route.component = Layout
} else if (route.component === 'ParentView') {
route.component = ParentView
} else if (route.component === 'InnerLink') {
route.component = InnerLink
} else {
route.component = loadView(route.component)
}
}
if (route.children != null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, route, type)
} else {
delete route['children']
delete route['redirect']
}
return true
})
}
function filterChildren(childrenMap, lastRouter = false) {
var children = []
childrenMap.forEach((el, index) => {
if (el.children && el.children.length) {
if (el.component === 'ParentView' && !lastRouter) {
el.children.forEach(c => {
c.path = el.path + '/' + c.path
if (c.children && c.children.length) {
children = children.concat(filterChildren(c.children, c))
return
}
children.push(c)
})
return
}
}
if (lastRouter) {
el.path = lastRouter.path + '/' + el.path
if (el.children && el.children.length) {
children = children.concat(filterChildren(el.children, el))
return
}
}
children = children.concat(el)
})
return children
}
// 动态路由遍历,验证是否具备权限
export function filterDynamicRoutes(routes) {
const res = []
routes.forEach(route => {
if (route.permissions) {
if (auth.hasPermiOr(route.permissions)) {
res.push(route)
}
} else if (route.roles) {
if (auth.hasRoleOr(route.roles)) {
res.push(route)
}
}
})
return res
}
export const loadView = (view) => {
let res;
for (const path in modules) {
const dir = path.split('views/')[1].split('.vue')[0];
if (dir === view) {
res = () => modules[path]();
}
}
return res;
}
export default usePermissionStore
================================================
FILE: front/src/store/modules/settings.js
================================================
import defaultSettings from '@/settings'
import { useDynamicTitle } from '@/utils/dynamicTitle'
const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings
const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
const useSettingsStore = defineStore(
'settings',
{
state: () => ({
title: '',
theme: storageSetting.theme || '#3F51B5',
sideTheme: storageSetting.sideTheme || sideTheme,
showSettings: showSettings,
topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav,
tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle
}),
actions: {
// 修改布局设置
changeSetting(data) {
const { key, value } = data
if (this.hasOwnProperty(key)) {
this[key] = value
}
},
// 设置网页标题
setTitle(title) {
this.title = title
useDynamicTitle();
}
}
})
export default useSettingsStore
================================================
FILE: front/src/store/modules/tagsView.js
================================================
const useTagsViewStore = defineStore(
'tags-view',
{
state: () => ({
visitedViews: [],
cachedViews: [],
iframeViews: []
}),
actions: {
addView(view) {
this.addVisitedView(view)
this.addCachedView(view)
},
addIframeView(view) {
if (this.iframeViews.some(v => v.path === view.path)) return
this.iframeViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
},
addVisitedView(view) {
if (this.visitedViews.some(v => v.path === view.path)) return
this.visitedViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
},
addCachedView(view) {
if (this.cachedViews.includes(view.name)) return
if (!view.meta.noCache) {
this.cachedViews.push(view.name)
}
},
delView(view) {
return new Promise(resolve => {
this.delVisitedView(view)
this.delCachedView(view)
resolve({
visitedViews: [...this.visitedViews],
cachedViews: [...this.cachedViews]
})
})
},
delVisitedView(view) {
return new Promise(resolve => {
for (const [i, v] of this.visitedViews.entries()) {
if (v.path === view.path) {
this.visitedViews.splice(i, 1)
break
}
}
this.iframeViews = this.iframeViews.filter(item => item.path !== view.path)
resolve([...this.visitedViews])
})
},
delIframeView(view) {
return new Promise(resolve => {
this.iframeViews = this.iframeViews.filter(item => item.path !== view.path)
resolve([...this.iframeViews])
})
},
delCachedView(view) {
return new Promise(resolve => {
const index = this.cachedViews.indexOf(view.name)
index > -1 && this.cachedViews.splice(index, 1)
resolve([...this.cachedViews])
})
},
delOthersViews(view) {
return new Promise(resolve => {
this.delOthersVisitedViews(view)
this.delOthersCachedViews(view)
resolve({
visitedViews: [...this.visitedViews],
cachedViews: [...this.cachedViews]
})
})
},
delOthersVisitedViews(view) {
return new Promise(resolve => {
this.visitedViews = this.visitedViews.filter(v => {
return v.meta.affix || v.path === view.path
})
this.iframeViews = this.iframeViews.filter(item => item.path === view.path)
resolve([...this.visitedViews])
})
},
delOthersCachedViews(view) {
return new Promise(resolve => {
const index = this.cachedViews.indexOf(view.name)
if (index > -1) {
this.cachedViews = this.cachedViews.slice(index, index + 1)
} else {
this.cachedViews = []
}
resolve([...this.cachedViews])
})
},
delAllViews(view) {
return new Promise(resolve => {
this.delAllVisitedViews(view)
this.delAllCachedViews(view)
resolve({
visitedViews: [...this.visitedViews],
cachedViews: [...this.cachedViews]
})
})
},
delAllVisitedViews(view) {
return new Promise(resolve => {
const affixTags = this.visitedViews.filter(tag => tag.meta.affix)
this.visitedViews = affixTags
this.iframeViews = []
resolve([...this.visitedViews])
})
},
delAllCachedViews(view) {
return new Promise(resolve => {
this.cachedViews = []
resolve([...this.cachedViews])
})
},
updateVisitedView(view) {
for (let v of this.visitedViews) {
if (v.path === view.path) {
v = Object.assign(v, view)
break
}
}
},
delRightTags(view) {
return new Promise(resolve => {
const index = this.visitedViews.findIndex(v => v.path === view.path)
if (index === -1) {
return
}
this.visitedViews = this.visitedViews.filter((item, idx) => {
if (idx <= index || (item.meta && item.meta.affix)) {
return true
}
const i = this.cachedViews.indexOf(item.name)
if (i > -1) {
this.cachedViews.splice(i, 1)
}
if(item.meta.link) {
const fi = this.iframeViews.findIndex(v => v.path === item.path)
this.iframeViews.splice(fi, 1)
}
return false
})
resolve([...this.visitedViews])
})
},
delLeftTags(view) {
return new Promise(resolve => {
const index = this.visitedViews.findIndex(v => v.path === view.path)
if (index === -1) {
return
}
this.visitedViews = this.visitedViews.filter((item, idx) => {
if (idx >= index || (item.meta && item.meta.affix)) {
return true
}
const i = this.cachedViews.indexOf(item.name)
if (i > -1) {
this.cachedViews.splice(i, 1)
}
if(item.meta.link) {
const fi = this.iframeViews.findIndex(v => v.path === item.path)
this.iframeViews.splice(fi, 1)
}
return false
})
resolve([...this.visitedViews])
})
}
}
})
export default useTagsViewStore
================================================
FILE: front/src/store/modules/user.js
================================================
import { login, logout, getInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import defAva from '@/assets/images/profile.jpg'
const useUserStore = defineStore(
'user',
{
state: () => ({
token: getToken(),
id: '',
name: '',
avatar: '',
roles: [],
permissions: []
}),
actions: {
// 登录
login(userInfo) {
const username = userInfo.username.trim()
const password = userInfo.password
const code = userInfo.code
const uuid = userInfo.uuid
return new Promise((resolve, reject) => {
login(username, password, code, uuid).then(res => {
setToken(res.token)
this.token = res.token
resolve()
}).catch(error => {
reject(error)
})
})
},
// 获取用户信息
getInfo() {
return new Promise((resolve, reject) => {
getInfo().then(res => {
const user = res.user
const avatar = (user.avatar == "" || user.avatar == null) ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
this.roles = res.roles
this.permissions = res.permissions
} else {
this.roles = ['ROLE_DEFAULT']
}
this.id = user.userId
this.name = user.userName
this.avatar = avatar
resolve(res)
}).catch(error => {
reject(error)
})
})
},
// 退出系统
logOut() {
return new Promise((resolve, reject) => {
logout(this.token).then(() => {
this.token = ''
this.roles = []
this.permissions = []
removeToken()
resolve()
}).catch(error => {
reject(error)
})
})
}
}
})
export default useUserStore
================================================
FILE: front/src/utils/auth.js
================================================
import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token'
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}
================================================
FILE: front/src/utils/dict.js
================================================
import useDictStore from '@/store/modules/dict'
import { getDicts } from '@/api/system/dict/data'
/**
* 获取字典数据
*/
export function useDict(...args) {
const res = ref({});
return (() => {
args.forEach((dictType, index) => {
res.value[dictType] = [];
const dicts = useDictStore().getDict(dictType);
if (dicts) {
res.value[dictType] = dicts;
} else {
getDicts(dictType).then(resp => {
res.value[dictType] = resp.data.map(p => ({ label: p.dictLabel, value: p.dictValue, elTagType: p.listClass, elTagClass: p.cssClass }))
useDictStore().setDict(dictType, res.value[dictType]);
})
}
})
return toRefs(res.value);
})()
}
================================================
FILE: front/src/utils/dynamicTitle.js
================================================
import store from '@/store'
import defaultSettings from '@/settings'
import useSettingsStore from '@/store/modules/settings'
/**
* 动态修改标题
*/
export function useDynamicTitle() {
const settingsStore = useSettingsStore();
if (settingsStore.dynamicTitle) {
document.title = settingsStore.title + ' - ' + defaultSettings.title;
} else {
document.title = defaultSettings.title;
}
}
================================================
FILE: front/src/utils/errorCode.js
================================================
export default {
'401': '认证失败,无法访问系统资源',
'403': '当前操作没有权限',
'404': '访问资源不存在',
'default': '系统未知错误,请反馈给管理员'
}
================================================
FILE: front/src/utils/index.js
================================================
import { parseTime } from './ruoyi'
/**
* 表格时间格式化
*/
export function formatDate(cellValue) {
if (cellValue == null || cellValue == "") return "";
var date = new Date(cellValue)
var year = date.getFullYear()
var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
}
/**
* @param {number} time
* @param {string} option
* @returns {string}
*/
export function formatTime(time, option) {
if (('' + time).length === 10) {
time = parseInt(time) * 1000
} else {
time = +time
}
const d = new Date(time)
const now = Date.now()
const diff = (now - d) / 1000
if (diff < 30) {
return '刚刚'
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + '分钟前'
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前'
} else if (diff < 3600 * 24 * 2) {
return '1天前'
}
if (option) {
return parseTime(time, option)
} else {
return (
d.getMonth() +
1 +
'月' +
d.getDate() +
'日' +
d.getHours() +
'时' +
d.getMinutes() +
'分'
)
}
}
/**
* @param {string} url
* @returns {Object}
*/
export function getQueryObject(url) {
url = url == null ? window.location.href : url
const search = url.substring(url.lastIndexOf('?') + 1)
const obj = {}
const reg = /([^?&=]+)=([^?&=]*)/g
search.replace(reg, (rs, $1, $2) => {
const name = decodeURIComponent($1)
let val = decodeURIComponent($2)
val = String(val)
obj[name] = val
return rs
})
return obj
}
/**
* @param {string} input value
* @returns {number} output value
*/
export function byteLength(str) {
// returns the byte length of an utf8 string
let s = str.length
for (var i = str.length - 1; i >= 0; i--) {
const code = str.charCodeAt(i)
if (code > 0x7f && code <= 0x7ff) s++
else if (code > 0x7ff && code <= 0xffff) s += 2
if (code >= 0xDC00 && code <= 0xDFFF) i--
}
return s
}
/**
* @param {Array} actual
* @returns {Array}
*/
export function cleanArray(actual) {
const newArray = []
for (let i = 0; i < actual.length; i++) {
if (actual[i]) {
newArray.push(actual[i])
}
}
return newArray
}
/**
* @param {Object} json
* @returns {Array}
*/
export function param(json) {
if (!json) return ''
return cleanArray(
Object.keys(json).map(key => {
if (json[key] === undefined) return ''
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
})
).join('&')
}
/**
* @param {string} url
* @returns {Object}
*/
export function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}
/**
* @param {string} val
* @returns {string}
*/
export function html2Text(val) {
const div = document.createElement('div')
div.innerHTML = val
return div.textContent || div.innerText
}
/**
* Merges two objects, giving the last one precedence
* @param {Object} target
* @param {(Object|Array)} source
* @returns {Object}
*/
export function objectMerge(target, source) {
if (typeof target !== 'object') {
target = {}
}
if (Array.isArray(source)) {
return source.slice()
}
Object.keys(source).forEach(property => {
const sourceProperty = source[property]
if (typeof sourceProperty === 'object') {
target[property] = objectMerge(target[property], sourceProperty)
} else {
target[property] = sourceProperty
}
})
return target
}
/**
* @param {HTMLElement} element
* @param {string} className
*/
export function toggleClass(element, className) {
if (!element || !className) {
return
}
let classString = element.className
const nameIndex = classString.indexOf(className)
if (nameIndex === -1) {
classString += '' + className
} else {
classString =
classString.substr(0, nameIndex) +
classString.substr(nameIndex + className.length)
}
element.className = classString
}
/**
* @param {string} type
* @returns {Date}
*/
export function getTime(type) {
if (type === 'start') {
return new Date().getTime() - 3600 * 1000 * 24 * 90
} else {
return new Date(new Date().toDateString())
}
}
/**
* @param {Function} func
* @param {number} wait
* @param {boolean} immediate
* @return {*}
*/
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}
return function(...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}
/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
* @param {Object} source
* @returns {Object}
*/
export function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}
/**
* @param {Array} arr
* @returns {Array}
*/
export function uniqueArr(arr) {
return Array.from(new Set(arr))
}
/**
* @returns {string}
*/
export function createUniqueString() {
const timestamp = +new Date() + ''
const randomNum = parseInt((1 + Math.random()) * 65536) + ''
return (+(randomNum + timestamp)).toString(32)
}
/**
* Check if an element has a class
* @param {HTMLElement} elm
* @param {string} cls
* @returns {boolean}
*/
export function hasClass(ele, cls) {
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
}
/**
* Add class to element
* @param {HTMLElement} elm
* @param {string} cls
*/
export function addClass(ele, cls) {
if (!hasClass(ele, cls)) ele.className += ' ' + cls
}
/**
* Remove class from element
* @param {HTMLElement} elm
* @param {string} cls
*/
export function removeClass(ele, cls) {
if (hasClass(ele, cls)) {
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
ele.className = ele.className.replace(reg, ' ')
}
}
export function makeMap(str, expectsLowerCase) {
const map = Object.create(null)
const list = str.split(',')
for (let i = 0; i < list.length; i++) {
map[list[i]] = true
}
return expectsLowerCase
? val => map[val.toLowerCase()]
: val => map[val]
}
export const exportDefault = 'export default '
export const beautifierConf = {
html: {
indent_size: '2',
indent_char: ' ',
max_preserve_newlines: '-1',
preserve_newlines: false,
keep_array_indentation: false,
break_chained_methods: false,
indent_scripts: 'separate',
brace_style: 'end-expand',
space_before_conditional: true,
unescape_strings: false,
jslint_happy: false,
end_with_newline: true,
wrap_line_length: '110',
indent_inner_html: true,
comma_first: false,
e4x: true,
indent_empty_lines: true
},
js: {
indent_size: '2',
indent_char: ' ',
max_preserve_newlines: '-1',
preserve_newlines: false,
keep_array_indentation: false,
break_chained_methods: false,
indent_scripts: 'normal',
brace_style: 'end-expand',
space_before_conditional: true,
unescape_strings: false,
jslint_happy: true,
end_with_newline: true,
wrap_line_length: '110',
indent_inner_html: true,
comma_first: false,
e4x: true,
indent_empty_lines: true
}
}
// 首字母大小
export function titleCase(str) {
return str.replace(/( |^)[a-z]/g, L => L.toUpperCase())
}
// 下划转驼峰
export function camelCase(str) {
return str.replace(/_[a-z]/g, str1 => str1.substr(-1).toUpperCase())
}
export function isNumberStr(str) {
return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
}
================================================
FILE: front/src/utils/jsencrypt.js
================================================
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
// 密钥对生成 http://web.chacuo.net/netrsakeypair
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
'UP8iWi1Qw0Y='
// 加密
export function encrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey) // 设置公钥
return encryptor.encrypt(txt) // 对数据进行加密
}
// 解密
export function decrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPrivateKey(privateKey) // 设置私钥
return encryptor.decrypt(txt) // 对数据进行解密
}
================================================
FILE: front/src/utils/permission.js
================================================
import useUserStore from '@/store/modules/user'
/**
* 字符权限校验
* @param {Array} value 校验值
* @returns {Boolean}
*/
export function checkPermi(value) {
if (value && value instanceof Array && value.length > 0) {
const permissions = useUserStore().permissions
const permissionDatas = value
const all_permission = "*:*:*";
const hasPermission = permissions.some(permission => {
return all_permission === permission || permissionDatas.includes(permission)
})
if (!hasPermission) {
return false
}
return true
} else {
console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`)
return false
}
}
/**
* 角色权限校验
* @param {Array} value 校验值
* @returns {Boolean}
*/
export function checkRole(value) {
if (value && value instanceof Array && value.length > 0) {
const roles = useUserStore().roles
const permissionRoles = value
const super_admin = "admin";
const hasRole = roles.some(role => {
return super_admin === role || permissionRoles.includes(role)
})
if (!hasRole) {
return false
}
return true
} else {
console.error(`need roles! Like checkRole="['admin','editor']"`)
return false
}
}
================================================
FILE: front/src/utils/request.js
================================================
import axios from 'axios'
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi'
import cache from '@/plugins/cache'
import { saveAs } from 'file-saver'
import useUserStore from '@/store/modules/user'
let downloadLoadingInstance;
// 是否显示重新登录
export let isRelogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: import.meta.env.VITE_APP_BASE_API,
// 超时
timeout: 10000
})
// request拦截器
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
}
const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
if (requestSize >= limitSize) {
console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。')
return config;
}
const sessionObj = cache.session.getJSON('sessionObj')
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj)
} else {
const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = '数据正在处理,请勿重复提交';
console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message))
} else {
cache.session.setJSON('sessionObj', requestObj)
}
}
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false;
useUserStore().logOut().then(() => {
location.href = '/index';
})
}).catch(() => {
isRelogin.show = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 422) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code !== 200) {
ElNotification.error({ title: msg })
return Promise.reject('error')
} else {
return Promise.resolve(res.data)
}
},
error => {
console.log('err' + error)
let { message } = error;
if (message == "Network Error") {
message = "后端接口连接异常";
} else if (message.includes("timeout")) {
message = "系统接口请求超时";
} else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error)
}
)
// 通用下载方法
export function download(url, params = {}, filename, config) {
downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
return service.get(url, {
responseType: 'blob',
...config,
params
}).then(async (data) => {
const isBlob = blobValidate(data);
if (isBlob) {
const blob = new Blob([data])
saveAs(blob, filename)
} else {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
ElMessage.error(errMsg);
}
downloadLoadingInstance.close();
}).catch((r) => {
console.error(r)
ElMessage.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close();
})
}
export default service
================================================
FILE: front/src/utils/ruoyi.js
================================================
import { isExternal } from "./validate"
/**
* 通用js方法封装处理
* Copyright (c) 2019 ruoyi
*/
// 日期格式化
export function parseTime(time, pattern) {
if (arguments.length === 0 || !time) {
return null
}
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
} else if (typeof time === 'string') {
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
// 表单重置
export function resetForm(refName) {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
}
// 添加日期范围
export function addDateRange(params, dateRange, propName) {
let search = params;
search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
dateRange = Array.isArray(dateRange) ? dateRange : [];
if (typeof (propName) === 'undefined') {
search.params['beginTime'] = dateRange[0];
search.params['endTime'] = dateRange[1];
} else {
search.params['begin' + propName] = dateRange[0];
search.params['end' + propName] = dateRange[1];
}
return search;
}
// 回显数据字典
export function selectDictLabel(datas, value) {
if (value === undefined) {
return "";
}
var actions = [];
Object.keys(datas).some((key) => {
if (datas[key].value == ('' + value)) {
actions.push(datas[key].label);
return true;
}
})
if (actions.length === 0) {
actions.push(value);
}
return actions.join('');
}
// 回显数据字典(字符串数组)
export function selectDictLabels(datas, value, separator) {
if (value === undefined || value.length ===0) {
return "";
}
if (Array.isArray(value)) {
value = value.join(",");
}
var actions = [];
var currentSeparator = undefined === separator ? "," : separator;
var temp = value.split(currentSeparator);
Object.keys(value.split(currentSeparator)).some((val) => {
var match = false;
Object.keys(datas).some((key) => {
if (datas[key].value == ('' + temp[val])) {
actions.push(datas[key].label + currentSeparator);
match = true;
}
})
if (!match) {
actions.push(temp[val] + currentSeparator);
}
})
return actions.join('').substring(0, actions.join('').length - 1);
}
// 字符串格式化(%s )
export function sprintf(str) {
var args = arguments, flag = true, i = 1;
str = str.replace(/%s/g, function () {
var arg = args[i++];
if (typeof arg === 'undefined') {
flag = false;
return '';
}
return arg;
});
return flag ? str : '';
}
// 转换字符串,undefined,null等转化为""
export function parseStrEmpty(str) {
if (!str || str == "undefined" || str == "null") {
return "";
}
return str;
}
// 数据合并
export function mergeRecursive(source, target) {
for (var p in target) {
try {
if (target[p].constructor == Object) {
source[p] = mergeRecursive(source[p], target[p]);
} else {
source[p] = target[p];
}
} catch (e) {
source[p] = target[p];
}
}
return source;
};
/**
* 构造树型结构数据
* @param {*} data 数据源
* @param {*} id id字段 默认 'id'
* @param {*} parentId 父节点字段 默认 'parentId'
* @param {*} children 孩子节点字段 默认 'children'
*/
export function handleTree(data, id, parentId, children) {
let config = {
id: id || 'id',
parentId: parentId || 'parentId',
childrenList: children || 'children'
};
var childrenListMap = {};
var nodeIds = {};
var tree = [];
for (let d of data) {
let parentId = d[config.parentId];
if (childrenListMap[parentId] == null) {
childrenListMap[parentId] = [];
}
nodeIds[d[config.id]] = d;
childrenListMap[parentId].push(d);
}
for (let d of data) {
let parentId = d[config.parentId];
if (nodeIds[parentId] == null) {
tree.push(d);
}
}
for (let t of tree) {
adaptToChildrenList(t);
}
function adaptToChildrenList(o) {
if (childrenListMap[o[config.id]] !== null) {
o[config.childrenList] = childrenListMap[o[config.id]];
}
if (o[config.childrenList]) {
for (let c of o[config.childrenList]) {
adaptToChildrenList(c);
}
}
}
return tree;
}
/**
* 参数处理
* @param {*} params 参数
*/
export function tansParams(params) {
let result = ''
for (const propName of Object.keys(params)) {
const value = params[propName];
var part = encodeURIComponent(propName) + "=";
if (value !== null && value !== "" && typeof (value) !== "undefined") {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
let params = propName + '[' + key + ']';
var subPart = encodeURIComponent(params) + "=";
result += subPart + encodeURIComponent(value[key]) + "&";
}
}
} else {
result += part + encodeURIComponent(value) + "&";
}
}
}
return result
}
// 返回项目路径
export function getNormalPath(p) {
if (p.length === 0 || !p || p == 'undefined') {
return p
};
let res = p.replace('//', '/')
if (res[res.length - 1] === '/') {
return res.slice(0, res.length - 1)
}
return res;
}
// 验证是否为blob格式
export function blobValidate(data) {
return data.type !== 'application/json'
}
//获取文件或者图片地址
export function getFilePath(path) {
return isExternal(path) ? path : import.meta.env.VITE_APP_BASE_API + path;
}
================================================
FILE: front/src/utils/scroll-to.js
================================================
Math.easeInOutQuad = function(t, b, c, d) {
t /= d / 2
if (t < 1) {
return c / 2 * t * t + b
}
t--
return -c / 2 * (t * (t - 2) - 1) + b
}
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
var requestAnimFrame = (function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
})()
/**
* Because it's so fucking difficult to detect the scrolling element, just move them all
* @param {number} amount
*/
function move(amount) {
document.documentElement.scrollTop = amount
document.body.parentNode.scrollTop = amount
document.body.scrollTop = amount
}
function position() {
return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
}
/**
* @param {number} to
* @param {number} duration
* @param {Function} callback
*/
export function scrollTo(to, duration, callback) {
const start = position()
const change = to - start
const increment = 20
let currentTime = 0
duration = (typeof (duration) === 'undefined') ? 500 : duration
var animateScroll = function() {
// increment the time
currentTime += increment
// find the value with the quadratic in-out easing function
var val = Math.easeInOutQuad(currentTime, start, change, duration)
// move the document.body
move(val)
// do the animation unless its over
if (currentTime < duration) {
requestAnimFrame(animateScroll)
} else {
if (callback && typeof (callback) === 'function') {
// the animation is done so lets callback
callback()
}
}
}
animateScroll()
}
================================================
FILE: front/src/utils/theme.js
================================================
// 处理主题样式
export function handleThemeStyle(theme) {
document.documentElement.style.setProperty('--el-color-primary', theme)
for (let i = 1; i <= 9; i++) {
document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, `${getLightColor(theme, i / 10)}`)
}
for (let i = 1; i <= 9; i++) {
document.documentElement.style.setProperty(`--el-color-primary-dark-${i}`, `${getDarkColor(theme, i / 10)}`)
}
}
// hex颜色转rgb颜色
export function hexToRgb(str) {
str = str.replace('#', '')
let hexs = str.match(/../g)
for (let i = 0; i < 3; i++) {
hexs[i] = parseInt(hexs[i], 16)
}
return hexs
}
// rgb颜色转Hex颜色
export function rgbToHex(r, g, b) {
let hexs = [r.toString(16), g.toString(16), b.toString(16)]
for (let i = 0; i < 3; i++) {
if (hexs[i].length == 1) {
hexs[i] = `0${hexs[i]}`
}
}
return `#${hexs.join('')}`
}
// 变浅颜色值
export function getLightColor(color, level) {
let rgb = hexToRgb(color)
for (let i = 0; i < 3; i++) {
rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i])
}
return rgbToHex(rgb[0], rgb[1], rgb[2])
}
// 变深颜色值
export function getDarkColor(color, level) {
let rgb = hexToRgb(color)
for (let i = 0; i < 3; i++) {
rgb[i] = Math.floor(rgb[i] * (1 - level))
}
return rgbToHex(rgb[0], rgb[1], rgb[2])
}
================================================
FILE: front/src/utils/validate.js
================================================
/**
* 判断url是否是http或https
* @param {string} path
* @returns {Boolean}
*/
export function isHttp(url) {
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
}
/**
* 判断path是否为外链
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
}
/**
* @param {string} url
* @returns {Boolean}
*/
export function validURL(url) {
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
return reg.test(url)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validLowerCase(str) {
const reg = /^[a-z]+$/
return reg.test(str)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUpperCase(str) {
const reg = /^[A-Z]+$/
return reg.test(str)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
}
/**
* @param {string} email
* @returns {Boolean}
*/
export function validEmail(email) {
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return reg.test(email)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function isString(str) {
if (typeof str === 'string' || str instanceof String) {
return true
}
return false
}
/**
* @param {Array} arg
* @returns {Boolean}
*/
export function isArray(arg) {
if (typeof Array.isArray === 'undefined') {
return Object.prototype.toString.call(arg) === '[object Array]'
}
return Array.isArray(arg)
}
================================================
FILE: front/src/views/error/401.vue
================================================
返回
401错误!
您没有访问权限!
对不起,您没有访问权限,请不要进行非法操作!您可以返回主页面
================================================
FILE: front/src/views/error/404.vue
================================================
404错误!
{{ message }}
对不起,您正在寻找的页面不存在。尝试检查URL的错误,然后按浏览器上的刷新按钮或尝试在我们的应用程序中找到其他内容。
返回首页
================================================
FILE: front/src/views/index.vue
================================================
Carole-admin后台管理框架
一款Nestjs+Prisma+Vue+Vite前后端分离的后台框架,
前端基于若依 。
查看文档
前端采用Vue3、Element-Plus、Vite。
后端采用Nest、Prisma、Redis & Jwt。
权限认证使用Jwt,支持多终端认证系统。
支持加载动态权限菜单,多方式轻松权限控制。
支持接口限流
高效率开发,使用代码生成器可以一键生成前后端代码。
当前版本: v{{ version }}
¥免费开源
github
技术选型
后端技术
Node
Nestjs
JWT
Mysql
Prisma
Redis
...
前端技术
Vue3
Vuex
Element-plus
Axios
Sass
Quill
...
联系信息
================================================
FILE: front/src/views/login.vue
================================================
Carole后台管理系统
记住密码
登 录
登 录 中...
================================================
FILE: front/src/views/monitor/cache/index.vue
================================================
基本信息
Redis版本
{{ cache.info.redis_version }}
运行模式
{{ cache.info.redis_mode == "standalone" ? "单机" : "集群" }}
端口
{{ cache.info.tcp_port }}
客户端数
{{ cache.info.connected_clients }}
运行时间(天)
{{ cache.info.uptime_in_days }}
使用内存
{{ cache.info.used_memory_human }}
使用CPU
{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}
内存配置
{{ cache.info.maxmemory_human }}
AOF是否开启
{{ cache.info.aof_enabled == "0" ? "否" : "是" }}
RDB是否成功
{{ cache.info.rdb_last_bgsave_status }}
Key数量
{{ cache.dbSize }}
网络入口/出口
{{ cache.info.instantaneous_input_kbps }}kps/{{cache.info.instantaneous_output_kbps}}kps
命令统计
内存信息
================================================
FILE: front/src/views/monitor/cache/list.vue
================================================
缓存列表
键名列表
缓存内容
清理全部
================================================
FILE: front/src/views/monitor/logininfor/index.vue
================================================
搜索
重置
删除
清空
导出
{{ parseTime(scope.row.loginTime) }}
================================================
FILE: front/src/views/monitor/online/index.vue
================================================
搜索
重置
批量强退
{{ (pageNum - 1) * pageSize + scope.$index + 1 }}
{{ parseTime(scope.row.loginTime) }}
强退
================================================
FILE: front/src/views/monitor/server/index.vue
================================================
CPU
属性
值
核心数
{{ server.cpu.cpuNum }}
用户使用率
{{ server.cpu.used }}%
系统使用率
{{ server.cpu.sys }}%
当前空闲率
{{ server.cpu.free }}%
内存
属性
内存
项目
总内存
{{ server.mem.total }}G
{{ server.project.total }}M
已用内存
{{ server.mem.used}}G
{{ server.project.used}}M
剩余内存
{{ server.mem.free }}G
{{ server.project.free }}M
使用率
{{ server.mem.usage }}%
{{ server.project.usage }}%
服务器信息
服务器名称
{{ server.sys.computerName }}
操作系统
{{ server.sys.osName }}
服务器IP
{{ server.sys.computerIp }}
系统架构
{{ server.sys.osArch }}
NodeJs信息
Node名称
{{ server.project.name }}
Node版本
{{ server.project.version }}
启动时间
{{ server.project.startTime }}
运行时长
{{ server.project.runTime }}
安装路径
{{ server.project.home }}
项目路径
{{ server.sys.userDir }}
运行参数
{{ server.project.inputArgs }}
磁盘状态
盘符路径
文件系统
盘符类型
总大小
可用大小
已用大小
已用百分比
{{ sysFile.dirName }}
{{ sysFile.sysTypeName }}
{{ sysFile.typeName }}
{{ sysFile.total }}
{{ sysFile.free }}
{{ sysFile.used }}
{{ sysFile.usage }}%
================================================
FILE: front/src/views/redirect/index.vue
================================================
================================================
FILE: front/src/views/system/config/edit.vue
================================================
================================================
FILE: front/src/views/system/config/index.vue
================================================
搜索
重置
新增
修改
删除
导出
刷新缓存
{{ parseTime(scope.row.createTime) }}
修改
删除
{{ dict.label }}
================================================
FILE: front/src/views/system/dept/index.vue
================================================
搜索
重置
新增
展开/折叠
{{ parseTime(scope.row.createTime) }}
修改
新增
删除
{{ dict.label }}
================================================
FILE: front/src/views/system/dict/data.vue
================================================
搜索
重置
新增
修改
删除
导出
关闭
{{ scope.row.dictLabel }}
{{ scope.row.dictLabel }}
{{ parseTime(scope.row.createTime) }}
修改
删除
{{ dict.label }}
================================================
FILE: front/src/views/system/dict/index.vue
================================================
搜索
重置
新增
修改
删除
导出
刷新缓存
{{ scope.row.dictType }}
{{ parseTime(scope.row.createTime) }}
修改
删除
{{ dict.label }}
================================================
FILE: front/src/views/system/menu/index.vue
================================================
搜索
重置
新增
展开/折叠
{{ parseTime(scope.row.createTime) }}
修改
新增
删除
目录
菜单
按钮
是否外链
是
否
路由地址
组件路径
权限字符
路由参数
是否缓存
缓存
不缓存
显示状态
{{ dict.label }}
菜单状态
{{ dict.label }}
================================================
FILE: front/src/views/system/notice/index.vue
================================================
搜索
重置
新增
修改
删除
{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}
修改
删除
{{ dict.label }}
================================================
FILE: front/src/views/system/post/index.vue
================================================
搜索
重置
新增
修改
删除
导出
{{ parseTime(scope.row.createTime) }}
修改
删除
{{ dict.label }}
================================================
FILE: front/src/views/system/role/authUser.vue
================================================
搜索
重置
添加用户
批量取消授权
关闭
{{ parseTime(scope.row.createTime) }}
取消授权
================================================
FILE: front/src/views/system/role/index.vue
================================================
搜索
重置
新增
修改
删除
导出
{{ parseTime(scope.row.createTime) }}
权限字符
{{ dict.label }}
展开/折叠
全选/全不选
父子联动
展开/折叠
全选/全不选
父子联动
================================================
FILE: front/src/views/system/role/selectUser.vue
================================================
搜索
重置
{{ parseTime(scope.row.createTime) }}
================================================
FILE: front/src/views/system/user/authRole.vue
================================================
{{ (pageNum - 1) * pageSize + scope.$index + 1 }}
{{ parseTime(scope.row.createTime) }}
提交
返回
================================================
FILE: front/src/views/system/user/index.vue
================================================
搜索
重置
新增
修改
删除
导出
{{ parseTime(scope.row.createTime) }}
{{ dict.label }}
================================================
FILE: front/src/views/system/user/profile/index.vue
================================================
个人信息
用户名称
{{ state.user.userName }}
手机号码
{{ state.user.phonenumber }}
用户邮箱
{{ state.user.email }}
所属部门
{{ state.user.dept.deptName }} / {{ state.postGroup }}
所属角色
{{ state.roleGroup }}
创建日期
{{ state.user.createTime }}
基本资料
================================================
FILE: front/src/views/system/user/profile/resetPwd.vue
================================================
保存
关闭
================================================
FILE: front/src/views/system/user/profile/userAvatar.vue
================================================
选择
提 交
================================================
FILE: front/src/views/system/user/profile/userInfo.vue
================================================
男
女
保存
关闭
================================================
FILE: front/src/views/tool/gen/basicInfoForm.vue
================================================
================================================
FILE: front/src/views/tool/gen/editTable.vue
================================================
{{ dict.dictName }}
{{ dict.dictType }}
提交
返回
================================================
FILE: front/src/views/tool/gen/excuteSql.vue
================================================
================================================
FILE: front/src/views/tool/gen/genInfoForm.vue
================================================
生成模板
前端类型
生成模块路径
子系统名
生成业务名
生成功能名
生成代码方式
zip压缩包
上级菜单
自定义路径
最近路径快速选择
恢复默认的生成基础路径
树编码字段
树父编码字段
树名称字段
关联子表的表名
子表关联的外键名
================================================
FILE: front/src/views/tool/gen/importTable.vue
================================================
搜索
重置
================================================
FILE: front/src/views/tool/gen/index.vue
================================================
搜索
重置
生成
执行sql
导入
修改
删除
{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}
复制
================================================
FILE: front/src/views/tool/swagger/index.vue
================================================
================================================
FILE: front/vite/plugins/auto-import.js
================================================
import autoImport from 'unplugin-auto-import/vite'
export default function createAutoImport() {
return autoImport({
imports: [
'vue',
'vue-router',
'pinia'
],
dts: false
})
}
================================================
FILE: front/vite/plugins/compression.js
================================================
import compression from 'vite-plugin-compression'
export default function createCompression(env) {
const { VITE_BUILD_COMPRESS } = env
const plugin = []
if (VITE_BUILD_COMPRESS) {
const compressList = VITE_BUILD_COMPRESS.split(',')
if (compressList.includes('gzip')) {
// http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
plugin.push(
compression({
ext: '.gz',
deleteOriginFile: false
})
)
}
if (compressList.includes('brotli')) {
plugin.push(
compression({
ext: '.br',
algorithm: 'brotliCompress',
deleteOriginFile: false
})
)
}
}
return plugin
}
================================================
FILE: front/vite/plugins/index.js
================================================
import vue from '@vitejs/plugin-vue'
import createAutoImport from './auto-import'
import createSvgIcon from './svg-icon'
import createCompression from './compression'
import createSetupExtend from './setup-extend'
export default function createVitePlugins(viteEnv, isBuild = false) {
const vitePlugins = [vue()]
vitePlugins.push(createAutoImport())
vitePlugins.push(createSetupExtend())
vitePlugins.push(createSvgIcon(isBuild))
isBuild && vitePlugins.push(...createCompression(viteEnv))
return vitePlugins
}
================================================
FILE: front/vite/plugins/setup-extend.js
================================================
import setupExtend from 'unplugin-vue-setup-extend-plus/vite'
export default function createSetupExtend() {
return setupExtend({})
}
================================================
FILE: front/vite/plugins/svg-icon.js
================================================
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
export default function createSvgIcon(isBuild) {
return createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons/svg')],
symbolId: 'icon-[dir]-[name]',
svgoOptions: isBuild
})
}
================================================
FILE: front/vite.config.js
================================================
import { defineConfig, loadEnv } from 'vite'
import path from 'path'
import createVitePlugins from './vite/plugins'
// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {
const env = loadEnv(mode, process.cwd())
const { VITE_APP_ENV } = env
return {
// 部署生产环境和开发环境下的URL。
// 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
base: VITE_APP_ENV === 'production' ? '/' : '/',
plugins: createVitePlugins(env, command === 'build'),
resolve: {
// https://cn.vitejs.dev/config/#resolve-alias
alias: {
// 设置路径
'~': path.resolve(__dirname, './'),
// 设置别名
'@': path.resolve(__dirname, './src')
},
// https://cn.vitejs.dev/config/#resolve-extensions
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
},
// // vite 相关配置
server: {
port: 3001,
host: true,
open: true,
proxy: {
// https://cn.vitejs.dev/config/#server-proxy
'/dev': {
target: 'http://localhost:3000/v1',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev/, '')
}
}
},
//fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file
css: {
postcss: {
plugins: [
{
postcssPlugin: 'internal:charset-removal',
AtRule: {
charset: (atRule) => {
if (atRule.name === 'charset') {
atRule.remove();
}
}
}
}
]
}
}
}
})
================================================
FILE: front/vite.config.js.timestamp-1718102364365-ed912c0771327.mjs
================================================
// vite.config.js
import { defineConfig, loadEnv } from "file:///F:/carole-admin/front/node_modules/vite/dist/node/index.js";
import path2 from "path";
// vite/plugins/index.js
import vue from "file:///F:/carole-admin/front/node_modules/@vitejs/plugin-vue/dist/index.mjs";
// vite/plugins/auto-import.js
import autoImport from "file:///F:/carole-admin/front/node_modules/unplugin-auto-import/dist/vite.js";
function createAutoImport() {
return autoImport({
imports: [
"vue",
"vue-router",
"pinia"
],
dts: false
});
}
// vite/plugins/svg-icon.js
import { createSvgIconsPlugin } from "file:///F:/carole-admin/front/node_modules/vite-plugin-svg-icons/dist/index.mjs";
import path from "path";
function createSvgIcon(isBuild) {
return createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), "src/assets/icons/svg")],
symbolId: "icon-[dir]-[name]",
svgoOptions: isBuild
});
}
// vite/plugins/compression.js
import compression from "file:///F:/carole-admin/front/node_modules/vite-plugin-compression/dist/index.mjs";
function createCompression(env) {
const { VITE_BUILD_COMPRESS } = env;
const plugin = [];
if (VITE_BUILD_COMPRESS) {
const compressList = VITE_BUILD_COMPRESS.split(",");
if (compressList.includes("gzip")) {
plugin.push(
compression({
ext: ".gz",
deleteOriginFile: false
})
);
}
if (compressList.includes("brotli")) {
plugin.push(
compression({
ext: ".br",
algorithm: "brotliCompress",
deleteOriginFile: false
})
);
}
}
return plugin;
}
// vite/plugins/setup-extend.js
import setupExtend from "file:///F:/carole-admin/front/node_modules/unplugin-vue-setup-extend-plus/dist/vite.js";
function createSetupExtend() {
return setupExtend({});
}
// vite/plugins/index.js
function createVitePlugins(viteEnv, isBuild = false) {
const vitePlugins = [vue()];
vitePlugins.push(createAutoImport());
vitePlugins.push(createSetupExtend());
vitePlugins.push(createSvgIcon(isBuild));
isBuild && vitePlugins.push(...createCompression(viteEnv));
return vitePlugins;
}
// vite.config.js
var __vite_injected_original_dirname = "F:\\carole-admin\\front";
var vite_config_default = defineConfig(({ mode, command }) => {
const env = loadEnv(mode, process.cwd());
const { VITE_APP_ENV } = env;
return {
// 部署生产环境和开发环境下的URL。
// 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
base: VITE_APP_ENV === "production" ? "/" : "/",
plugins: createVitePlugins(env, command === "build"),
resolve: {
// https://cn.vitejs.dev/config/#resolve-alias
alias: {
// 设置路径
"~": path2.resolve(__vite_injected_original_dirname, "./"),
// 设置别名
"@": path2.resolve(__vite_injected_original_dirname, "./src")
},
// https://cn.vitejs.dev/config/#resolve-extensions
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"]
},
// // vite 相关配置
server: {
port: 3001,
host: true,
open: true,
proxy: {
// https://cn.vitejs.dev/config/#server-proxy
"/dev": {
target: "http://localhost:3000/v1",
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev/, "")
}
}
},
//fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file
css: {
postcss: {
plugins: [
{
postcssPlugin: "internal:charset-removal",
AtRule: {
charset: (atRule) => {
if (atRule.name === "charset") {
atRule.remove();
}
}
}
}
]
}
}
};
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiLCAidml0ZS9wbHVnaW5zL2luZGV4LmpzIiwgInZpdGUvcGx1Z2lucy9hdXRvLWltcG9ydC5qcyIsICJ2aXRlL3BsdWdpbnMvc3ZnLWljb24uanMiLCAidml0ZS9wbHVnaW5zL2NvbXByZXNzaW9uLmpzIiwgInZpdGUvcGx1Z2lucy9zZXR1cC1leHRlbmQuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJGOlxcXFxjYXJvbGUtYWRtaW5cXFxcZnJvbnRcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkY6XFxcXGNhcm9sZS1hZG1pblxcXFxmcm9udFxcXFx2aXRlLmNvbmZpZy5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRjovY2Fyb2xlLWFkbWluL2Zyb250L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnLCBsb2FkRW52IH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHBhdGggZnJvbSAncGF0aCdcclxuaW1wb3J0IGNyZWF0ZVZpdGVQbHVnaW5zIGZyb20gJy4vdml0ZS9wbHVnaW5zJ1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKCh7IG1vZGUsIGNvbW1hbmQgfSkgPT4ge1xyXG4gIGNvbnN0IGVudiA9IGxvYWRFbnYobW9kZSwgcHJvY2Vzcy5jd2QoKSlcclxuICBjb25zdCB7IFZJVEVfQVBQX0VOViB9ID0gZW52XHJcbiAgcmV0dXJuIHtcclxuICAgIC8vIFx1OTBFOFx1N0Y3Mlx1NzUxRlx1NEVBN1x1NzNBRlx1NTg4M1x1NTQ4Q1x1NUYwMFx1NTNEMVx1NzNBRlx1NTg4M1x1NEUwQlx1NzY4NFVSTFx1MzAwMlxyXG4gICAgLy8gXHU5RUQ4XHU4QkE0XHU2MEM1XHU1MUI1XHU0RTBCXHVGRjBDdml0ZSBcdTRGMUFcdTUwNDdcdThCQkVcdTRGNjBcdTc2ODRcdTVFOTRcdTc1MjhcdTY2MkZcdTg4QUJcdTkwRThcdTdGNzJcdTU3MjhcdTRFMDBcdTRFMkFcdTU3REZcdTU0MERcdTc2ODRcdTY4MzlcdThERUZcdTVGODRcdTRFMEFcclxuICAgIC8vIFx1NEY4Qlx1NTk4MiBodHRwczovL3d3dy5ydW95aS52aXAvXHUzMDAyXHU1OTgyXHU2NzlDXHU1RTk0XHU3NTI4XHU4OEFCXHU5MEU4XHU3RjcyXHU1NzI4XHU0RTAwXHU0RTJBXHU1QjUwXHU4REVGXHU1Rjg0XHU0RTBBXHVGRjBDXHU0RjYwXHU1QzMxXHU5NzAwXHU4OTgxXHU3NTI4XHU4RkQ5XHU0RTJBXHU5MDA5XHU5ODc5XHU2MzA3XHU1QjlBXHU4RkQ5XHU0RTJBXHU1QjUwXHU4REVGXHU1Rjg0XHUzMDAyXHU0RjhCXHU1OTgyXHVGRjBDXHU1OTgyXHU2NzlDXHU0RjYwXHU3Njg0XHU1RTk0XHU3NTI4XHU4OEFCXHU5MEU4XHU3RjcyXHU1NzI4IGh0dHBzOi8vd3d3LnJ1b3lpLnZpcC9hZG1pbi9cdUZGMENcdTUyMTlcdThCQkVcdTdGNkUgYmFzZVVybCBcdTRFM0EgL2FkbWluL1x1MzAwMlxyXG4gICAgYmFzZTogVklURV9BUFBfRU5WID09PSAncHJvZHVjdGlvbicgPyAnLycgOiAnLycsXHJcbiAgICBwbHVnaW5zOiBjcmVhdGVWaXRlUGx1Z2lucyhlbnYsIGNvbW1hbmQgPT09ICdidWlsZCcpLFxyXG4gICAgcmVzb2x2ZToge1xyXG4gICAgICAvLyBodHRwczovL2NuLnZpdGVqcy5kZXYvY29uZmlnLyNyZXNvbHZlLWFsaWFzXHJcbiAgICAgIGFsaWFzOiB7XHJcbiAgICAgICAgLy8gXHU4QkJFXHU3RjZFXHU4REVGXHU1Rjg0XHJcbiAgICAgICAgJ34nOiBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi8nKSxcclxuICAgICAgICAvLyBcdThCQkVcdTdGNkVcdTUyMkJcdTU0MERcclxuICAgICAgICAnQCc6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuL3NyYycpXHJcbiAgICAgIH0sXHJcbiAgICAgIC8vIGh0dHBzOi8vY24udml0ZWpzLmRldi9jb25maWcvI3Jlc29sdmUtZXh0ZW5zaW9uc1xyXG4gICAgICBleHRlbnNpb25zOiBbJy5tanMnLCAnLmpzJywgJy50cycsICcuanN4JywgJy50c3gnLCAnLmpzb24nLCAnLnZ1ZSddXHJcbiAgICB9LFxyXG4gICAgLy8gLy8gdml0ZSBcdTc2RjhcdTUxNzNcdTkxNERcdTdGNkVcclxuICAgIHNlcnZlcjoge1xyXG4gICAgICBwb3J0OiAzMDAxLFxyXG4gICAgICBob3N0OiB0cnVlLFxyXG4gICAgICBvcGVuOiB0cnVlLFxyXG4gICAgICBwcm94eToge1xyXG4gICAgICAgIC8vIGh0dHBzOi8vY24udml0ZWpzLmRldi9jb25maWcvI3NlcnZlci1wcm94eVxyXG4gICAgICAgICcvZGV2Jzoge1xyXG4gICAgICAgICAgdGFyZ2V0OiAnaHR0cDovL2xvY2FsaG9zdDozMDAwL3YxJyxcclxuICAgICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcclxuICAgICAgICAgIHJld3JpdGU6IChwKSA9PiBwLnJlcGxhY2UoL15cXC9kZXYvLCAnJylcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0sXHJcbiAgICAvL2ZpeDplcnJvcjpzdGRpbj46NzM1NjoxOiB3YXJuaW5nOiBcIkBjaGFyc2V0XCIgbXVzdCBiZSB0aGUgZmlyc3QgcnVsZSBpbiB0aGUgZmlsZVxyXG4gICAgY3NzOiB7XHJcbiAgICAgIHBvc3Rjc3M6IHtcclxuICAgICAgICBwbHVnaW5zOiBbXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIHBvc3Rjc3NQbHVnaW46ICdpbnRlcm5hbDpjaGFyc2V0LXJlbW92YWwnLFxyXG4gICAgICAgICAgICBBdFJ1bGU6IHtcclxuICAgICAgICAgICAgICBjaGFyc2V0OiAoYXRSdWxlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAoYXRSdWxlLm5hbWUgPT09ICdjaGFyc2V0Jykge1xyXG4gICAgICAgICAgICAgICAgICBhdFJ1bGUucmVtb3ZlKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgXVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59KVxyXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIkY6XFxcXGNhcm9sZS1hZG1pblxcXFxmcm9udFxcXFx2aXRlXFxcXHBsdWdpbnNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkY6XFxcXGNhcm9sZS1hZG1pblxcXFxmcm9udFxcXFx2aXRlXFxcXHBsdWdpbnNcXFxcaW5kZXguanNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0Y6L2Nhcm9sZS1hZG1pbi9mcm9udC92aXRlL3BsdWdpbnMvaW5kZXguanNcIjtpbXBvcnQgdnVlIGZyb20gJ0B2aXRlanMvcGx1Z2luLXZ1ZSdcclxuXHJcbmltcG9ydCBjcmVhdGVBdXRvSW1wb3J0IGZyb20gJy4vYXV0by1pbXBvcnQnXHJcbmltcG9ydCBjcmVhdGVTdmdJY29uIGZyb20gJy4vc3ZnLWljb24nXHJcbmltcG9ydCBjcmVhdGVDb21wcmVzc2lvbiBmcm9tICcuL2NvbXByZXNzaW9uJ1xyXG5pbXBvcnQgY3JlYXRlU2V0dXBFeHRlbmQgZnJvbSAnLi9zZXR1cC1leHRlbmQnXHJcblxyXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBjcmVhdGVWaXRlUGx1Z2lucyh2aXRlRW52LCBpc0J1aWxkID0gZmFsc2UpIHtcclxuICAgIGNvbnN0IHZpdGVQbHVnaW5zID0gW3Z1ZSgpXVxyXG4gICAgdml0ZVBsdWdpbnMucHVzaChjcmVhdGVBdXRvSW1wb3J0KCkpXHJcblx0dml0ZVBsdWdpbnMucHVzaChjcmVhdGVTZXR1cEV4dGVuZCgpKVxyXG4gICAgdml0ZVBsdWdpbnMucHVzaChjcmVhdGVTdmdJY29uKGlzQnVpbGQpKVxyXG5cdGlzQnVpbGQgJiYgdml0ZVBsdWdpbnMucHVzaCguLi5jcmVhdGVDb21wcmVzc2lvbih2aXRlRW52KSlcclxuICAgIHJldHVybiB2aXRlUGx1Z2luc1xyXG59XHJcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiRjpcXFxcY2Fyb2xlLWFkbWluXFxcXGZyb250XFxcXHZpdGVcXFxccGx1Z2luc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiRjpcXFxcY2Fyb2xlLWFkbWluXFxcXGZyb250XFxcXHZpdGVcXFxccGx1Z2luc1xcXFxhdXRvLWltcG9ydC5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRjovY2Fyb2xlLWFkbWluL2Zyb250L3ZpdGUvcGx1Z2lucy9hdXRvLWltcG9ydC5qc1wiO2ltcG9ydCBhdXRvSW1wb3J0IGZyb20gJ3VucGx1Z2luLWF1dG8taW1wb3J0L3ZpdGUnXHJcblxyXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBjcmVhdGVBdXRvSW1wb3J0KCkge1xyXG4gICAgcmV0dXJuIGF1dG9JbXBvcnQoe1xyXG4gICAgICAgIGltcG9ydHM6IFtcclxuICAgICAgICAgICAgJ3Z1ZScsXHJcbiAgICAgICAgICAgICd2dWUtcm91dGVyJyxcclxuICAgICAgICAgICAgJ3BpbmlhJ1xyXG4gICAgICAgIF0sXHJcbiAgICAgICAgZHRzOiBmYWxzZVxyXG4gICAgfSlcclxufVxyXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIkY6XFxcXGNhcm9sZS1hZG1pblxcXFxmcm9udFxcXFx2aXRlXFxcXHBsdWdpbnNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkY6XFxcXGNhcm9sZS1hZG1pblxcXFxmcm9udFxcXFx2aXRlXFxcXHBsdWdpbnNcXFxcc3ZnLWljb24uanNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0Y6L2Nhcm9sZS1hZG1pbi9mcm9udC92aXRlL3BsdWdpbnMvc3ZnLWljb24uanNcIjtpbXBvcnQgeyBjcmVhdGVTdmdJY29uc1BsdWdpbiB9IGZyb20gJ3ZpdGUtcGx1Z2luLXN2Zy1pY29ucydcclxuaW1wb3J0IHBhdGggZnJvbSAncGF0aCdcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGNyZWF0ZVN2Z0ljb24oaXNCdWlsZCkge1xyXG4gICAgcmV0dXJuIGNyZWF0ZVN2Z0ljb25zUGx1Z2luKHtcclxuXHRcdGljb25EaXJzOiBbcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksICdzcmMvYXNzZXRzL2ljb25zL3N2ZycpXSxcclxuICAgICAgICBzeW1ib2xJZDogJ2ljb24tW2Rpcl0tW25hbWVdJyxcclxuICAgICAgICBzdmdvT3B0aW9uczogaXNCdWlsZFxyXG4gICAgfSlcclxufVxyXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIkY6XFxcXGNhcm9sZS1hZG1pblxcXFxmcm9udFxcXFx2aXRlXFxcXHBsdWdpbnNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkY6XFxcXGNhcm9sZS1hZG1pblxcXFxmcm9udFxcXFx2aXRlXFxcXHBsdWdpbnNcXFxcY29tcHJlc3Npb24uanNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0Y6L2Nhcm9sZS1hZG1pbi9mcm9udC92aXRlL3BsdWdpbnMvY29tcHJlc3Npb24uanNcIjtpbXBvcnQgY29tcHJlc3Npb24gZnJvbSAndml0ZS1wbHVnaW4tY29tcHJlc3Npb24nXHJcblxyXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBjcmVhdGVDb21wcmVzc2lvbihlbnYpIHtcclxuICAgIGNvbnN0IHsgVklURV9CVUlMRF9DT01QUkVTUyB9ID0gZW52XHJcbiAgICBjb25zdCBwbHVnaW4gPSBbXVxyXG4gICAgaWYgKFZJVEVfQlVJTERfQ09NUFJFU1MpIHtcclxuICAgICAgICBjb25zdCBjb21wcmVzc0xpc3QgPSBWSVRFX0JVSUxEX0NPTVBSRVNTLnNwbGl0KCcsJylcclxuICAgICAgICBpZiAoY29tcHJlc3NMaXN0LmluY2x1ZGVzKCdnemlwJykpIHtcclxuICAgICAgICAgICAgLy8gaHR0cDovL2RvYy5ydW95aS52aXAvcnVveWktdnVlL290aGVyL2ZhcS5odG1sI1x1NEY3Rlx1NzUyOGd6aXBcdTg5RTNcdTUzOEJcdTdGMjlcdTk3NTlcdTYwMDFcdTY1ODdcdTRFRjZcclxuICAgICAgICAgICAgcGx1Z2luLnB1c2goXHJcbiAgICAgICAgICAgICAgICBjb21wcmVzc2lvbih7XHJcbiAgICAgICAgICAgICAgICAgICAgZXh0OiAnLmd6JyxcclxuICAgICAgICAgICAgICAgICAgICBkZWxldGVPcmlnaW5GaWxlOiBmYWxzZVxyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoY29tcHJlc3NMaXN0LmluY2x1ZGVzKCdicm90bGknKSkge1xyXG4gICAgICAgICAgICBwbHVnaW4ucHVzaChcclxuICAgICAgICAgICAgICAgIGNvbXByZXNzaW9uKHtcclxuICAgICAgICAgICAgICAgICAgICBleHQ6ICcuYnInLFxyXG4gICAgICAgICAgICAgICAgICAgIGFsZ29yaXRobTogJ2Jyb3RsaUNvbXByZXNzJyxcclxuICAgICAgICAgICAgICAgICAgICBkZWxldGVPcmlnaW5GaWxlOiBmYWxzZVxyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBwbHVnaW5cclxufVxyXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIkY6XFxcXGNhcm9sZS1hZG1pblxcXFxmcm9udFxcXFx2aXRlXFxcXHBsdWdpbnNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkY6XFxcXGNhcm9sZS1hZG1pblxcXFxmcm9udFxcXFx2aXRlXFxcXHBsdWdpbnNcXFxcc2V0dXAtZXh0ZW5kLmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9GOi9jYXJvbGUtYWRtaW4vZnJvbnQvdml0ZS9wbHVnaW5zL3NldHVwLWV4dGVuZC5qc1wiO2ltcG9ydCBzZXR1cEV4dGVuZCBmcm9tICd1bnBsdWdpbi12dWUtc2V0dXAtZXh0ZW5kLXBsdXMvdml0ZSdcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGNyZWF0ZVNldHVwRXh0ZW5kKCkge1xyXG4gICAgcmV0dXJuIHNldHVwRXh0ZW5kKHt9KVxyXG59XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBdVAsU0FBUyxjQUFjLGVBQWU7QUFDN1IsT0FBT0EsV0FBVTs7O0FDRHFRLE9BQU8sU0FBUzs7O0FDQUosT0FBTyxnQkFBZ0I7QUFFMVMsU0FBUixtQkFBb0M7QUFDdkMsU0FBTyxXQUFXO0FBQUEsSUFDZCxTQUFTO0FBQUEsTUFDTDtBQUFBLE1BQ0E7QUFBQSxNQUNBO0FBQUEsSUFDSjtBQUFBLElBQ0EsS0FBSztBQUFBLEVBQ1QsQ0FBQztBQUNMOzs7QUNYNFIsU0FBUyw0QkFBNEI7QUFDalUsT0FBTyxVQUFVO0FBRUYsU0FBUixjQUErQixTQUFTO0FBQzNDLFNBQU8scUJBQXFCO0FBQUEsSUFDOUIsVUFBVSxDQUFDLEtBQUssUUFBUSxRQUFRLElBQUksR0FBRyxzQkFBc0IsQ0FBQztBQUFBLElBQ3hELFVBQVU7QUFBQSxJQUNWLGFBQWE7QUFBQSxFQUNqQixDQUFDO0FBQ0w7OztBQ1RrUyxPQUFPLGlCQUFpQjtBQUUzUyxTQUFSLGtCQUFtQyxLQUFLO0FBQzNDLFFBQU0sRUFBRSxvQkFBb0IsSUFBSTtBQUNoQyxRQUFNLFNBQVMsQ0FBQztBQUNoQixNQUFJLHFCQUFxQjtBQUNyQixVQUFNLGVBQWUsb0JBQW9CLE1BQU0sR0FBRztBQUNsRCxRQUFJLGFBQWEsU0FBUyxNQUFNLEdBQUc7QUFFL0IsYUFBTztBQUFBLFFBQ0gsWUFBWTtBQUFBLFVBQ1IsS0FBSztBQUFBLFVBQ0wsa0JBQWtCO0FBQUEsUUFDdEIsQ0FBQztBQUFBLE1BQ0w7QUFBQSxJQUNKO0FBQ0EsUUFBSSxhQUFhLFNBQVMsUUFBUSxHQUFHO0FBQ2pDLGFBQU87QUFBQSxRQUNILFlBQVk7QUFBQSxVQUNSLEtBQUs7QUFBQSxVQUNMLFdBQVc7QUFBQSxVQUNYLGtCQUFrQjtBQUFBLFFBQ3RCLENBQUM7QUFBQSxNQUNMO0FBQUEsSUFDSjtBQUFBLEVBQ0o7QUFDQSxTQUFPO0FBQ1g7OztBQzNCb1MsT0FBTyxpQkFBaUI7QUFFN1MsU0FBUixvQkFBcUM7QUFDeEMsU0FBTyxZQUFZLENBQUMsQ0FBQztBQUN6Qjs7O0FKR2UsU0FBUixrQkFBbUMsU0FBUyxVQUFVLE9BQU87QUFDaEUsUUFBTSxjQUFjLENBQUMsSUFBSSxDQUFDO0FBQzFCLGNBQVksS0FBSyxpQkFBaUIsQ0FBQztBQUN0QyxjQUFZLEtBQUssa0JBQWtCLENBQUM7QUFDakMsY0FBWSxLQUFLLGNBQWMsT0FBTyxDQUFDO0FBQzFDLGFBQVcsWUFBWSxLQUFLLEdBQUcsa0JBQWtCLE9BQU8sQ0FBQztBQUN0RCxTQUFPO0FBQ1g7OztBRGRBLElBQU0sbUNBQW1DO0FBS3pDLElBQU8sc0JBQVEsYUFBYSxDQUFDLEVBQUUsTUFBTSxRQUFRLE1BQU07QUFDakQsUUFBTSxNQUFNLFFBQVEsTUFBTSxRQUFRLElBQUksQ0FBQztBQUN2QyxRQUFNLEVBQUUsYUFBYSxJQUFJO0FBQ3pCLFNBQU87QUFBQTtBQUFBO0FBQUE7QUFBQSxJQUlMLE1BQU0saUJBQWlCLGVBQWUsTUFBTTtBQUFBLElBQzVDLFNBQVMsa0JBQWtCLEtBQUssWUFBWSxPQUFPO0FBQUEsSUFDbkQsU0FBUztBQUFBO0FBQUEsTUFFUCxPQUFPO0FBQUE7QUFBQSxRQUVMLEtBQUtDLE1BQUssUUFBUSxrQ0FBVyxJQUFJO0FBQUE7QUFBQSxRQUVqQyxLQUFLQSxNQUFLLFFBQVEsa0NBQVcsT0FBTztBQUFBLE1BQ3RDO0FBQUE7QUFBQSxNQUVBLFlBQVksQ0FBQyxRQUFRLE9BQU8sT0FBTyxRQUFRLFFBQVEsU0FBUyxNQUFNO0FBQUEsSUFDcEU7QUFBQTtBQUFBLElBRUEsUUFBUTtBQUFBLE1BQ04sTUFBTTtBQUFBLE1BQ04sTUFBTTtBQUFBLE1BQ04sTUFBTTtBQUFBLE1BQ04sT0FBTztBQUFBO0FBQUEsUUFFTCxRQUFRO0FBQUEsVUFDTixRQUFRO0FBQUEsVUFDUixjQUFjO0FBQUEsVUFDZCxTQUFTLENBQUMsTUFBTSxFQUFFLFFBQVEsVUFBVSxFQUFFO0FBQUEsUUFDeEM7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBO0FBQUEsSUFFQSxLQUFLO0FBQUEsTUFDSCxTQUFTO0FBQUEsUUFDUCxTQUFTO0FBQUEsVUFDUDtBQUFBLFlBQ0UsZUFBZTtBQUFBLFlBQ2YsUUFBUTtBQUFBLGNBQ04sU0FBUyxDQUFDLFdBQVc7QUFDbkIsb0JBQUksT0FBTyxTQUFTLFdBQVc7QUFDN0IseUJBQU8sT0FBTztBQUFBLGdCQUNoQjtBQUFBLGNBQ0Y7QUFBQSxZQUNGO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRixDQUFDOyIsCiAgIm5hbWVzIjogWyJwYXRoIiwgInBhdGgiXQp9Cg==
================================================
FILE: server/.eslintignore
================================================
prisma-client
================================================
FILE: server/.eslintrc.js
================================================
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off', // 关闭接口名称前缀规则
'@typescript-eslint/explicit-function-return-type': 'off', // 关闭显式函数返回类型规则
'@typescript-eslint/explicit-module-boundary-types': 'off', // 关闭显式模块边界类型规则
'@typescript-eslint/no-explicit-any': 'off', // 允许使用 any 类型
'@typescript-eslint/no-var-requires': 'off', // 允许使用 require
'@typescript-eslint/no-empty-function': 'off', // 允许空函数
'@typescript-eslint/ban-types': 'off', // 关闭禁止特定类型的规则
'prettier/prettier': ['error', { endOfLine: 'auto' }], // 确保 Prettier 使用自动行尾格式
'prefer-const': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'quotes': ['0'] //忽略单双引号
},
overrides: [
{
files: ['src/common/middleware/auth/auth.middleware.ts'],
rules: {
'@typescript-eslint/ban-ts-comment': 'off', // 在特定文件中关闭该规则
},
},
],
};
================================================
FILE: server/.prettierrc
================================================
{
"singleQuote": true,
"trailingComma": "all"
}
================================================
FILE: server/nest-cli.json
================================================
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true,
"assets": [
{ "include": ".env", "watchAssets": true },
{ "include": "common/service/gen/gen-template", "watchAssets": true },
{ "include": "common/prisma-client", "watchAssets": true },
{ "include": "**/*.json", "watchAssets": true }
]
}
}
================================================
FILE: server/package.json
================================================
{
"name": "carole-admin",
"version": "1.0.0",
"description": "carole-admin后台框架",
"author": "carole",
"private": true,
"license": "UNLICENSED",
"prisma": {
"schema": "./src/prisma/"
},
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/schedule": "^4.0.2",
"@nestjs/swagger": "^7.3.1",
"@nestjs/throttler": "^5.1.2",
"@prisma/client": "^5.15.0",
"archiver": "^7.0.1",
"axios": "^1.6.8",
"bowser": "^2.11.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.11",
"dotenv": "^16.4.5",
"generic-pool": "^3.9.0",
"ioredis": "^5.4.1",
"jsonwebtoken": "^9.0.2",
"kolorist": "^1.8.0",
"lib-qqwry": "^1.3.4",
"lodash": "^4.17.21",
"module-alias": "^2.2.3",
"multer": "^1.4.5-lts.1",
"mysql2": "^3.9.7",
"nestjs-throttler-storage-redis": "^0.4.4",
"node-xlsx": "^0.24.0",
"nodemailer": "^6.9.13",
"redis": "^4.6.13",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
"svg-captcha": "^1.4.0",
"swagger-ui-express": "^5.0.0",
"systeminformation": "^5.22.7",
"velocityjs": "^2.0.6"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/crypto-js": "^4.2.2",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.2",
"@types/jsonwebtoken": "^9.0.6",
"@types/lodash": "^4.17.0",
"@types/multer": "^1.4.11",
"@types/node": "^20.12.12",
"@types/nodemailer": "^6.4.15",
"@types/redis": "^4.0.11",
"@types/supertest": "^6.0.0",
"@types/systeminformation": "^3.54.1",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"prettier": "^3.0.0",
"prisma": "^5.15.0",
"source-map-support": "^0.5.21",
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.3.2"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
================================================
FILE: server/src/admin/admin.module.ts
================================================
import { Module } from '@nestjs/common';
import { CaptchaController } from '@/admin/common/captcha/captcha.controller';
import { UploadController } from './common/upload/upload.controller';
import { AuthController } from './system/auth/auth.controller';
import { SysUserController } from './system/user/sys-user.controller';
import { SysDeptController } from './system/dept/sys-dept.controller';
import { SysConfigController } from './system/config/sys-config.controller';
import { DictDataController } from './system/dict-data/dict-data.controller';
import { DictTypeController } from './system/dict-type/dict-type.controller';
import { SysMenuController } from './system/menu/sys-menu.controller';
import { SysPostController } from './system/post/sys-post.controller';
import { SysRoleController } from './system/role/sys-role.controller';
import { GenController } from './gen/gen.controller';
import { DeptService } from './system/dept/service/sys-dept.service';
import { MenuService } from './system/menu/service/sys-menu.service';
import { ConfigService } from './system/config/service/sys-config.service';
import { LogininforService } from './system/logininfor/service/sys-logininfor.service';
import { NoticeService } from './system/notice/service/sys-notice.service';
import { PostService } from './system/post/service/sys-post.service';
import { RoleService } from './system/role/service/sys-role.service';
import { GenService } from '@/common/service/gen/gen.service';
import { SysDictTypeService } from './system/dict-type/service/sys-dict-type.service';
import { SysDictDataService } from './system/dict-data/service/sys-dict-data.service';
import { UserService } from './system/user/service/sys-user.service';
import { SysNoticeController } from './system/notice/sys-notice.controller';
import { SysLogininforController } from './system/logininfor/sys-logininfor.controller';
import { monitorController } from './system/monitor/monitor.controller';
@Module({
imports: [],
controllers: [
CaptchaController,
UploadController,
AuthController,
SysDeptController,
SysConfigController,
DictDataController,
DictTypeController,
SysMenuController,
SysPostController,
SysRoleController,
GenController,
SysUserController,
SysNoticeController,
SysLogininforController,
monitorController,
],
providers: [
DeptService,
MenuService,
ConfigService,
LogininforService,
MenuService,
NoticeService,
PostService,
RoleService,
GenService,
SysDictDataService,
SysDictTypeService,
UserService,
LogininforService,
],
})
export class AdminModule {}
================================================
FILE: server/src/admin/common/captcha/captcha.controller.ts
================================================
import { Controller, Get } from '@nestjs/common';
import { createMath, createText } from '@/common/utils/captcha';
import { Config } from '@/config';
import { redisUtils } from '@/common/utils/redisUtils';
import Result from '@/common/result/Result';
import { Constants } from '@/common/constant/Constants';
import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
import CaptchaImageVo from './vo/CaptchaImageVo';
import { randomUUID } from 'crypto';
import { Throttle } from '@nestjs/throttler';
@ApiTags('验证码模块')
@Controller('/captchaImage')
export class CaptchaController {
/*
* 生成验证码
* */
@Get()
@ApiOperation({
summary: '获取验证码',
})
@ApiOkResponse({
type: CaptchaImageVo,
})
@Throttle({
default: {
limit: 8,
ttl: 1000 * 60,
},
})
async getCaptchaImage() {
const map = {
math: createMath,
text: createText,
};
//根据配置的是math还是text自动调用方法生成数据
const captchaInfo = map[Config.captcha.mode]();
//是否开启验证码
const enable = await redisUtils.get(
Constants.SYS_CONFIG_KEY + 'sys.account.captchaEnabled',
);
const captchaEnabled: boolean = enable == '' ? true : enable === 'true';
const data = {
captchaEnabled,
img: captchaInfo.data,
uuid: randomUUID(),
};
try {
await redisUtils.set(
Constants.CAPTCHA_CODE_KEY + data.uuid,
captchaInfo.text.toLowerCase(),
Config.captcha.expiresIn,
);
return data;
} catch (err) {
return Result.Error('生成验证码错误,请重试');
}
}
}
================================================
FILE: server/src/admin/common/captcha/vo/CaptchaImageVo.ts
================================================
import { ApiProperty } from '@nestjs/swagger';
class Data {
@ApiProperty({
example: true,
description: '验证码是否启用',
})
'captchaEnabled': boolean;
@ApiProperty({
example: '..... ',
description: '接口图片svg格式',
})
'img': string;
@ApiProperty({
example: '14196d31-2bdf-4a42-b34c-eb771556e10e',
description: '接口uuid,验证需要',
})
'uuid': string;
}
export default class CaptchaImageVo {
@ApiProperty({
example: 200,
description: '响应code',
})
code: number;
@ApiProperty({
example: true,
description: '请求是否成功处理',
})
'success': boolean;
@ApiProperty({
example: 'successful',
description: '接口备注信息',
})
'msg': string;
@ApiProperty({
type: Data,
description: '返回数据',
})
'data': Data;
@ApiProperty({
example: '2024-04-28 22:32:35',
description: '处理时间',
})
'time': string;
}
================================================
FILE: server/src/admin/common/upload/config/uploadConfig.ts
================================================
import { createFolder, nowDate } from '@/common/utils';
import * as path from 'path';
import * as multer from 'multer';
import { randomUUID } from 'crypto';
import { Config } from '@/config';
import { Constants } from '@/common/constant/Constants';
let saveDir = Config.upload.path;
const avatarDir = path.join(saveDir, 'avatar');
saveDir = path.join(saveDir, 'files');
function createStorage(dir = saveDir) {
return multer.diskStorage({
destination: function (req, file, cb) {
createFolder(path.join(dir, nowDate()));
// 接收到文件后输出的保存路径(若不存在则需要创建)
cb(null, path.join(dir, nowDate()));
},
filename: function (req, file, cb) {
// 将保存文件名设置为 uuid + 文件原始名
cb(
null,
+new Date() +
randomUUID().replaceAll('-', '') +
(path.extname(file.originalname) || '.jpg'),
);
},
});
}
createFolder(saveDir);
createFolder(avatarDir);
export const uploadFileConfig = {
storage: createStorage(saveDir),
limits: Config.upload.config.file,
fileFilter: function (_req, file, cb) {
checkFileType(file, cb);
},
};
export const uploadAvatarConfig = {
storage: createStorage(avatarDir),
limits: Config.upload.config.img,
fileFilter: function (_req, file, cb) {
checkImgFileType(file, cb);
},
};
function checkImgFileType(file, cb) {
const filetypes = ['jpeg', 'jpg', 'png', 'gif'];
const mimetypes = [
'image/png',
'image/jpeg',
'image/jpg',
'image/webp',
'image/gif',
];
const extname = filetypes.includes(
file.originalname.split('.').pop().toLowerCase(),
);
const mimetype = mimetypes.includes(file.mimetype);
if (mimetype && extname) {
return cb(null, true);
} else {
const err = new multer.MulterError(
<
| 'LIMIT_PART_COUNT'
| 'LIMIT_FILE_SIZE'
| 'LIMIT_FILE_COUNT'
| 'LIMIT_FIELD_KEY'
| 'LIMIT_FIELD_VALUE'
| 'LIMIT_FIELD_COUNT'
| 'LIMIT_UNEXPECTED_FILE'
>'TypeError',
);
err.message = '只允许上传图片类型!';
cb(err, false);
}
}
function checkFileType(file, cb) {
const fileTypes = [
// 图片
'gif',
'jpg',
'jpeg',
'png',
// word excel powerpoint
'doc',
'docx',
'csv',
'text/csv',
'xls',
'xlsx',
'ppt',
'pptx',
'txt',
// 压缩文件
'rar',
'zip',
'gz',
// 视频格式
'mp4',
'avi',
// pdf
'pdf',
];
const mimeTypes = [
'image/gif',
'image/jpeg',
'image/jpeg',
'image/png',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-powerpoint',
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'text/plain',
'application/vnd.rar',
'application/zip',
'application/gzip',
'video/mp4',
'video/x-msvideo',
'application/pdf',
'application/x-zip-compressed',
];
const extname = fileTypes.includes(
file.originalname.split('.').pop().toLowerCase(),
);
const mimetype = mimeTypes.some((v) => file.mimetype.includes(v));
if (mimetype && extname) {
return cb(null, true);
} else {
const err = new multer.MulterError(
<
| 'LIMIT_PART_COUNT'
| 'LIMIT_FILE_SIZE'
| 'LIMIT_FILE_COUNT'
| 'LIMIT_FIELD_KEY'
| 'LIMIT_FIELD_VALUE'
| 'LIMIT_FIELD_COUNT'
| 'LIMIT_UNEXPECTED_FILE'
>'error',
);
err.message = '不允许上传的文件!';
cb(err, false);
}
}
export function getFilePath(file: Express.Multer.File) {
const configPath = Config.upload.path.replace(/\\+/g, '/');
const uploadPath = file.path.replace(/\\+/g, '/');
return Constants.FILE_PREFIX + uploadPath.replace(configPath, '');
}
================================================
FILE: server/src/admin/common/upload/dto/upload.dto.ts
================================================
import { ApiProperty } from '@nestjs/swagger';
export class UploadFileDto {
@ApiProperty({
example: '文件',
description: '上传文件',
})
file: Express.Multer.File;
}
export class UploadFilesDto {
@ApiProperty({
example: ['文件'],
description: '上传多个文件',
})
files: Express.Multer.File[];
}
================================================
FILE: server/src/admin/common/upload/upload.controller.ts
================================================
import {
Controller,
Post,
UploadedFile,
UploadedFiles,
UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
import Result from '@/common/result/Result';
import {
getFilePath,
uploadFileConfig,
} from '@/admin/common/upload/config/uploadConfig';
import {
ApiBearerAuth,
ApiBody,
ApiConsumes,
ApiOkResponse,
ApiOperation,
ApiTags,
} from '@nestjs/swagger';
import { uploadMultiple, uploadSingle } from './vo/upload';
import {
UploadFileDto,
UploadFilesDto,
} from '@/admin/common/upload/dto/upload.dto';
@ApiBearerAuth()
@ApiTags('文件上传模块')
@Controller()
export class UploadController {
@Post('/common/upload')
@ApiOperation({
summary: '上传单个文件',
description: '上传单个文件',
})
@ApiConsumes('multipart/form-data')
@ApiBody({
type: UploadFileDto,
})
@ApiOkResponse({
schema: {
example: uploadSingle,
},
})
@UseInterceptors(FileInterceptor('file', uploadFileConfig))
async uploadFile(@UploadedFile() file: Express.Multer.File) {
if (!file) {
return Result.BadRequest('请选择要上传的文件!');
}
const data = {
fileName: file.filename,
newFileName: file.filename,
originalFilename: file.originalname,
url: getFilePath(file),
size: file.size,
};
return { ...Result.ok(), ...data };
}
@Post('/common/uploads')
@ApiOperation({
summary: '上传多文件',
description: '上传多文件',
})
@ApiConsumes('multipart/form-data')
@ApiBody({
type: UploadFilesDto,
})
@ApiOkResponse({
schema: {
example: uploadMultiple,
},
})
@UseInterceptors(FilesInterceptor('files', 10, uploadFileConfig))
async uploadFiles(@UploadedFiles() files: Express.Multer.File[]) {
if (!files?.length) {
return Result.BadRequest('请选择要上传的文件!');
}
const data = [];
files.forEach((file) => {
data.push({
fileName: file.filename,
newFileName: file.filename,
originalFilename: file.originalname,
url: getFilePath(file),
size: file.size,
});
});
return Result.ok(data);
}
}
================================================
FILE: server/src/admin/common/upload/vo/upload.ts
================================================
export const uploadSingle = {
code: 200,
success: true,
msg: 'successful',
data: null,
time: '2024-04-29 08:11:08',
fileName: '17143494685302ec06156db9f4170b4635131b49356d6.png',
newFileName: '17143494685302ec06156db9f4170b4635131b49356d6.png',
originalFilename: 'thumb-1920-1314539.png',
url: '/upload/files/2024-04-29/17143494685302ec06156db9f4170b4635131b49356d6.png',
size: 951415,
};
export const uploadMultiple = {
code: 200,
success: true,
msg: 'successful',
data: [
{
fileName: '171434954750637f85940e0b245269c8a025b202b5555.png',
newFileName: '171434954750637f85940e0b245269c8a025b202b5555.png',
originalFilename: 'thumb-1920-1314539.png',
url: '/upload/files/2024-04-29/171434954750637f85940e0b245269c8a025b202b5555.png',
size: 951415,
},
{
fileName: '171434954751607c13706343443afa642532dae87a02d.jpeg',
newFileName: '171434954751607c13706343443afa642532dae87a02d.jpeg',
originalFilename: 'cropped-3840-2160-1328138.jpeg',
url: '/upload/files/2024-04-29/171434954751607c13706343443afa642532dae87a02d.jpeg',
size: 2563084,
},
],
time: '2024-04-29 08:12:27',
};
================================================
FILE: server/src/admin/gen/dto/exucteSqlDto.ts
================================================
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
export class excuteSqlDto {
@ApiProperty({ description: '执行的sql' })
@IsNotEmpty({ message: 'sql语句不能为空!' })
@IsString({ message: '类型不正确!' })
sql: string;
}
================================================
FILE: server/src/admin/gen/dto/queryDatabaseDto.ts
================================================
import { queryDomain } from '@/common/domain/queryDomain';
import { ApiProperty } from '@nestjs/swagger';
export class queryDataBaseDto extends queryDomain {
@ApiProperty({ description: '表名称' })
tableName: string | null;
@ApiProperty({ description: '表描述' })
tableComment: string | null;
}
================================================
FILE: server/src/admin/gen/dto/queryGenTableDto.ts
================================================
import { queryDomain } from '@/common/domain/queryDomain';
import { ApiProperty } from '@nestjs/swagger';
import { IsOptional } from 'class-validator';
export class queryGenTableDto extends queryDomain {
@ApiProperty({ description: '表名称',required:false })
@IsOptional()
tableName: string | null;
@ApiProperty({ description: '表描述',required:false })
@IsOptional()
tableComment: string | null;
@IsOptional()
params: {
beginTime: string | null;
endTime: string | null;
};
}
================================================
FILE: server/src/admin/gen/gen.controller.ts
================================================
import {
Body,
Controller,
Delete,
Get,
Param,
ParseArrayPipe,
ParseIntPipe,
Post,
Put,
Query,
Res,
} from '@nestjs/common';
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import Result from '@/common/result/Result';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { queryGenTableDto } from './dto/queryGenTableDto';
import { GenService } from '@/common/service/gen/gen.service';
import { queryDataBaseDto } from './dto/queryDatabaseDto';
import { isNumber } from 'class-validator';
import { Response } from 'express';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { RequireRole } from '@/common/decorator/require-role.decorator';
import { excuteSqlDto } from './dto/exucteSqlDto';
@ApiTags('代码生成')
@ApiBearerAuth()
@Controller('tool/gen')
export class GenController {
constructor(private genService: GenService) {}
@ApiOperation({ summary: '查询生成表数据' })
@RequirePermission('tool:gen:query')
@Get('/list')
async listTable(@Query() q: queryGenTableDto) {
return Result.TableData(await this.genService.listTable(q));
}
@ApiOperation({ summary: '查询db数据库列表' })
@RequirePermission('tool:gen:query')
@Get('/db/list')
async listDbTable(@Query() q: queryDataBaseDto) {
return Result.TableData(await this.genService.listDbTable(q));
}
@ApiOperation({ summary: '生成代码 返回压缩包' })
@RequirePermission('tool:gen:code')
@Get('/batchGenCode')
genCode(
@Query('tables', ParseArrayPipe) tables: string[],
@Res() res: Response,
) {
if (!tables.length || tables.some((v) => typeof v != 'string')) {
return Result.BadRequest('参数错误!');
}
this.genService.genCode(tables, res);
}
@ApiOperation({ summary: '修改代码生成信息' })
@RequirePermission('tool:gen:edit')
@Put()
async updateGenTable(@Body() info) {
await this.genService.updateGenTable(info);
return Result.ok();
}
@ApiOperation({ summary: '导入表' })
@RequirePermission('tool:gen:import')
@Post('/importTable')
async importTable(@Query('tables', ParseArrayPipe) tables: string[]) {
await this.genService.importTable(tables);
return Result.ok();
}
@ApiOperation({ summary: '执行sql' })
@RequireRole('admin')
@Post('/excute')
async excuteSql(@Body() excute: excuteSqlDto) {
try {
await this.genService.excute(excute.sql);
return Result.ok(null, '执行成功!');
} catch (error) {
console.log(error);
return Result.BadRequest('sql执行失败:' + error.message);
}
}
@ApiOperation({ summary: '预览生成代码' })
@RequirePermission('tool:gen:preview')
@Get('/preview/:tableId')
async previewTable(@Param('tableId', ParseIntPipe) tableId: number) {
return Result.ok(await this.genService.previewTable(tableId));
}
@ApiOperation({ summary: '生成代码(自定义路径)' })
@RequirePermission('tool:gen:code')
@Get('/genCode/:tableNames')
// 无用接口
// async genCodeByPath(@Param('tableNames', ParseArrayPipe) tableNames: string[]) { }
async genCodeByPath() {
return Result.ok();
}
@ApiOperation({ summary: '同步数据库' })
@RequirePermission('tool:gen:edit')
@Get('synchDb/:tableName')
async synchDb(@Param('tableName') tableName: string) {
await this.genService.synchDb(tableName);
return Result.ok('操作成功');
}
@ApiOperation({ summary: '查询表详细信息' })
@RequirePermission('tool:gen:edit')
@Get('/:id')
async getGenTable(@Param('id') id: string) {
const info = isNumber(+id)
? await this.genService.getTableInfoById(+id)
: await this.genService.getTableInfoByTableName(id);
if (!info) return Result.ok(null);
const data = {
info,
rows: info.columns,
tables: [info],
};
return Result.ok(data);
}
@ApiOperation({ summary: '删除表数据' })
@RequirePermission('tool:gen:remove')
@Delete('/:ids')
async delTable(@Param('ids', ParseIntArrayPipe) ids: number[]) {
await this.genService.delTable(ids);
return Result.ok();
}
}
================================================
FILE: server/src/admin/system/auth/auth.controller.ts
================================================
import { Body, Controller, Get, Headers, Post, Req } from '@nestjs/common';
import { LoginBody } from '@/admin/system/auth/dto/LoginBody';
import { AuthService } from '@/common/service/auth/auth.service';
import Result from '@/common/result/Result';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { Constants } from '@/common/constant/Constants';
import { redisUtils } from '@/common/utils/redisUtils';
import { Throttle } from '@nestjs/throttler';
@ApiTags('Auth')
@Controller()
export class AuthController {
constructor(private authService: AuthService) {}
@Throttle({
default: {
limit: 8,
ttl: 1000 * 60 * 60,
},
})
@Post('/login')
@ApiOperation({ summary: '登录' })
async login(@Body() loginBody: LoginBody, @Req() req) {
const token = await this.authService.login(loginBody, req);
return {
...Result.ok(),
token,
};
}
@ApiOperation({ summary: '退出登录' })
@Throttle({
default: {
limit: 8,
ttl: 1000 * 60 * 60,
},
})
@Post('/logout')
async logout(@Headers('authorization') token: string) {
try {
await redisUtils.del(Constants.LOGIN_TOKEN_KEY + token.slice(7));
} catch (error) {
} finally {
return Result.ok();
}
}
@ApiOperation({ summary: '获取用户信息,包括权限和角色' })
@ApiBearerAuth()
@Get('/getInfo')
async getInfo(@Req() req) {
const user = await this.authService.getUserInfo(req.userId);
return {
...Result.ok(),
user,
roles: user.roles,
permissions: user.permissions,
};
}
@ApiOperation({ summary: '获取用户能访问的路由' })
@ApiBearerAuth()
@Get('/getRouters')
async getRouters(@Req() req) {
return Result.ok(await this.authService.getRouters(req.userId));
}
}
================================================
FILE: server/src/admin/system/auth/dto/LoginBody.ts
================================================
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsOptional, IsString, MinLength } from 'class-validator';
export class LoginBody {
@ApiProperty({description: '用户名'})
@IsNotEmpty({ message: '用户名不能为空!' })
@MinLength(4, { message: '用户名格式不正确' })
@IsString()
username: string;
@ApiProperty({description: '密码'})
@IsNotEmpty({ message: '密码不能为空!' })
@MinLength(5, { message: '密码格式不正确' })
@IsString()
password: string;
@ApiProperty({description: '验证码', required:false})
@IsString()
@IsOptional()
code?: string;
@IsString()
@IsOptional()
@ApiProperty({description: '验证码uuid', required:false})
uuid?: string;
}
================================================
FILE: server/src/admin/system/config/dto/index.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNotEmpty, IsNumber, IsString, IsOptional } from 'class-validator';
import { queryDomain } from '@/common/domain/queryDomain';
/**@description 查询参数配置Dto */
export class QuerySysConfigDto extends queryDomain {
@ApiProperty({ description: '参数主键',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
configId: number | null;
@ApiProperty({ description: '参数名称',required:false })
@IsOptional()
configName: string | null;
@ApiProperty({ description: '参数键名',required:false })
@IsOptional()
configKey: string | null;
@ApiProperty({ description: '参数键值',required:false })
@IsOptional()
configValue: string | null;
@ApiProperty({ description: '系统内置',required:false })
@IsOptional()
configType: string | null;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
createBy: string | null;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
updateBy: string | null;
}
/**@description 创建参数配置Dto */
export class CreateSysConfigDto extends BaseDomain {
@ApiProperty({ description: '参数名称' })
@IsNotEmpty({ message: '参数名称不能为空' })
@IsString()
configName: string;
@ApiProperty({ description: '参数键名' })
@IsNotEmpty({ message: '参数键名不能为空' })
@IsString()
configKey: string;
@ApiProperty({ description: '参数键值' })
@IsNotEmpty({ message: '参数键值不能为空' })
@IsString()
configValue: string;
@ApiProperty({ description: '系统内置',required:false })
@IsOptional()
@IsString()
configType?: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
}
/**@description 更新参数配置Dto */
export class UpdateSysConfigDto extends BaseDomain {
@ApiProperty({ description: '参数主键' })
@IsNotEmpty({ message: '参数主键不能为空' })
@Transform((v) => +v.value)
@IsNumber()
configId: number;
@ApiProperty({ description: '参数名称' })
@IsNotEmpty({ message: '参数名称不能为空' })
@IsString()
configName: string;
@ApiProperty({ description: '参数键名' })
@IsNotEmpty({ message: '参数键名不能为空' })
@IsString()
configKey: string;
@ApiProperty({ description: '参数键值' })
@IsNotEmpty({ message: '参数键值不能为空' })
@IsString()
configValue: string;
@ApiProperty({ description: '系统内置',required:false })
@IsOptional()
@IsString()
configType?: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
}
================================================
FILE: server/src/admin/system/config/service/sys-config.service.ts
================================================
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { Response } from 'express';
import { exportTable } from '@/common/utils';
import {
QuerySysConfigDto,
CreateSysConfigDto,
UpdateSysConfigDto,
} from '../dto/index';
import { Prisma } from '@prismaClient';
import { isNotEmpty } from 'class-validator';
import { redisUtils } from '@/common/utils/redisUtils';
import { Constants } from '@/common/constant/Constants';
@Injectable()
export class ConfigService {
constructor(private prisma: PrismaService) {
this.initSysConfigData();
}
/**@desc 初始化系统配置到redis缓存 */
async initSysConfigData() {
const configData = await this.prisma.sysConfig.findMany({
select: {
configKey: true,
configValue: true,
},
});
for (const item of configData) {
await redisUtils.set(
Constants.SYS_CONFIG_KEY + item.configKey,
item.configValue,
);
}
console.log('系统配置信息初始化完成!');
}
/**@description 查询参数配置所有 */
async selectConfigAll() {
return this.prisma.sysConfig.findMany();
}
/**@description 分页查询参数配置列表 */
async selectConfigList(q: QuerySysConfigDto) {
const queryCondition: Prisma.SysConfigWhereInput = {};
if (isNotEmpty(q['configId'])) {
queryCondition.configId = {
equals: q.configId,
};
}
if (isNotEmpty(q['configName'])) {
queryCondition.configName = {
contains: q.configName,
};
}
if (isNotEmpty(q['configKey'])) {
queryCondition.configKey = {
contains: q.configKey,
};
}
if (isNotEmpty(q['configValue'])) {
queryCondition.configValue = {
equals: q.configValue,
};
}
if (isNotEmpty(q['configType'])) {
queryCondition.configType = {
equals: q.configType,
};
}
if (isNotEmpty(q['createBy'])) {
queryCondition.createBy = {
equals: q.createBy,
};
}
if (
isNotEmpty(q.params.beginCreateTime) &&
isNotEmpty(q.params.endCreateTime)
) {
queryCondition.createTime = {
lte: q.params.endCreateTime,
gte: q.params.beginCreateTime,
};
}
if (isNotEmpty(q['updateBy'])) {
queryCondition.updateBy = {
equals: q.updateBy,
};
}
if (
isNotEmpty(q.params.beginUpdateTime) &&
isNotEmpty(q.params.endUpdateTime)
) {
queryCondition.updateTime = {
lte: q.params.endUpdateTime,
gte: q.params.beginUpdateTime,
};
}
return {
rows: await this.prisma.sysConfig.findMany({
skip: (q.pageNum - 1) * q.pageSize,
take: q.pageSize,
where: queryCondition,
}),
total: await this.prisma.sysConfig.count({
where: queryCondition,
}),
};
}
/**@description 查询参数配置详情 */
async selectConfigByConfigId(configId: number) {
return this.prisma.sysConfig.findUnique({
where: {
configId,
},
});
}
/**@description 新增参数配置 */
async addConfig(sysConfig: CreateSysConfigDto) {
//删除掉空值
for (const key in sysConfig) {
!isNotEmpty(sysConfig[key]) && delete sysConfig[key];
}
const d = await this.prisma.sysConfig.create({
data: sysConfig,
});
await redisUtils.set(
Constants.SYS_CONFIG_KEY + sysConfig.configKey,
sysConfig.configValue,
);
return d;
}
/**@description 修改参数配置 */
async updateConfig(sysConfig: UpdateSysConfigDto) {
//删除掉空值
for (const key in sysConfig) {
!isNotEmpty(sysConfig[key]) && delete sysConfig[key];
}
await this.prisma.sysConfig.update({
where: {
configId: sysConfig.configId,
},
data: sysConfig,
});
await redisUtils.set(
Constants.SYS_CONFIG_KEY + sysConfig.configKey,
sysConfig.configValue,
);
return true;
}
/**@description 批量删除参数配置 */
async deleteConfigByConfigIds(configIds: number[]) {
const r = await this.prisma.sysConfig.deleteMany({
where: {
configId: {
in: configIds,
},
},
});
await this.initSysConfigData();
return r;
}
/**@description 单个删除参数配置 */
async deleteConfigByConfigId(configId: number) {
const r = this.prisma.sysConfig.delete({
where: {
configId,
},
});
await this.initSysConfigData();
return r;
}
/**@description 导出参数配置所有数据为xlsx */
async exportConfig(res: Response) {
const title = [
'参数主键',
'参数名称',
'参数键名',
'参数键值',
'系统内置',
'创建者',
'创建时间',
'更新者',
'更新时间',
'备注',
];
const data = (await this.prisma.sysConfig.findMany()).map((v) =>
Object.values(v),
);
data.unshift(title);
exportTable(data, res);
}
}
================================================
FILE: server/src/admin/system/config/sys-config.controller.ts
================================================
import {
Body,
Controller,
Delete,
Get,
Logger,
Param,
ParseIntPipe,
Post,
Put,
Query,
Req,
Res,
} from '@nestjs/common';
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import Result from '@/common/result/Result';
import {
ApiBearerAuth,
ApiBody,
ApiOperation,
ApiQuery,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { nowDateTime, readJsonFile } from '@/common/utils';
import { ConfigService } from './service/sys-config.service';
import {
QuerySysConfigDto,
CreateSysConfigDto,
UpdateSysConfigDto,
} from './dto/index';
import { Response } from 'express';
import { SysConfig } from '@prismaClient';
import { TableDataInfo } from '@/common/domain/TableDataInfo';
import { RequireRole } from '@/common/decorator/require-role.decorator';
import { join } from 'path';
import { writeFileSync } from 'fs';
import { Config } from '@/config';
@ApiTags('参数配置')
@ApiBearerAuth()
@Controller('system/config')
export class SysConfigController {
constructor(private configService: ConfigService) { }
@ApiOperation({ summary: '获取配置文件列表' })
@Get("/getFileKeys")
@RequirePermission("system:serverconfig:menu")
getConfigFileKeys() {
let map = structuredClone(Config.ConfigFileMap)
for (let key in map) {
delete map[key].filePath
}
return Result.ok(map);
}
@ApiOperation({ summary: '根据key获取配置信息' })
@Get("/getConfigInfo")
@RequirePermission("system:serverconfig:menu")
getConfigInfo(@Query("key") key: string) {
if (key && Config.ConfigFileMap[key]) {
return Result.ok(readJsonFile(Config.ConfigFileMap[key].filePath))
} else {
}
}
@ApiOperation({ summary: '更新配置信息' })
@Post("serverConfig")
@RequirePermission("system:serverconfig:menu")
changeServerConfig(@Body() data, @Query("key") key: string) {
if (key in Config.ConfigFileMap) {
if (typeof data != "string") {
data = JSON.stringify(data, null, 2)
}
try {
JSON.parse(data);
} catch (error) {
Logger.error("修改配置文件异常:", error?.message);
return Result.Error("json格式有误!");
}
writeFileSync(Config.ConfigFileMap[key].filePath, data);
Logger.log("修改配置文件成功:", key);
return Result.ok("修改成功!");
} else {
return Result.Error("key不存在!");
}
}
@ApiOperation({ summary: '查询参数配置列表' })
@ApiResponse({ type: TableDataInfo })
@RequirePermission('system:config:query')
@Get('/list')
async listConfig(
@Query() q: QuerySysConfigDto,
): Promise> {
return Result.TableData(await this.configService.selectConfigList(q));
}
@ApiOperation({ summary: '导出参数配置xlsx文件' })
@RequirePermission('system:config:export')
@Get('/export')
async export(@Res() res: Response): Promise {
return this.configService.exportConfig(res);
}
@ApiOperation({ summary: '查询参数配置详细' })
@ApiResponse({ type: Result })
@RequirePermission('system:config:query')
@Get('/:configId')
async getConfig(
@Param('configId', ParseIntPipe) configId: number,
): Promise> {
return Result.ok(await this.configService.selectConfigByConfigId(configId));
}
@ApiOperation({ summary: '新增参数配置' })
@ApiResponse({ type: Result })
@ApiBody({ type: CreateSysConfigDto })
@RequirePermission('system:config:add')
@Post('/')
async addConfig(
@Body() sysConfig: CreateSysConfigDto,
@Req() req,
): Promise> {
sysConfig = {
...sysConfig,
createTime: nowDateTime(),
updateTime: nowDateTime(),
createBy: req.user?.userName,
updateBy: req.user?.userName,
};
return Result.ok(await this.configService.addConfig(sysConfig));
}
@ApiOperation({ summary: '修改参数配置' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysConfigDto })
@RequirePermission('system:config:edit')
@Put('/')
async updateConfig(
@Body() sysConfig: UpdateSysConfigDto,
@Req() req,
): Promise> {
sysConfig = {
...sysConfig,
updateTime: nowDateTime(),
updateBy: req.user?.userName,
};
await this.configService.updateConfig(sysConfig);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '删除参数配置' })
@ApiResponse({ type: Result })
@RequirePermission('system:config:remove')
@Delete('/:ids')
async delConfig(
@Param('ids', ParseIntArrayPipe) configIds: number[],
): Promise> {
const { count } =
await this.configService.deleteConfigByConfigIds(configIds);
return Result.toAjax(count);
}
}
================================================
FILE: server/src/admin/system/dept/dto/index.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNotEmpty, IsNumber, IsString, IsOptional } from 'class-validator';
import { queryDomain } from '@/common/domain/queryDomain';
/**@description 查询部门管理Dto */
export class QuerySysDeptDto extends queryDomain {
@ApiProperty({ description: '部门id',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
deptId: number | null;
@ApiProperty({ description: '父部门',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
parentId: number | null;
@ApiProperty({ description: '祖级列表',required:false })
@IsOptional()
ancestors: string | null;
@ApiProperty({ description: '部门名称',required:false })
@IsOptional()
deptName: string | null;
@ApiProperty({ description: '显示顺序',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
orderNum: number | null;
@ApiProperty({ description: '负责人',required:false })
@IsOptional()
leader: string | null;
@ApiProperty({ description: '联系电话',required:false })
@IsOptional()
phone: string | null;
@ApiProperty({ description: '邮箱',required:false })
@IsOptional()
email: string | null;
@ApiProperty({ description: '部门状态(0停用,1正常)',required:false })
@IsOptional()
status: string | null;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
createBy: string | null;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
updateBy: string | null;
}
/**@description 创建部门管理Dto */
export class CreateSysDeptDto extends BaseDomain {
@ApiProperty({ description: '父部门' })
@IsNotEmpty({ message: '父部门不能为空' })
@Transform((v) => +v.value)
@IsNumber()
parentId: number;
@ApiProperty({ description: '祖级列表',required:false })
@IsOptional()
@IsString()
ancestors?: string;
@ApiProperty({ description: '部门名称' })
@IsNotEmpty({ message: '部门名称不能为空' })
@IsString()
deptName: string;
@ApiProperty({ description: '显示顺序' })
@IsNotEmpty({ message: '显示顺序不能为空' })
@Transform((v) => +v.value)
@IsNumber()
orderNum: number;
@ApiProperty({ description: '负责人',required:false })
@IsOptional()
@IsString()
leader?: string;
@ApiProperty({ description: '联系电话',required:false })
@IsOptional()
@IsString()
phone?: string;
@ApiProperty({ description: '邮箱',required:false })
@IsOptional()
@IsString()
email?: string;
@ApiProperty({ description: '部门状态(0停用,1正常)',required:false })
@IsOptional()
@IsString()
status?: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
}
/**@description 更新部门管理Dto */
export class UpdateSysDeptDto extends BaseDomain {
@ApiProperty({ description: '部门id' })
@IsNotEmpty({ message: '部门id不能为空' })
@Transform((v) => +v.value)
@IsNumber()
deptId: number;
@ApiProperty({ description: '祖级列表',required:false })
@IsOptional()
@IsString()
ancestors?: string;
@ApiProperty({ description: '部门名称' })
@IsNotEmpty({ message: '部门名称不能为空' })
@IsString()
deptName: string;
@ApiProperty({ description: '显示顺序' })
@IsNotEmpty({ message: '显示顺序不能为空' })
@Transform((v) => +v.value)
@IsNumber()
orderNum: number;
@ApiProperty({ description: '负责人',required:false })
@IsOptional()
@IsString()
leader?: string;
@ApiProperty({ description: '联系电话',required:false })
@IsOptional()
@IsString()
phone?: string;
@ApiProperty({ description: '邮箱',required:false })
@IsOptional()
@IsString()
email?: string;
@ApiProperty({ description: '部门状态(0停用,1正常)',required:false })
@IsOptional()
@IsString()
status?: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
}
================================================
FILE: server/src/admin/system/dept/service/sys-dept.service.ts
================================================
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { Response } from 'express';
import { exportTable, tree } from '@/common/utils';
import {
QuerySysDeptDto,
CreateSysDeptDto,
UpdateSysDeptDto,
} from '../dto/index';
import { Prisma } from '@prismaClient';
import { isNotEmpty } from 'class-validator';
import * as assert from 'assert';
@Injectable()
export class DeptService {
constructor(private prisma: PrismaService) {}
/**@description 分页查询部门管理列表 */
async selectDeptList(q: QuerySysDeptDto) {
const queryCondition: Prisma.SysDeptWhereInput = {};
if (isNotEmpty(q['deptId'])) {
queryCondition.deptId = {
equals: q.deptId,
};
}
if (isNotEmpty(q['parentId'])) {
queryCondition.parentId = {
equals: q.parentId,
};
}
if (isNotEmpty(q['ancestors'])) {
queryCondition.ancestors = {
equals: q.ancestors,
};
}
if (isNotEmpty(q['deptName'])) {
queryCondition.deptName = {
contains: q.deptName,
};
}
if (isNotEmpty(q['orderNum'])) {
queryCondition.orderNum = {
equals: q.orderNum,
};
}
if (isNotEmpty(q['leader'])) {
queryCondition.leader = {
equals: q.leader,
};
}
if (isNotEmpty(q['phone'])) {
queryCondition.phone = {
equals: q.phone,
};
}
if (isNotEmpty(q['email'])) {
queryCondition.email = {
equals: q.email,
};
}
if (isNotEmpty(q['status'])) {
queryCondition.status = {
equals: q.status,
};
}
if (isNotEmpty(q['createBy'])) {
queryCondition.createBy = {
equals: q.createBy,
};
}
if (
isNotEmpty(q.params.beginCreateTime) &&
isNotEmpty(q.params.endCreateTime)
) {
queryCondition.createTime = {
lte: q.params.endCreateTime,
gte: q.params.beginCreateTime,
};
}
if (isNotEmpty(q['updateBy'])) {
queryCondition.updateBy = {
equals: q.updateBy,
};
}
if (
isNotEmpty(q.params.beginUpdateTime) &&
isNotEmpty(q.params.endUpdateTime)
) {
queryCondition.updateTime = {
lte: q.params.endUpdateTime,
gte: q.params.beginUpdateTime,
};
}
return await this.prisma.sysDept.findMany({
where: queryCondition,
});
}
/**@description 分页查询部门管理列表 */
async listDeptExcludeChild(deptId: number) {
return this.prisma.sysDept.findMany({
where: {
deptId: {
not: deptId,
},
},
orderBy: {
orderNum: 'asc',
},
});
}
/**@description 查询部门管理详情 */
async selectDeptByDeptId(deptId: number) {
return this.prisma.sysDept.findUnique({
where: {
deptId,
},
});
}
/**@description 新增部门管理 */
async addDept(sysDept: CreateSysDeptDto) {
//删除掉空值
for (const key in sysDept) {
!isNotEmpty(sysDept[key]) && delete sysDept[key];
}
return await this.prisma.sysDept.create({
data: sysDept,
});
}
/**@description 修改部门管理 */
async updateDept(sysDept: UpdateSysDeptDto) {
//删除掉空值
for (const key in sysDept) {
!isNotEmpty(sysDept[key]) && delete sysDept[key];
}
return await this.prisma.sysDept.update({
where: {
deptId: sysDept.deptId,
},
data: sysDept,
});
}
/**@description 批量删除部门管理 */
async deleteDeptByDeptIds(deptIds: number[]) {
const dept = await this.prisma.sysDept.findFirst({
where: {
parentId: {
in: deptIds,
},
},
});
assert(!dept, '存在子部门,不允许删除!');
const dept1 = await this.prisma.sysRoleDept.findFirst({
where: { deptId: { in: deptIds } },
});
assert(!dept1, '部门已分配,不允许删除!');
const dept2 = await this.prisma.sysUser.findFirst({
where: { deptId: { in: deptIds } },
});
assert(!dept2, '部门已分配,不允许删除!');
return this.prisma.sysDept.deleteMany({
where: {
deptId: {
in: deptIds,
},
},
});
}
/**@description 单个删除部门管理 */
async deleteDeptByDeptId(deptId: number) {
const dept = await this.prisma.sysDept.findFirst({
where: {
parentId: deptId,
},
});
assert(!dept, '存在子部门,不允许删除!');
const dept1 = await this.prisma.sysRoleDept.findFirst({
where: { deptId },
});
assert(!dept1, '部门已分配,不允许删除!');
const dept2 = await this.prisma.sysUser.findFirst({ where: { deptId } });
assert(!dept2, '部门已分配,不允许删除!');
return this.prisma.sysDept.deleteMany({
where: {
deptId,
},
});
}
/**@description 导出部门管理所有数据为xlsx */
async exportDept(res: Response) {
const title = [
'部门id',
'父部门',
'祖级列表',
'部门名称',
'显示顺序',
'负责人',
'联系电话',
'邮箱',
'部门状态(0停用,1正常)',
'删除标志(0删除,1存在 )',
'创建者',
'创建时间',
'更新者',
'更新时间',
];
const data = (await this.prisma.sysDept.findMany()).map((v) =>
Object.values(v),
);
data.unshift(title);
exportTable(data, res);
}
async getDeptTree() {
return tree(
(await this.prisma.sysDept.findMany()).map((v) => ({
id: v.deptId,
pid: v.parentId,
label: v.deptName,
})),
);
}
}
================================================
FILE: server/src/admin/system/dept/sys-dept.controller.ts
================================================
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Post,
Put,
Query,
Req,
Res,
} from '@nestjs/common';
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import Result from '@/common/result/Result';
import {
ApiBearerAuth,
ApiBody,
ApiOperation,
ApiQuery,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { nowDateTime } from '@/common/utils';
import { DeptService } from './service/sys-dept.service';
import {
QuerySysDeptDto,
CreateSysDeptDto,
UpdateSysDeptDto,
} from './dto/index';
import { Response } from 'express';
import { SysDept } from '@prismaClient';
@ApiBearerAuth()
@ApiTags('部门管理')
@Controller('system/dept')
export class SysDeptController {
constructor(private deptService: DeptService) {}
@ApiOperation({ summary: '查询部门管理列表' })
@ApiResponse({ type: Result })
@RequirePermission('system:dept:query')
@Get('/list')
async listDept(@Query() q: QuerySysDeptDto): Promise> {
return Result.ok(await this.deptService.selectDeptList(q));
}
@ApiOperation({ summary: '查询部门列表(排除节点)' })
@ApiResponse({ type: Result })
@RequirePermission('system:dept:query')
@Get('list/exclude/:deptId')
async listDeptExcludeChild(
@Param('deptId', ParseIntPipe) deptId: number,
): Promise> {
return Result.ok(await this.deptService.listDeptExcludeChild(deptId));
}
@ApiOperation({ summary: '导出部门管理xlsx文件' })
@RequirePermission('system:dept:export')
@Get('/export')
async export(@Res() res: Response): Promise {
return this.deptService.exportDept(res);
}
@ApiOperation({ summary: '查询部门管理详细' })
@ApiResponse({ type: Result })
@RequirePermission('system:dept:query')
@Get('/:deptId')
async getDept(
@Param('deptId', ParseIntPipe) deptId: number,
): Promise> {
return Result.ok(await this.deptService.selectDeptByDeptId(deptId));
}
@ApiOperation({ summary: '新增部门管理' })
@ApiResponse({ type: Result })
@ApiBody({ type: CreateSysDeptDto })
@RequirePermission('system:dept:add')
@Post('/')
async addDept(
@Body() sysDept: CreateSysDeptDto,
@Req() req,
): Promise> {
sysDept = {
...sysDept,
createTime: nowDateTime(),
updateTime: nowDateTime(),
createBy: req.user?.userName,
updateBy: req.user?.userName,
};
return Result.ok(await this.deptService.addDept(sysDept));
}
@ApiOperation({ summary: '修改部门管理' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysDeptDto })
@RequirePermission('system:dept:edit')
@Put('/')
async updateDept(
@Body() sysDept: UpdateSysDeptDto,
@Req() req,
): Promise> {
sysDept = {
...sysDept,
updateTime: nowDateTime(),
updateBy: req.user?.userName,
};
await this.deptService.updateDept(sysDept);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '删除部门管理' })
@ApiResponse({ type: Result })
@RequirePermission('system:dept:remove')
@Delete('/:ids')
async delDept(
@Param('ids', ParseIntArrayPipe) deptIds: number[],
): Promise> {
const { count } = await this.deptService.deleteDeptByDeptIds(deptIds);
return Result.toAjax(count);
}
}
================================================
FILE: server/src/admin/system/dict-data/dict-data.controller.ts
================================================
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import {
Controller,
Get,
Post,
Put,
Delete,
Query,
Body,
Param,
ParseIntPipe,
Inject,
Req,
Res,
} from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { queryDictDataDto } from './dto/queryDictDataDto';
import { SysDictDataService } from './service/sys-dict-data.service';
import Result from '@/common/result/Result';
import { CreateDictDataDto } from './dto/createDictDataDto';
import { nowDateTime } from '@/common/utils';
import { updateDictDataDto } from './dto/updateDictDataDto';
import { Response } from 'express';
@ApiTags('字典数据')
@ApiBearerAuth()
@Controller('/system/dict/data')
export class DictDataController {
@Inject()
dictDataService: SysDictDataService;
@ApiOperation({ summary: '查询字典数据列表' })
@Get('list')
async listData(@Query() q: queryDictDataDto) {
return Result.TableData(await this.dictDataService.selectDictDataList(q));
}
@ApiOperation({ summary: '导出xlsx文件' })
@Get('export')
async export(@Res() res: Response) {
this.dictDataService.exportDictData(res);
}
@Get('/type/:type')
@ApiOperation({ summary: '根据字典类型查询字典数据信息' })
async getDicts(@Param('type') type: string) {
if (!type) return Result.Validation('请传入字典类型');
return Result.ok(
(await this.dictDataService.selectDictDataByDictType(type)) || [],
);
}
@Get(':id')
@ApiOperation({ summary: '查询字典数据详细' })
async getData(@Param('id', ParseIntPipe) id: number) {
return Result.ok(await this.dictDataService.selectDictDataDetail(id));
}
@ApiOperation({ summary: '新增字典数据' })
@Post()
async addData(@Body() dictData: CreateDictDataDto, @Req() req) {
dictData.createTime = nowDateTime();
dictData.updateTime = nowDateTime();
dictData.createBy = req.user.userName;
dictData.updateBy = req.user.userName;
await this.dictDataService.addDictData(dictData);
return Result.ok('新增成功!');
}
@ApiOperation({ summary: '修改字典数据' })
@Put()
async updateData(@Body() dictData: updateDictDataDto, @Req() req) {
dictData.updateTime = nowDateTime();
dictData.updateBy = req.user.userName;
await this.dictDataService.updateDictData(dictData);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '删除字典数据' })
@Delete(':dictCodes')
async delData(@Param('dictCodes', ParseIntArrayPipe) dictCodes: number[]) {
const { count } = await this.dictDataService.deleteDictData(dictCodes);
return Result.toAjax(count);
}
}
================================================
FILE: server/src/admin/system/dict-data/dto/createDictDataDto.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNotEmpty, IsNumber, IsOptional, IsString } from 'class-validator';
export class CreateDictDataDto extends BaseDomain {
@ApiProperty({ description: '字典类型' })
@IsNotEmpty({ message: '字典类型不能为空' })
@IsString()
dictType: string;
@ApiProperty({ description: '数据标签' })
@IsNotEmpty({ message: '数据标签不能为空' })
@IsString()
dictLabel: string;
@ApiProperty({ description: '数据键值' })
@IsNotEmpty({ message: '数据键值不能为空' })
@IsString()
dictValue?: string;
@ApiProperty({ description: '样式属性',required:false })
@IsOptional()
cssClass?: string;
@ApiProperty({ description: '回显样式',required:false })
@IsOptional()
listClass?: string;
@ApiProperty({ description: '显示排序' })
@IsNotEmpty({ message: '排序值不能为空' })
@Transform((v) => +v.value)
@IsNumber()
dictSort: number;
@ApiProperty({ description: '字典状态(0停用,1正常)',required:false })
@IsOptional()
status?: string = '1';
}
================================================
FILE: server/src/admin/system/dict-data/dto/queryDictDataDto.ts
================================================
import { queryDomain } from '@/common/domain/queryDomain';
import { ApiProperty } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator';
export class queryDictDataDto extends queryDomain {
@ApiProperty({ description: '字典标签',required:false })
@IsString()
@IsOptional()
dictLabel?: string | null;
@ApiProperty({ description: '字典名称',required:false })
@IsString()
@IsOptional()
dictType?: string | null;
@ApiProperty({ description: '数据状态',required:false })
@IsString()
@IsOptional()
status?: string | null;
}
================================================
FILE: server/src/admin/system/dict-data/dto/updateDictDataDto.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNotEmpty, IsNumber, IsOptional, IsString } from 'class-validator';
export class updateDictDataDto extends BaseDomain {
@IsNotEmpty({ message: '字典数据id不能为空!' })
@Transform((v) => +v.value)
@IsNumber()
dictCode: number;
@ApiProperty({ description: '字典类型' })
@IsNotEmpty({ message: '字典类型不能为空' })
@IsString()
dictType: string;
@ApiProperty({ description: '数据标签' })
@IsNotEmpty({ message: '数据标签不能为空' })
@IsString()
dictLabel: string;
@ApiProperty({ description: '数据键值' })
@IsNotEmpty({ message: '数据键值不能为空' })
@IsString()
dictValue?: string;
@ApiProperty({ description: '样式属性',required:false })
@IsOptional()
cssClass?: string;
@ApiProperty({ description: '回显样式',required:false })
@IsOptional()
listClass?: string;
@ApiProperty({ description: '显示排序' })
@IsNotEmpty({ message: '排序值不能为空' })
@Transform((v) => +v.value)
@IsNumber()
dictSort: number;
@ApiProperty({ description: '字典状态(0停用,1正常)',required:false })
@IsOptional()
status?: string = '1';
}
================================================
FILE: server/src/admin/system/dict-data/service/sys-dict-data.service.ts
================================================
import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { groupBy } from 'lodash';
import { redisUtils } from '@/common/utils/redisUtils';
import { Constants } from '@/common/constant/Constants';
import { queryDictDataDto } from '@/admin/system/dict-data/dto/queryDictDataDto';
import { Prisma } from '@prismaClient';
import { isNotEmpty } from 'class-validator';
import { CreateDictDataDto } from '@/admin/system/dict-data/dto/createDictDataDto';
import { updateDictDataDto } from '@/admin/system/dict-data/dto/updateDictDataDto';
import { exportTable } from '@/common/utils';
import { Response } from 'express';
@Injectable()
export class SysDictDataService implements OnModuleInit {
constructor(private prisma: PrismaService) {}
onModuleInit() {
this.initSysDictData();
}
//初始化字典数据
async initSysDictData() {
const dictData = groupBy(
await this.prisma.sysDictData.findMany(),
'dictType',
);
for (const dictKey in dictData) {
await redisUtils.set(
Constants.SYS_DICT_KEY + dictKey,
JSON.stringify(dictData[dictKey], null, 2),
);
}
console.log('字典信息初始化完毕!');
}
//根据字典类型更新redis字典数据
async updateCache(dictType: string) {
const dictDatas = await this.prisma.sysDictData.findMany({
where: {
dictType,
},
});
return await redisUtils.set(
Constants.SYS_DICT_KEY + dictType,
JSON.stringify(dictDatas, null, 2),
);
}
//查询字典数据列表
async selectDictDataList(q: queryDictDataDto) {
const queryCondition: Prisma.SysDictDataWhereInput = {};
if (isNotEmpty(q.dictType)) {
queryCondition.dictType = {
equals: q.dictType,
};
}
if (isNotEmpty(q.dictLabel)) {
queryCondition.dictLabel = {
contains: q.dictLabel,
};
}
if (isNotEmpty(q.status)) {
queryCondition.status = {
equals: q.status,
};
}
return {
rows: await this.prisma.sysDictData.findMany({
skip: (q.pageNum - 1) * q.pageSize,
take: q.pageSize,
where: queryCondition,
orderBy: {
dictSort: 'asc',
},
}),
total: await this.prisma.sysDictData.count({
where: queryCondition,
}),
};
}
//查询所有数据
async selectAllDictData() {
return await this.prisma.sysDictData.findMany();
}
//查询字典数据详细
async selectDictDataDetail(dictCode: number) {
return this.prisma.sysDictData.findUnique({
where: {
dictCode: dictCode,
},
});
}
//根据字典类型查询字典数据信息
async selectDictDataByDictType(dictType: string) {
return JSON.parse(
(await redisUtils.get(Constants.SYS_DICT_KEY + dictType)) || null,
);
}
//新增字典数据
async addDictData(dictData: CreateDictDataDto) {
const res = await this.prisma.sysDictData.create({
data: dictData,
});
await this.updateCache(dictData.dictType);
return res;
}
//修改字典数据
async updateDictData(dictData: updateDictDataDto) {
const res = await this.prisma.sysDictData.update({
where: {
dictCode: dictData.dictCode,
},
data: dictData,
});
await this.updateCache(dictData.dictType);
return res;
}
//删除字典数据
async deleteDictData(dictCodes: number[]) {
const dictType = (
await this.prisma.sysDictData.findFirst({
select: {
dictType: true,
},
where: {
dictCode: dictCodes[0],
},
})
).dictType;
const res = await this.prisma.sysDictData.deleteMany({
where: {
dictCode: {
in: dictCodes,
},
},
});
await this.updateCache(dictType);
return res;
}
//导出xlsx文件
async exportDictData(res: Response) {
const title = [
'字典编码',
'字典排序',
'字典标签',
'字典键值',
'字典类型',
'样式属性',
'表格回显样式',
'是否默认',
'状态',
'创建者',
'创建时间',
'更新者',
'更新时间',
'备注',
];
const data = (await this.prisma.sysDictData.findMany()).map((v) =>
Object.values(v),
);
data.unshift(title);
exportTable(data, res);
}
}
================================================
FILE: server/src/admin/system/dict-type/dict-type.controller.ts
================================================
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import {
Controller,
Get,
Req,
Post,
Put,
Delete,
Query,
Body,
Param,
ParseIntPipe,
Inject,
Res,
} from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { queryDictTypeDto } from './dto/queryDictTypeDto';
import Result from '@/common/result/Result';
import { SysDictTypeService } from './service/sys-dict-type.service';
import { CreateDictTypeDto } from './dto/createDictTypeDto';
import { updateDictTypeDto } from './dto/updateDictTypeDto';
import { nowDateTime } from '@/common/utils';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { Response } from 'express';
@ApiTags('字典类型')
@ApiBearerAuth()
@Controller('/system/dict/type')
export class DictTypeController {
@Inject()
private readonly dictTypeService: SysDictTypeService;
@ApiOperation({ summary: '查询字典类型列表' })
@RequirePermission('system:dict:query')
@Get('list')
async listType(@Query() q: queryDictTypeDto) {
return Result.TableData(await this.dictTypeService.selectDictTypeList(q));
}
@ApiOperation({ summary: '获取字典选择框列表' })
@Get('optionselect')
async optionselect() {
return Result.ok(await this.dictTypeService.selectAllDictType());
}
@ApiOperation({ summary: '导出xlsx文件' })
@Get('export')
async export(@Res() res: Response) {
this.dictTypeService.exportDictType(res);
}
@Get(':id')
@ApiOperation({ summary: '查询字典类型详细' })
async getType(@Param('id', ParseIntPipe) id: number) {
return Result.ok(await this.dictTypeService.selectDictTypeDetail(id));
}
@ApiOperation({ summary: '新增字典类型' })
@Post()
async addType(@Body() dictType: CreateDictTypeDto, @Req() req) {
dictType = {
...dictType,
createTime: nowDateTime(),
updateTime: nowDateTime(),
createBy: req.user?.userName,
updateBy: req.user?.userName,
};
await this.dictTypeService.addDictType(dictType);
return Result.ok('新增成功!');
}
@ApiOperation({ summary: '修改字典类型' })
@Put()
async updateType(@Body() dictType: updateDictTypeDto, @Req() req) {
dictType = {
...dictType,
updateTime: nowDateTime(),
updateBy: req.user?.userName,
};
await this.dictTypeService.updateDictType(dictType);
// 更新后刷新缓存
await this.dictTypeService.refreshDictCache();
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '刷新字典缓存' })
@Delete('refreshCache')
async refreshCache() {
await this.dictTypeService.refreshDictCache();
return Result.ok();
}
@ApiOperation({ summary: '删除字典类型' })
@Delete('/:ids')
async delType(@Param('ids', ParseIntArrayPipe) ids: number[]) {
const { count } = await this.dictTypeService.deleteDictType(ids);
return Result.toAjax(count);
}
}
================================================
FILE: server/src/admin/system/dict-type/dto/createDictTypeDto.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
export class CreateDictTypeDto extends BaseDomain {
@ApiProperty({ description: '字典名称' })
@IsNotEmpty({ message: '字典名称不能为空' })
@IsString()
dictName: string;
@ApiProperty({ description: '字典类型' })
@IsNotEmpty({ message: '字典类型不能为空' })
@IsString()
dictType: string;
@ApiProperty({ description: '字典状态(0停用,1正常)',required:false })
@IsOptional()
status?: string = '1';
}
================================================
FILE: server/src/admin/system/dict-type/dto/queryDictTypeDto.ts
================================================
import { queryDomain } from '@/common/domain/queryDomain';
import { ApiProperty } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator';
export class queryDictTypeDto extends queryDomain {
@ApiProperty({ description: '字典名称',required:false })
@IsString()
@IsOptional()
dictName?: string | null;
@ApiProperty({ description: '字典类型',required:false })
@IsString()
@IsOptional()
dictType?: string | null;
@ApiProperty({ description: '字典状态',required:false })
@IsString()
@IsOptional()
status?: string | null;
@ApiProperty({ description: '附加参数',required:false })
@IsOptional()
params: {
beginTime: string | null;
endTime: string | null;
};
}
================================================
FILE: server/src/admin/system/dict-type/dto/updateDictTypeDto.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsNumber, IsOptional, IsString } from 'class-validator';
export class updateDictTypeDto extends BaseDomain {
@ApiProperty({ description: '字典Id' })
@IsNotEmpty({ message: '字典Id不能为空' })
@IsNumber()
dictId: number;
@ApiProperty({ description: '字典名称' })
@IsNotEmpty({ message: '字典名称不能为空' })
@IsString()
dictName: string;
@ApiProperty({ description: '字典类型' })
@IsNotEmpty({ message: '字典类型不能为空' })
@IsString()
dictType: string;
@ApiProperty({ description: '字典状态(0停用,1正常)',required:false })
@IsOptional()
status?: string = '1';
}
================================================
FILE: server/src/admin/system/dict-type/service/sys-dict-type.service.ts
================================================
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { queryDictTypeDto } from '@/admin/system/dict-type/dto/queryDictTypeDto';
import { Prisma } from '@prismaClient';
import { isNotEmpty } from 'class-validator';
import { CreateDictTypeDto } from '@/admin/system/dict-type/dto/createDictTypeDto';
import { updateDictTypeDto } from '@/admin/system/dict-type/dto/updateDictTypeDto';
import { SysDictDataService } from '../../dict-data/service/sys-dict-data.service';
import { ValidationException } from '@/common/exception/ValidationException';
import { Response } from 'express';
import { exportTable } from '@/common/utils';
import { redisUtils } from '@/common/utils/redisUtils';
import { Constants } from '@/common/constant/Constants';
@Injectable()
export class SysDictTypeService {
constructor(
private prisma: PrismaService,
private dictDataService: SysDictDataService,
) {}
//查询字典类型列表
async selectDictTypeList(q: queryDictTypeDto) {
const queryCondition: Prisma.SysDictTypeWhereInput = {};
if (isNotEmpty(q.dictType)) {
queryCondition.dictType = {
contains: q.dictType,
};
}
if (isNotEmpty(q.dictName)) {
queryCondition.dictName = {
contains: q.dictName,
};
}
if (isNotEmpty(q.status)) {
queryCondition.status = {
equals: q.status,
};
}
if (isNotEmpty(q.params?.beginTime) && isNotEmpty(q.params?.endTime)) {
queryCondition.createTime = {
gte: q.params.beginTime,
lte: q.params.endTime,
};
}
return {
rows: await this.prisma.sysDictType.findMany({
skip: (q.pageNum - 1) * q.pageSize,
take: q.pageSize,
where: queryCondition,
}),
total: await this.prisma.sysDictType.count({
where: queryCondition,
}),
};
}
//查询所有数据
async selectAllDictType() {
return this.prisma.sysDictType.findMany();
}
//查询字典类型详细
async selectDictTypeDetail(dictId: number) {
return await this.prisma.sysDictType.findUnique({
where: {
dictId,
},
});
}
//新增字典类型
async addDictType(dictType: CreateDictTypeDto) {
const res = await this.prisma.sysDictType.create({
data: dictType,
});
await redisUtils.set(
Constants.SYS_DICT_KEY + dictType.dictType,
JSON.stringify([], null, 2),
);
return res;
}
//修改字典类型
async updateDictType(dictType: updateDictTypeDto) {
const old = await this.prisma.sysDictType.findUnique({
where: {
dictId: dictType.dictId,
},
include: {
dictDatas: true,
},
});
if (!old) return { count: 0 };
return this.prisma.$transaction(async (db) => {
//如果修改了dictType我们需要同步修改dictDatas中的dictType
if (old.dictType !== dictType.dictType) {
await db.sysDictData.updateMany({
where: {
dictType: old.dictType,
},
data: {
dictType: dictType.dictType,
},
});
}
const res = await db.sysDictType.update({
where: {
dictId: dictType.dictId,
},
data: dictType,
});
await this.dictDataService.updateCache(dictType.dictType);
return res;
});
}
//删除字典类型
async deleteDictType(dictIds: number[]) {
const dictTypes = new Set();
for (const id of dictIds) {
const r = await this.prisma.sysDictType.findUnique({
where: {
dictId: id,
},
include: {
dictDatas: true,
},
});
//如果当前字典类型里面存有子数据,不能删除
if (r?.dictDatas?.length) {
throw new ValidationException('当前字典类型下有子数据,不能删除');
}
dictTypes.add(Constants.SYS_DICT_KEY + r.dictType);
}
const res = await this.prisma.sysDictType.deleteMany({
where: {
dictId: {
in: dictIds,
},
},
});
for (const k of dictTypes) {
await redisUtils.del(k);
}
return res;
}
//刷新字典缓存
async refreshDictCache() {
return await this.dictDataService.initSysDictData();
}
//导出字典类型为xlsx
async exportDictType(res: Response) {
const title = [
'字典主键',
'字典名称',
'字典类型',
'状态',
'创建者',
'创建时间',
'更新者',
'更新时间',
'备注',
];
const data = (await this.prisma.sysDictType.findMany()).map((v) =>
Object.values(v),
);
data.unshift(title);
exportTable(data, res);
}
}
================================================
FILE: server/src/admin/system/logininfor/dto/index.ts
================================================
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNotEmpty, IsNumber, IsString, IsOptional } from 'class-validator';
import { queryDomain } from '@/common/domain/queryDomain';
/**@description 查询登录日志Dto */
export class QuerySysLogininforDto extends queryDomain {
@ApiProperty({ description: '用户账号',required:false })
@IsOptional()
userName: string | null;
@ApiProperty({ description: '登录IP地址',required:false })
@IsOptional()
ipaddr: string | null;
@ApiProperty({ description: '登录地点',required:false })
@IsOptional()
loginLocation: string | null;
@ApiProperty({ description: '浏览器类型',required:false })
@IsOptional()
browser: string | null;
@ApiProperty({ description: '操作系统',required:false })
@IsOptional()
os: string | null;
@ApiProperty({ description: '登录状态(0失败,1成功)',required:false })
@IsOptional()
status: string | null;
@ApiProperty({ description: '提示消息',required:false })
@IsOptional()
msg: string | null;
@ApiProperty({ description: '登录时间排序 descending|ascending',required:false })
@IsOptional()
isAsc: string | null;
}
/**@description 创建登录日志Dto */
export class CreateSysLogininforDto {
@ApiProperty({ description: '用户账号',required:false })
@IsOptional()
@IsString()
userName?: string;
@ApiProperty({ description: '登录IP地址',required:false })
@IsOptional()
@IsString()
ipaddr?: string;
@ApiProperty({ description: '登录地点',required:false })
@IsOptional()
@IsString()
loginLocation?: string;
@ApiProperty({ description: '浏览器类型',required:false })
@IsOptional()
@IsString()
browser?: string;
@ApiProperty({ description: '操作系统',required:false })
@IsOptional()
@IsString()
os?: string;
@ApiProperty({ description: '登录状态(0失败,1成功)',required:false })
@IsOptional()
@IsString()
status?: string;
@ApiProperty({ description: '提示消息',required:false })
@IsOptional()
@IsString()
msg?: string;
@ApiProperty({ description: '访问时间',required:false })
@IsOptional()
@IsString()
loginTime?: string;
}
/**@description 更新登录日志Dto */
export class UpdateSysLogininforDto {
@ApiProperty({ description: '访问ID' })
@IsNotEmpty({ message: '访问ID不能为空' })
@Transform((v) => +v.value)
@IsNumber()
infoId: number;
@ApiProperty({ description: '用户账号',required:false })
@IsOptional()
@IsString()
userName?: string;
@ApiProperty({ description: '登录IP地址',required:false })
@IsOptional()
@IsString()
ipaddr?: string;
@ApiProperty({ description: '登录地点',required:false })
@IsOptional()
@IsString()
loginLocation?: string;
@ApiProperty({ description: '浏览器类型',required:false })
@IsOptional()
@IsString()
browser?: string;
@ApiProperty({ description: '操作系统',required:false })
@IsOptional()
@IsString()
os?: string;
@ApiProperty({ description: '登录状态(0失败,1成功)',required:false })
@IsOptional()
@IsString()
status?: string;
@ApiProperty({ description: '提示消息',required:false })
@IsOptional()
@IsString()
msg?: string;
@ApiProperty({ description: '访问时间',required:false })
@IsOptional()
@IsString()
loginTime?: string;
}
================================================
FILE: server/src/admin/system/logininfor/service/sys-logininfor.service.ts
================================================
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { Response } from 'express';
import { exportTable } from '@/common/utils';
import {
QuerySysLogininforDto,
CreateSysLogininforDto,
UpdateSysLogininforDto,
} from '../dto/index';
import { Prisma } from '@prismaClient';
import { isNotEmpty } from 'class-validator';
@Injectable()
export class LogininforService {
constructor(private prisma: PrismaService) {}
/**@description 查询登录日志所有 */
async selectLogininforAll() {
return this.prisma.sysLogininfor.findMany();
}
/**@description 分页查询登录日志列表 */
async selectLogininforList(q: QuerySysLogininforDto) {
const queryCondition: Prisma.SysLogininforWhereInput = {};
const order: 'asc' | 'desc' = q.isAsc === 'ascending' ? 'asc' : 'desc';
if (isNotEmpty(q['userName'])) {
queryCondition.userName = {
contains: q.userName,
};
}
if (isNotEmpty(q['ipaddr'])) {
queryCondition.ipaddr = {
contains: q.ipaddr,
};
}
if (isNotEmpty(q['loginLocation'])) {
queryCondition.loginLocation = {
equals: q.loginLocation,
};
}
if (isNotEmpty(q['browser'])) {
queryCondition.browser = {
equals: q.browser,
};
}
if (isNotEmpty(q['os'])) {
queryCondition.os = {
equals: q.os,
};
}
if (isNotEmpty(q['status'])) {
queryCondition.status = {
equals: q.status,
};
}
if (isNotEmpty(q['msg'])) {
queryCondition.msg = {
equals: q.msg,
};
}
if (
isNotEmpty(q.params.beginLoginTime) &&
isNotEmpty(q.params.endLoginTime)
) {
queryCondition.loginTime = {
lte: q.params.endLoginTime,
gte: q.params.beginLoginTime,
};
}
return {
rows: await this.prisma.sysLogininfor.findMany({
skip: (q.pageNum - 1) * q.pageSize,
take: q.pageSize,
orderBy: {
loginTime: order,
},
where: queryCondition,
}),
total: await this.prisma.sysLogininfor.count({
where: queryCondition,
}),
};
}
/**@description 查询登录日志详情 */
async selectLogininforByInfoId(infoId: number) {
return this.prisma.sysLogininfor.findUnique({
where: {
infoId,
},
});
}
/**@description 新增登录日志 */
async addLogininfor(sysLogininfor: CreateSysLogininforDto) {
//删除掉空值
for (const key in sysLogininfor) {
!isNotEmpty(sysLogininfor[key]) && delete sysLogininfor[key];
}
return await this.prisma.sysLogininfor.create({
data: sysLogininfor,
});
}
/**@description 修改登录日志 */
async updateLogininfor(sysLogininfor: UpdateSysLogininforDto) {
//删除掉空值
for (const key in sysLogininfor) {
!isNotEmpty(sysLogininfor[key]) && delete sysLogininfor[key];
}
return await this.prisma.sysLogininfor.update({
where: {
infoId: sysLogininfor.infoId,
},
data: sysLogininfor,
});
}
/** @description 清空所有 */
async clear() {
return this.prisma.sysLogininfor.deleteMany();
}
/**@description 批量删除登录日志 */
async deleteLogininforByInfoIds(infoIds: number[]) {
return this.prisma.sysLogininfor.deleteMany({
where: {
infoId: {
in: infoIds,
},
},
});
}
/**@description 单个删除登录日志 */
async deleteLogininforByInfoId(infoId: number) {
return this.prisma.sysLogininfor.delete({
where: {
infoId,
},
});
}
/**@description 导出登录日志所有数据为xlsx */
async exportLogininfor(res: Response) {
const title = [
'访问ID',
'用户账号',
'登录IP地址',
'登录地点',
'浏览器类型',
'操作系统',
'登录状态(0失败,1成功)',
'提示消息',
'访问时间',
];
const data = (await this.prisma.sysLogininfor.findMany()).map((v) =>
Object.values(v),
);
data.unshift(title);
exportTable(data, res);
}
}
================================================
FILE: server/src/admin/system/logininfor/sys-logininfor.controller.ts
================================================
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Post,
Put,
Query,
Res,
} from '@nestjs/common';
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import Result from '@/common/result/Result';
import {
ApiBearerAuth,
ApiBody,
ApiOperation,
ApiQuery,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { LogininforService } from './service/sys-logininfor.service';
import {
QuerySysLogininforDto,
CreateSysLogininforDto,
UpdateSysLogininforDto,
} from './dto/index';
import { Response } from 'express';
import { SysLogininfor } from '@prismaClient';
import { TableDataInfo } from '@/common/domain/TableDataInfo';
@ApiTags('登录日志')
@ApiBearerAuth()
@Controller('monitor/logininfor')
export class SysLogininforController {
constructor(private logininforService: LogininforService) {}
@ApiOperation({ summary: '查询登录日志列表' })
@ApiResponse({ type: TableDataInfo })
@RequirePermission('monitor:logininfor:query')
@Get('/list')
async listLogininfor(
@Query() q: QuerySysLogininforDto,
): Promise> {
return Result.TableData(
await this.logininforService.selectLogininforList(q),
);
}
@ApiOperation({ summary: '清空登录日志' })
@Delete('/clean')
async clearInfo(): Promise> {
await this.logininforService.clear();
return Result.ok();
}
@ApiOperation({ summary: '导出登录日志xlsx文件' })
@RequirePermission('monitor:logininfor:export')
@Get('/export')
async export(@Res() res: Response): Promise {
return this.logininforService.exportLogininfor(res);
}
@ApiOperation({ summary: '查询登录日志详细' })
@ApiResponse({ type: Result })
@RequirePermission('monitor:logininfor:query')
@Get('/:infoId')
async getLogininfor(
@Param('infoId', ParseIntPipe) infoId: number,
): Promise> {
return Result.ok(
await this.logininforService.selectLogininforByInfoId(infoId),
);
}
@ApiOperation({ summary: '新增登录日志' })
@ApiResponse({ type: Result })
@ApiBody({ type: CreateSysLogininforDto })
@RequirePermission('monitor:logininfor:add')
@Post('/')
async addLogininfor(
@Body() sysLogininfor: CreateSysLogininforDto,
): Promise> {
return Result.ok(await this.logininforService.addLogininfor(sysLogininfor));
}
@ApiOperation({ summary: '修改登录日志' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysLogininforDto })
@RequirePermission('monitor:logininfor:edit')
@Put('/')
async updateLogininfor(
@Body() sysLogininfor: UpdateSysLogininforDto,
): Promise> {
await this.logininforService.updateLogininfor(sysLogininfor);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '删除登录日志' })
@ApiResponse({ type: Result })
@RequirePermission('monitor:logininfor:remove')
@Delete('/:ids')
async delLogininfor(
@Param('ids', ParseIntArrayPipe) infoIds: number[],
): Promise> {
const { count } =
await this.logininforService.deleteLogininforByInfoIds(infoIds);
return Result.toAjax(count);
}
}
================================================
FILE: server/src/admin/system/menu/dto/index.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNotEmpty, IsNumber, IsString, IsOptional } from 'class-validator';
import { queryDomain } from '@/common/domain/queryDomain';
/**@description 查询菜单管理Dto */
export class QuerySysMenuDto extends queryDomain {
@ApiProperty({ description: '菜单名称',required:false })
@IsOptional()
menuName: string | null;
@ApiProperty({ description: '显示顺序',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
orderNum: number | null;
@ApiProperty({ description: '路由地址',required:false })
@IsOptional()
path: string | null;
@ApiProperty({ description: '组件路径',required:false })
@IsOptional()
component: string | null;
@ApiProperty({ description: '路由参数',required:false })
@IsOptional()
query: string | null;
@ApiProperty({ description: '是否为外链(0否 1是)',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
isFrame: number | null;
@ApiProperty({ description: '是否缓存(0不缓存 1缓存)',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
isCache: number | null;
@ApiProperty({ description: '菜单类型(M目录 C菜单 F按钮)',required:false })
@IsOptional()
menuType: string | null;
@ApiProperty({ description: '菜单状态(0隐藏 1显示)',required:false })
@IsOptional()
visible: string | null;
@ApiProperty({ description: '菜单状态(0停用 1正常)',required:false })
@IsOptional()
status: string | null;
@ApiProperty({ description: '权限标识',required:false })
@IsOptional()
perms: string | null;
@ApiProperty({ description: '菜单图标',required:false })
@IsOptional()
icon: string | null;
}
/**@description 创建菜单管理Dto */
export class CreateSysMenuDto extends BaseDomain {
@ApiProperty({ description: '菜单名称' })
@IsNotEmpty({ message: '菜单名称不能为空' })
@IsString()
menuName: string;
@ApiProperty({ description: '父菜单ID',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
parentId?: number;
@ApiProperty({ description: '显示顺序' })
@IsNotEmpty({ message: '显示顺序不能为空' })
@Transform((v) => +v.value)
@IsNumber()
orderNum: number;
@ApiProperty({ description: '路由地址' })
@IsNotEmpty({ message: '路由地址不能为空' })
@IsString()
path: string;
@ApiProperty({ description: '组件路径',required:false })
@IsOptional()
@IsString()
component?: string;
@ApiProperty({ description: '路由参数',required:false })
@IsOptional()
@IsString()
query?: string;
@ApiProperty({ description: '是否为外链(0否 1是)',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
isFrame?: number;
@ApiProperty({ description: '是否缓存(0不缓存 1缓存)',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
isCache?: number;
@ApiProperty({ description: '菜单类型(M目录 C菜单 F按钮)',required:false })
@IsOptional()
@IsString()
menuType?: string;
@ApiProperty({ description: '菜单状态(0隐藏 1显示)',required:false })
@IsOptional()
@IsString()
visible?: string;
@ApiProperty({ description: '菜单状态(0停用 1正常)',required:false })
@IsOptional()
@IsString()
status?: string;
@ApiProperty({ description: '权限标识',required:false })
@IsOptional()
@IsString()
perms?: string;
@ApiProperty({ description: '菜单图标',required:false })
@IsOptional()
@IsString()
icon?: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
}
/**@description 更新菜单管理Dto */
export class UpdateSysMenuDto extends BaseDomain {
@ApiProperty({ description: '菜单ID' })
@IsNotEmpty({ message: '菜单ID不能为空' })
@Transform((v) => +v.value)
@IsNumber()
menuId: number;
@ApiProperty({ description: '菜单名称' })
@IsNotEmpty({ message: '菜单名称不能为空' })
@IsString()
menuName: string;
@ApiProperty({ description: '父菜单ID',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
parentId?: number;
@ApiProperty({ description: '显示顺序' })
@IsNotEmpty({ message: '显示顺序不能为空' })
@Transform((v) => +v.value)
@IsNumber()
orderNum: number;
@ApiProperty({ description: '路由地址' })
@IsNotEmpty({ message: '路由地址不能为空' })
@IsString()
path: string;
@ApiProperty({ description: '组件路径',required:false })
@IsOptional()
@IsString()
component?: string;
@ApiProperty({ description: '路由参数',required:false })
@IsOptional()
@IsString()
query?: string;
@ApiProperty({ description: '是否为外链(0否 1是)',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
isFrame?: number;
@ApiProperty({ description: '是否缓存(0不缓存 1缓存)',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
isCache?: number;
@ApiProperty({ description: '菜单类型(M目录 C菜单 F按钮)',required:false })
@IsOptional()
@IsString()
menuType?: string;
@ApiProperty({ description: '菜单状态(0隐藏 1显示)',required:false })
@IsOptional()
@IsString()
visible?: string;
@ApiProperty({ description: '菜单状态(0停用 1正常)',required:false })
@IsOptional()
@IsString()
status?: string;
@ApiProperty({ description: '权限标识',required:false })
@IsOptional()
@IsString()
perms?: string;
@ApiProperty({ description: '菜单图标',required:false })
@IsOptional()
@IsString()
icon?: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
}
================================================
FILE: server/src/admin/system/menu/dto/queryMenuDto.ts
================================================
import { ApiProperty } from '@nestjs/swagger';
export class queryMenuDto {
@ApiProperty({ description: '菜单名称' })
menuName: string | null;
@ApiProperty({ description: '菜单状态' })
status: string | null;
}
================================================
FILE: server/src/admin/system/menu/service/sys-menu.service.ts
================================================
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { Response } from 'express';
import { exportTable, tree } from '@/common/utils';
import {
QuerySysMenuDto,
CreateSysMenuDto,
UpdateSysMenuDto,
} from '../dto/index';
import { Prisma } from '@prismaClient';
import { isNotEmpty } from 'class-validator';
import * as assert from 'assert';
@Injectable()
export class MenuService {
constructor(private prisma: PrismaService) {}
/**@description 查询菜单管理所有 */
async selectMenuAll() {
return this.prisma.sysMenu.findMany();
}
/**@description 查询菜单管理列表 */
async selectMenuList(q: QuerySysMenuDto) {
const queryCondition: Prisma.SysMenuWhereInput = {};
if (isNotEmpty(q['menuName'])) {
queryCondition.menuName = {
contains: q.menuName,
};
}
if (isNotEmpty(q['orderNum'])) {
queryCondition.orderNum = {
equals: q.orderNum,
};
}
if (isNotEmpty(q['path'])) {
queryCondition.path = {
equals: q.path,
};
}
if (isNotEmpty(q['component'])) {
queryCondition.component = {
equals: q.component,
};
}
if (isNotEmpty(q['query'])) {
queryCondition.query = {
equals: q.query,
};
}
if (isNotEmpty(q['isFrame'])) {
queryCondition.isFrame = {
equals: q.isFrame,
};
}
if (isNotEmpty(q['isCache'])) {
queryCondition.isCache = {
equals: q.isCache,
};
}
if (isNotEmpty(q['menuType'])) {
queryCondition.menuType = {
equals: q.menuType,
};
}
if (isNotEmpty(q['visible'])) {
queryCondition.visible = {
equals: q.visible,
};
}
if (isNotEmpty(q['status'])) {
queryCondition.status = {
equals: q.status,
};
}
if (isNotEmpty(q['perms'])) {
queryCondition.perms = {
equals: q.perms,
};
}
if (isNotEmpty(q['icon'])) {
queryCondition.icon = {
equals: q.icon,
};
}
return this.prisma.sysMenu.findMany({
where: queryCondition,
orderBy: {
orderNum: 'asc',
},
});
}
/**@description 查询菜单管理详情 */
async selectMenuByMenuId(menuId: number) {
return this.prisma.sysMenu.findUnique({
where: {
menuId,
},
});
}
/**@description 新增菜单管理 */
async addMenu(sysMenu: CreateSysMenuDto) {
//删除掉空值
for (const key in sysMenu) {
!isNotEmpty(sysMenu[key]) && delete sysMenu[key];
}
return await this.prisma.sysMenu.create({
data: sysMenu,
});
}
/**@description 修改菜单管理 */
async updateMenu(sysMenu: UpdateSysMenuDto) {
//删除掉空值
for (const key in sysMenu) {
!isNotEmpty(sysMenu[key]) && delete sysMenu[key];
}
return await this.prisma.sysMenu.update({
where: {
menuId: sysMenu.menuId,
},
data: sysMenu,
});
}
/**@description 批量删除菜单管理 */
async deleteMenuByMenuIds(menuIds: number[]) {
const menu = await this.prisma.sysMenu.findFirst({
where: {
parentId: {
in: menuIds,
},
menuType: {
in: ['M', 'C'],
},
},
});
assert(!menu, '存在子菜单,不允许删除!');
const menu1 = await this.prisma.sysRoleMenu.findFirst({
where: { menuId: { in: menuIds } },
});
assert(!menu1, '菜单已被分配,不允许删除!');
return this.prisma.sysMenu.deleteMany({
where: {
OR: [
{
menuId: { in: menuIds },
},
{
menuType: 'F',
parentId: { in: menuIds },
},
],
},
});
}
/**@description 单个删除菜单管理 */
async deleteMenuByMenuId(menuId: number) {
const menu = await this.prisma.sysMenu.findFirst({
where: {
parentId: menuId,
menuType: {
in: ['M', 'C'],
},
},
});
assert(!menu, '存在子菜单,不允许删除!');
const menu1 = await this.prisma.sysRoleMenu.findFirst({
where: { menuId },
});
assert(!menu1, '菜单已被分配,不允许删除!');
return this.prisma.sysMenu.deleteMany({
where: {
OR: [
{
menuId,
},
{
menuType: 'F',
parentId: menuId,
},
],
},
});
}
/**@description 导出菜单管理所有数据为xlsx */
async exportMenu(res: Response) {
const title = [
'菜单ID',
'菜单名称',
'父菜单ID',
'显示顺序',
'路由地址',
'组件路径',
'路由参数',
'是否为外链(0否 1是)',
'是否缓存(0不缓存 1缓存)',
'菜单类型(M目录 C菜单 F按钮)',
'菜单状态(0隐藏 1显示)',
'菜单状态(0停用 1正常)',
'权限标识',
'菜单图标',
'创建者',
'创建时间',
'更新者',
'更新时间',
'备注',
];
const data = (await this.prisma.sysMenu.findMany()).map((v) =>
Object.values(v),
);
data.unshift(title);
exportTable(data, res);
}
async selectMenuTree() {
const menus = tree(
(await this.prisma.sysMenu.findMany()).map((v) => ({
id: v.menuId,
label: v.menuName,
pid: v.parentId,
})),
);
return menus;
}
async roleMenuTreeselect(roleId: number) {
const menus = await this.selectMenuTree();
const checkedKeys = (
await this.prisma.sysRoleMenu.findMany({ where: { roleId } })
).map((v) => v.menuId);
return { menus, checkedKeys };
}
}
================================================
FILE: server/src/admin/system/menu/sys-menu.controller.ts
================================================
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Post,
Put,
Query,
Req,
Res,
} from '@nestjs/common';
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import Result from '@/common/result/Result';
import {
ApiBearerAuth,
ApiBody,
ApiOperation,
ApiQuery,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { nowDateTime } from '@/common/utils';
import { MenuService } from './service/sys-menu.service';
import {
QuerySysMenuDto,
CreateSysMenuDto,
UpdateSysMenuDto,
} from './dto/index';
import { Response } from 'express';
import { SysMenu } from '@prismaClient';
@ApiTags('菜单管理')
@ApiBearerAuth()
@Controller('system/menu')
export class SysMenuController {
constructor(private menuService: MenuService) {}
@ApiOperation({ summary: '获取树形菜单选项' })
@RequirePermission('system:menu:query')
@Get('/treeselect')
async listMenuTree() {
return Result.ok(await this.menuService.selectMenuTree());
}
@ApiOperation({ summary: '获取树形菜单选项' })
@RequirePermission('system:menu:edit')
@Get('/roleMenuTreeselect/:menuId')
async roleMenuTreeselect(@Param('menuId', ParseIntPipe) menuId: number) {
return {
...Result.ok(),
...(await this.menuService.roleMenuTreeselect(menuId)),
};
}
@ApiOperation({ summary: '查询菜单管理列表' })
@ApiResponse({ type: Result })
@RequirePermission('system:menu:query')
@Get('/list')
async listMenu(@Query() q: QuerySysMenuDto): Promise> {
return Result.ok(await this.menuService.selectMenuList(q));
}
@ApiOperation({ summary: '导出菜单管理xlsx文件' })
@RequirePermission('system:menu:export')
@Get('/export')
async export(@Res() res: Response): Promise {
return this.menuService.exportMenu(res);
}
@ApiOperation({ summary: '查询菜单管理详细' })
@ApiResponse({ type: Result })
@RequirePermission('system:menu:query')
@Get('/:menuId')
async getMenu(
@Param('menuId', ParseIntPipe) menuId: number,
): Promise> {
return Result.ok(await this.menuService.selectMenuByMenuId(menuId));
}
@ApiOperation({ summary: '新增菜单管理' })
@ApiResponse({ type: Result })
@ApiBody({ type: CreateSysMenuDto })
@RequirePermission('system:menu:add')
@Post('/')
async addMenu(
@Body() sysMenu: CreateSysMenuDto,
@Req() req,
): Promise> {
sysMenu = {
...sysMenu,
createTime: nowDateTime(),
updateTime: nowDateTime(),
createBy: req.user?.userName,
updateBy: req.user?.userName,
};
return Result.ok(await this.menuService.addMenu(sysMenu));
}
@ApiOperation({ summary: '修改菜单管理' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysMenuDto })
@RequirePermission('system:menu:edit')
@Put('/')
async updateMenu(
@Body() sysMenu: UpdateSysMenuDto,
@Req() req,
): Promise> {
sysMenu = {
...sysMenu,
updateTime: nowDateTime(),
updateBy: req.user?.userName,
};
await this.menuService.updateMenu(sysMenu);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '删除菜单管理' })
@ApiResponse({ type: Result })
@RequirePermission('system:menu:remove')
@Delete('/:ids')
async delMenu(
@Param('ids', ParseIntArrayPipe) menuIds: number[],
): Promise> {
const { count } = await this.menuService.deleteMenuByMenuIds(menuIds);
return Result.toAjax(count);
}
}
================================================
FILE: server/src/admin/system/monitor/monitor.controller.ts
================================================
import { Constants } from '@/common/constant/Constants';
import Result from '@/common/result/Result';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { redisUtils } from '@/common/utils/redisUtils';
import { getServerInfo } from '@/common/utils/systemInfo';
import {
Controller,
Delete,
Get,
Param,
ParseArrayPipe,
Query,
} from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { Throttle } from '@nestjs/throttler';
@ApiTags('系统监控')
@ApiBearerAuth()
@Controller('/monitor')
export class monitorController {
constructor() {}
@ApiOperation({ summary: '获取redis信息' })
@Throttle({
default: {
limit: 10,
ttl: 1000 * 60,
},
})
@Get('/cache')
async getCacheInfo() {
return Result.ok(await redisUtils.getRedisInfo());
}
@ApiOperation({ summary: '获取服务器信息' })
@Throttle({
default: {
limit: 10,
ttl: 1000 * 60,
},
})
@Get('/server')
async getInfo() {
return Result.ok(await getServerInfo());
}
@ApiOperation({ summary: '获取在线用户信息' })
@Throttle({
default: {
limit: 20,
ttl: 1000 * 60,
},
})
@RequirePermission('monitor:online:query')
@Get('/online/list')
async getOnlineList(@Query() { ipaddr = '', userName = '' }) {
const tokens = await redisUtils.scanStream(Constants.LOGIN_TOKEN_KEY + '*');
if (!tokens.length) {
return Result.TableData({
rows: [],
total: 0,
});
}
let userList = (await redisUtils.mget(tokens)).map((v) => JSON.parse(v));
userList = userList.filter(
(v) => v.loginLocation.includes(ipaddr) && v.userName.includes(userName),
);
userList.sort((a, b) => +new Date(b.loginTime) - +new Date(a.loginTime));
return Result.TableData({
rows: userList,
total: userList.length,
});
}
@ApiOperation({ summary: '强退用户' })
@Throttle({
default: {
limit: 20,
ttl: 1000 * 60,
},
})
@RequirePermission('monitor:online:batchLogout')
@Delete('/online/:tokenId')
async forceLogout(@Param('tokenId', ParseArrayPipe) tokenIds: string[]) {
for (const tokenId of tokenIds) {
const user = JSON.parse(
(await redisUtils.get(Constants.LOGIN_TOKEN_KEY + tokenId)) || null,
);
if (user) {
//不可强退超级管理员
if (user.userId === 1) return Result.Error('不可强退超级管理员!');
await redisUtils.del(Constants.LOGIN_TOKEN_KEY + tokenId);
}
}
return Result.ok('操作成功!');
}
}
================================================
FILE: server/src/admin/system/notice/dto/index.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNotEmpty, IsNumber, IsString, IsOptional } from 'class-validator';
import { queryDomain } from '@/common/domain/queryDomain';
/**@description 查询通知公告表Dto */
export class QuerySysNoticeDto extends queryDomain {
@ApiProperty({ description: '公告标题',required:false })
@IsOptional()
noticeTitle: string | null;
@ApiProperty({ description: '公告类型(1通知 2公告)',required:false })
@IsOptional()
noticeType: string | null;
@ApiProperty({ description: '公告状态(0关闭 1正常)',required:false })
@IsOptional()
status: string | null;
}
/**@description 创建通知公告表Dto */
export class CreateSysNoticeDto extends BaseDomain {
@ApiProperty({ description: '公告标题' })
@IsNotEmpty({ message: '公告标题不能为空' })
@IsString()
noticeTitle: string;
@ApiProperty({ description: '公告类型(1通知 2公告)' })
@IsNotEmpty({ message: '公告类型(1通知 2公告)不能为空' })
@IsString()
noticeType: string;
@ApiProperty({ description: '公告内容',required:false })
@IsOptional()
@IsString()
noticeContent?: string;
@ApiProperty({ description: '公告状态(0关闭 1正常)',required:false })
@IsOptional()
@IsString()
status?: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
}
/**@description 更新通知公告表Dto */
export class UpdateSysNoticeDto extends BaseDomain {
@ApiProperty({ description: '公告ID' })
@IsNotEmpty({ message: '公告ID不能为空' })
@Transform((v) => +v.value)
@IsNumber()
noticeId: number;
@ApiProperty({ description: '公告标题' })
@IsNotEmpty({ message: '公告标题不能为空' })
@IsString()
noticeTitle: string;
@ApiProperty({ description: '公告类型(1通知 2公告)' })
@IsNotEmpty({ message: '公告类型(1通知 2公告)不能为空' })
@IsString()
noticeType: string;
@ApiProperty({ description: '公告内容',required:false })
@IsOptional()
@IsString()
noticeContent?: string;
@ApiProperty({ description: '公告状态(0关闭 1正常)',required:false })
@IsOptional()
@IsString()
status?: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
}
================================================
FILE: server/src/admin/system/notice/service/sys-notice.service.ts
================================================
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { Response } from 'express';
import { exportTable } from '@/common/utils';
import {
QuerySysNoticeDto,
CreateSysNoticeDto,
UpdateSysNoticeDto,
} from '../dto/index';
import { Prisma } from '@prismaClient';
import { isNotEmpty } from 'class-validator';
@Injectable()
export class NoticeService {
constructor(private prisma: PrismaService) {}
/**@description 查询通知公告表所有 */
async selectNoticeAll() {
return this.prisma.sysNotice.findMany();
}
/**@description 分页查询通知公告表列表 */
async selectNoticeList(q: QuerySysNoticeDto) {
const queryCondition: Prisma.SysNoticeWhereInput = {};
if (isNotEmpty(q['noticeTitle'])) {
queryCondition.noticeTitle = {
equals: q.noticeTitle,
};
}
if (isNotEmpty(q['noticeType'])) {
queryCondition.noticeType = {
equals: q.noticeType,
};
}
if (isNotEmpty(q['status'])) {
queryCondition.status = {
equals: q.status,
};
}
return {
rows: await this.prisma.sysNotice.findMany({
skip: (q.pageNum - 1) * q.pageSize,
take: q.pageSize,
where: queryCondition,
}),
total: await this.prisma.sysNotice.count({
where: queryCondition,
}),
};
}
/**@description 查询通知公告表详情 */
async selectNoticeByNoticeId(noticeId: number) {
return this.prisma.sysNotice.findUnique({
where: {
noticeId,
},
});
}
/**@description 新增通知公告表 */
async addNotice(sysNotice: CreateSysNoticeDto) {
//删除掉空值
for (const key in sysNotice) {
!isNotEmpty(sysNotice[key]) && delete sysNotice[key];
}
return await this.prisma.sysNotice.create({
data: sysNotice,
});
}
/**@description 修改通知公告表 */
async updateNotice(sysNotice: UpdateSysNoticeDto) {
//删除掉空值
for (const key in sysNotice) {
!isNotEmpty(sysNotice[key]) && delete sysNotice[key];
}
return await this.prisma.sysNotice.update({
where: {
noticeId: sysNotice.noticeId,
},
data: sysNotice,
});
}
/**@description 批量删除通知公告表 */
async deleteNoticeByNoticeIds(noticeIds: number[]) {
return this.prisma.sysNotice.deleteMany({
where: {
noticeId: {
in: noticeIds,
},
},
});
}
/**@description 单个删除通知公告表 */
async deleteNoticeByNoticeId(noticeId: number) {
return this.prisma.sysNotice.delete({
where: {
noticeId,
},
});
}
/**@description 导出通知公告表所有数据为xlsx */
async exportNotice(res: Response) {
const title = [
'公告ID',
'公告标题',
'公告类型(1通知 2公告)',
'公告内容',
'公告状态(0关闭 1正常)',
'创建者',
'创建时间',
'更新者',
'更新时间',
'备注',
];
const data = (await this.prisma.sysNotice.findMany()).map((v) =>
Object.values(v),
);
data.unshift(title);
exportTable(data, res);
}
}
================================================
FILE: server/src/admin/system/notice/sys-notice.controller.ts
================================================
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Post,
Put,
Query,
Req,
Res,
} from '@nestjs/common';
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import Result from '@/common/result/Result';
import {
ApiBearerAuth,
ApiBody,
ApiOperation,
ApiQuery,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { nowDateTime } from '@/common/utils';
import { NoticeService } from './service/sys-notice.service';
import {
QuerySysNoticeDto,
CreateSysNoticeDto,
UpdateSysNoticeDto,
} from './dto/index';
import { Response } from 'express';
import { SysNotice } from '@prismaClient';
import { TableDataInfo } from '@/common/domain/TableDataInfo';
@ApiTags('通知公告表')
@ApiBearerAuth()
@Controller('system/notice')
export class SysNoticeController {
constructor(private noticeService: NoticeService) {}
@ApiOperation({ summary: '查询通知公告表列表' })
@ApiResponse({ type: TableDataInfo })
@RequirePermission('system:notice:query')
@Get('/list')
async listNotice(
@Query() q: QuerySysNoticeDto,
): Promise> {
return Result.TableData(await this.noticeService.selectNoticeList(q));
}
@ApiOperation({ summary: '导出通知公告表xlsx文件' })
@RequirePermission('system:notice:export')
@Get('/export')
async export(@Res() res: Response): Promise {
return this.noticeService.exportNotice(res);
}
@ApiOperation({ summary: '查询通知公告表详细' })
@ApiResponse({ type: Result })
@RequirePermission('system:notice:query')
@Get('/:noticeId')
async getNotice(
@Param('noticeId', ParseIntPipe) noticeId: number,
): Promise> {
return Result.ok(await this.noticeService.selectNoticeByNoticeId(noticeId));
}
@ApiOperation({ summary: '新增通知公告表' })
@ApiResponse({ type: Result })
@ApiBody({ type: CreateSysNoticeDto })
@RequirePermission('system:notice:add')
@Post('/')
async addNotice(
@Body() sysNotice: CreateSysNoticeDto,
@Req() req,
): Promise> {
sysNotice = {
...sysNotice,
createTime: nowDateTime(),
updateTime: nowDateTime(),
createBy: req.user?.userName,
updateBy: req.user?.userName,
};
return Result.ok(await this.noticeService.addNotice(sysNotice));
}
@ApiOperation({ summary: '修改通知公告表' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysNoticeDto })
@RequirePermission('system:notice:edit')
@Put('/')
async updateNotice(
@Body() sysNotice: UpdateSysNoticeDto,
@Req() req,
): Promise> {
sysNotice = {
...sysNotice,
updateTime: nowDateTime(),
updateBy: req.user?.userName,
};
await this.noticeService.updateNotice(sysNotice);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '删除通知公告表' })
@ApiResponse({ type: Result })
@RequirePermission('system:notice:remove')
@Delete('/:ids')
async delNotice(
@Param('ids', ParseIntArrayPipe) noticeIds: number[],
): Promise> {
const { count } =
await this.noticeService.deleteNoticeByNoticeIds(noticeIds);
return Result.toAjax(count);
}
}
================================================
FILE: server/src/admin/system/post/dto/index.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNotEmpty, IsNumber, IsString, IsOptional } from 'class-validator';
import { queryDomain } from '@/common/domain/queryDomain';
/**@description 查询岗位信息表Dto */
export class QuerySysPostDto extends queryDomain {
@ApiProperty({ description: '岗位编码',required:false })
@IsOptional()
postCode: string | null;
@ApiProperty({ description: '岗位名称',required:false })
@IsOptional()
postName: string | null;
@ApiProperty({ description: '显示顺序',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
postSort: number | null;
@ApiProperty({ description: '状态(0停用 1正常)',required:false })
@IsOptional()
status: string | null;
}
/**@description 创建岗位信息表Dto */
export class CreateSysPostDto extends BaseDomain {
@ApiProperty({ description: '岗位编码' })
@IsNotEmpty({ message: '岗位编码不能为空' })
@IsString()
postCode: string;
@ApiProperty({ description: '岗位名称' })
@IsNotEmpty({ message: '岗位名称不能为空' })
@IsString()
postName: string;
@ApiProperty({ description: '显示顺序' })
@IsNotEmpty({ message: '显示顺序不能为空' })
@Transform((v) => +v.value)
@IsNumber()
postSort: number;
@ApiProperty({ description: '状态(0停用 1正常)' })
@IsNotEmpty({ message: '状态(0停用 1正常)不能为空' })
@IsString()
status: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
}
/**@description 更新岗位信息表Dto */
export class UpdateSysPostDto extends BaseDomain {
@ApiProperty({ description: '岗位ID' })
@IsNotEmpty({ message: '岗位ID不能为空' })
@Transform((v) => +v.value)
@IsNumber()
postId: number;
@ApiProperty({ description: '岗位编码' })
@IsNotEmpty({ message: '岗位编码不能为空' })
@IsString()
postCode: string;
@ApiProperty({ description: '岗位名称' })
@IsNotEmpty({ message: '岗位名称不能为空' })
@IsString()
postName: string;
@ApiProperty({ description: '显示顺序' })
@IsNotEmpty({ message: '显示顺序不能为空' })
@Transform((v) => +v.value)
@IsNumber()
postSort: number;
@ApiProperty({ description: '状态(0停用 1正常)' })
@IsNotEmpty({ message: '状态(0停用 1正常)不能为空' })
@IsString()
status: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
}
================================================
FILE: server/src/admin/system/post/service/sys-post.service.ts
================================================
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { Response } from 'express';
import { exportTable } from '@/common/utils';
import {
QuerySysPostDto,
CreateSysPostDto,
UpdateSysPostDto,
} from '../dto/index';
import { Prisma } from '@prismaClient';
import { isNotEmpty } from 'class-validator';
import * as assert from 'assert';
@Injectable()
export class PostService {
constructor(private prisma: PrismaService) {}
/**@description 查询岗位信息表所有 */
async selectPostAll() {
return this.prisma.sysPost.findMany();
}
/**@description 分页查询岗位信息表列表 */
async selectPostList(q: QuerySysPostDto) {
const queryCondition: Prisma.SysPostWhereInput = {};
if (isNotEmpty(q['postCode'])) {
queryCondition.postCode = {
equals: q.postCode,
};
}
if (isNotEmpty(q['postName'])) {
queryCondition.postName = {
contains: q.postName,
};
}
if (isNotEmpty(q['postSort'])) {
queryCondition.postSort = {
equals: q.postSort,
};
}
if (isNotEmpty(q['status'])) {
queryCondition.status = {
equals: q.status,
};
}
if (
isNotEmpty(q.params.beginCreateTime) &&
isNotEmpty(q.params.endCreateTime)
) {
queryCondition.createTime = {
lte: q.params.endCreateTime,
gte: q.params.beginCreateTime,
};
}
if (
isNotEmpty(q.params.beginUpdateTime) &&
isNotEmpty(q.params.endUpdateTime)
) {
queryCondition.updateTime = {
lte: q.params.endUpdateTime,
gte: q.params.beginUpdateTime,
};
}
return {
rows: await this.prisma.sysPost.findMany({
skip: (q.pageNum - 1) * q.pageSize,
take: q.pageSize,
where: queryCondition,
}),
total: await this.prisma.sysPost.count({
where: queryCondition,
}),
};
}
/**@description 查询岗位信息表详情 */
async selectPostByPostId(postId: number) {
return this.prisma.sysPost.findUnique({
where: {
postId,
},
});
}
/**@description 新增岗位信息表 */
async addPost(sysPost: CreateSysPostDto) {
//删除掉空值
for (const key in sysPost) {
!isNotEmpty(sysPost[key]) && delete sysPost[key];
}
return await this.prisma.sysPost.create({
data: sysPost,
});
}
/**@description 修改岗位信息表 */
async updatePost(sysPost: UpdateSysPostDto) {
//删除掉空值
for (const key in sysPost) {
!isNotEmpty(sysPost[key]) && delete sysPost[key];
}
return await this.prisma.sysPost.update({
where: {
postId: sysPost.postId,
},
data: sysPost,
});
}
/**@description 批量删除岗位信息表 */
async deletePostByPostIds(postIds: number[]) {
const post = await this.prisma.sysUserPost.findFirst({
where: {
postId: {
in: postIds,
},
},
});
assert(!post, '岗位已被分配,不允许删除!');
return this.prisma.sysPost.deleteMany({
where: {
postId: {
in: postIds,
},
},
});
}
/**@description 单个删除岗位信息表 */
async deletePostByPostId(postId: number) {
const post = await this.prisma.sysUserPost.findFirst({
where: {
postId,
},
});
assert(!post, '岗位已被分配,不允许删除!');
return this.prisma.sysPost.delete({
where: {
postId,
},
});
}
/**@description 导出岗位信息表所有数据为xlsx */
async exportPost(res: Response) {
const title = [
'岗位ID',
'岗位编码',
'岗位名称',
'显示顺序',
'状态(0停用 1正常)',
'创建者',
'创建时间',
'更新者',
'更新时间',
'备注',
];
const data = (await this.prisma.sysPost.findMany()).map((v) =>
Object.values(v),
);
data.unshift(title);
exportTable(data, res);
}
}
================================================
FILE: server/src/admin/system/post/sys-post.controller.ts
================================================
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Post,
Put,
Query,
Req,
Res,
} from '@nestjs/common';
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import Result from '@/common/result/Result';
import {
ApiBearerAuth,
ApiBody,
ApiOperation,
ApiQuery,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { nowDateTime } from '@/common/utils';
import { PostService } from './service/sys-post.service';
import {
QuerySysPostDto,
CreateSysPostDto,
UpdateSysPostDto,
} from './dto/index';
import { Response } from 'express';
import { SysPost } from '@prismaClient';
import { TableDataInfo } from '@/common/domain/TableDataInfo';
@ApiTags('岗位信息表')
@ApiBearerAuth()
@Controller('system/post')
export class SysPostController {
constructor(private postService: PostService) {}
@ApiOperation({ summary: '查询岗位信息表列表' })
@ApiResponse({ type: TableDataInfo })
@RequirePermission('system:post:query')
@Get('/list')
async listPost(@Query() q: QuerySysPostDto): Promise> {
return Result.TableData(await this.postService.selectPostList(q));
}
@ApiOperation({ summary: '导出岗位信息表xlsx文件' })
@RequirePermission('system:post:export')
@Get('/export')
async export(@Res() res: Response): Promise {
return this.postService.exportPost(res);
}
@ApiOperation({ summary: '查询岗位信息表详细' })
@ApiResponse({ type: Result })
@RequirePermission('system:post:query')
@Get('/:postId')
async getPost(
@Param('postId', ParseIntPipe) postId: number,
): Promise> {
return Result.ok(await this.postService.selectPostByPostId(postId));
}
@ApiOperation({ summary: '新增岗位信息表' })
@ApiResponse({ type: Result })
@ApiBody({ type: CreateSysPostDto })
@RequirePermission('system:post:add')
@Post('/')
async addPost(
@Body() sysPost: CreateSysPostDto,
@Req() req,
): Promise> {
sysPost = {
...sysPost,
createTime: nowDateTime(),
updateTime: nowDateTime(),
createBy: req.user?.userName,
updateBy: req.user?.userName,
};
return Result.ok(await this.postService.addPost(sysPost));
}
@ApiOperation({ summary: '修改岗位信息表' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysPostDto })
@RequirePermission('system:post:edit')
@Put('/')
async updatePost(
@Body() sysPost: UpdateSysPostDto,
@Req() req,
): Promise> {
sysPost = {
...sysPost,
updateTime: nowDateTime(),
updateBy: req.user?.userName,
};
await this.postService.updatePost(sysPost);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '删除岗位信息表' })
@ApiResponse({ type: Result })
@RequirePermission('system:post:remove')
@Delete('/:ids')
async delPost(
@Param('ids', ParseIntArrayPipe) postIds: number[],
): Promise> {
const { count } = await this.postService.deletePostByPostIds(postIds);
return Result.toAjax(count);
}
}
================================================
FILE: server/src/admin/system/role/dto/index.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import {
IsNotEmpty,
IsNumber,
IsString,
IsOptional,
IsArray,
} from 'class-validator';
import { queryDomain } from '@/common/domain/queryDomain';
/**@description 查询角色管理Dto */
export class QuerySysRoleDto extends queryDomain {
@ApiProperty({ description: '角色名称',required:false })
@IsOptional()
roleName: string | null;
@ApiProperty({ description: '角色权限字符串',required:false })
@IsOptional()
roleKey: string | null;
@ApiProperty({ description: '显示顺序',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
roleSort: number | null;
@ApiProperty({
description:
'数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅个人权限)',
required:false })
@IsOptional()
dataScope: string | null;
@ApiProperty({ description: '菜单树选择项是否关联显示',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
menuCheckStrictly: number | null;
@ApiProperty({ description: '部门树选择项是否关联显示',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
deptCheckStrictly: number | null;
@ApiProperty({ description: '角色状态(0停用 1正常)',required:false })
@IsOptional()
status: string | null;
}
/**@description 创建角色管理Dto */
export class CreateSysRoleDto extends BaseDomain {
@ApiProperty({ description: '角色名称' })
@IsNotEmpty({ message: '角色名称不能为空' })
@IsString()
roleName: string;
@ApiProperty({ description: '角色权限字符串' })
@IsNotEmpty({ message: '角色权限字符串不能为空' })
@IsString()
roleKey: string;
@ApiProperty({ description: '显示顺序' })
@IsNotEmpty({ message: '显示顺序不能为空' })
@Transform((v) => +v.value)
@IsNumber()
roleSort: number;
@ApiProperty({
description:
'数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
required:false })
@IsOptional()
@IsString()
dataScope?: string;
@ApiProperty({ description: '菜单树选择项是否关联显示',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
menuCheckStrictly?: number;
@ApiProperty({ description: '部门树选择项是否关联显示',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
deptCheckStrictly?: number;
@ApiProperty({ description: '角色状态(0停用 1正常)' })
@IsNotEmpty({ message: '角色状态(0停用 1正常)不能为空' })
@IsString()
status: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
@ApiProperty({ description: '菜单权限' })
@IsArray()
menuIds: number[];
}
/**@description 更新角色管理Dto */
export class UpdateSysRoleDto extends BaseDomain {
@ApiProperty({ description: '角色ID' })
@IsNotEmpty({ message: '角色ID不能为空' })
@Transform((v) => +v.value)
@IsNumber()
roleId: number;
@ApiProperty({ description: '角色名称' })
@IsNotEmpty({ message: '角色名称不能为空' })
@IsString()
roleName: string;
@ApiProperty({ description: '角色权限字符串' })
@IsNotEmpty({ message: '角色权限字符串不能为空' })
@IsString()
roleKey: string;
@ApiProperty({ description: '显示顺序' })
@IsNotEmpty({ message: '显示顺序不能为空' })
@Transform((v) => +v.value)
@IsNumber()
roleSort: number;
@ApiProperty({
description:
'数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
required:false })
@IsOptional()
@IsString()
dataScope?: string;
@ApiProperty({ description: '菜单树选择项是否关联显示',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
menuCheckStrictly?: number;
@ApiProperty({ description: '部门树选择项是否关联显示',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
deptCheckStrictly?: number;
@ApiProperty({ description: '角色状态(0停用 1正常)' })
@IsNotEmpty({ message: '角色状态(0停用 1正常)不能为空' })
@IsString()
status: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
@ApiProperty({ description: '菜单权限',required:false })
@IsOptional()
@IsArray()
menuIds: number[];
@ApiProperty({ description: '部门权限',required:false })
@IsOptional()
@IsArray()
deptIds: number[];
}
/**@description 更新角色状态管理Dto */
export class UpdateSysRoleStatusDto {
@ApiProperty({ description: '角色ID' })
@IsNotEmpty({ message: '角色ID不能为空' })
@Transform((v) => +v.value)
@IsNumber()
roleId?: number;
@ApiProperty({ description: '角色状态(0停用 1正常)' })
@IsNotEmpty({ message: '角色状态(0停用 1正常)不能为空' })
@IsString()
status: string;
}
/**@description 查询授权角色用户管理Dto */
export class QueryAllocatedListDto extends queryDomain {
@IsNotEmpty({ message: '角色ID不能为空' })
@Transform((v) => +v.value)
@IsNumber()
roleId: number;
@IsOptional()
userName?: string;
@IsOptional()
phoneNumber?: string;
}
================================================
FILE: server/src/admin/system/role/service/sys-role.service.ts
================================================
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { Response } from 'express';
import { exportTable } from '@/common/utils';
import {
QuerySysRoleDto,
CreateSysRoleDto,
UpdateSysRoleDto,
UpdateSysRoleStatusDto,
QueryAllocatedListDto,
} from '../dto/index';
import { Prisma } from '@prismaClient';
import { isArray, isNotEmpty } from 'class-validator';
import * as assert from 'assert';
import { AuthService } from '@/common/service/auth/auth.service';
@Injectable()
export class RoleService {
constructor(
private prisma: PrismaService,
private authService: AuthService,
) {}
/**@description 查询角色管理所有 */
async selectRoleAll() {
return this.prisma.sysRole.findMany();
}
/**@description 分页查询角色管理列表 */
async selectRoleList(q: QuerySysRoleDto) {
const queryCondition: Prisma.SysRoleWhereInput = {};
if (isNotEmpty(q['roleName'])) {
queryCondition.roleName = {
contains: q.roleName,
};
}
if (isNotEmpty(q['roleKey'])) {
queryCondition.roleKey = {
contains: q.roleKey,
};
}
if (isNotEmpty(q['roleSort'])) {
queryCondition.roleSort = {
equals: q.roleSort,
};
}
if (isNotEmpty(q['dataScope'])) {
queryCondition.dataScope = {
equals: q.dataScope,
};
}
if (isNotEmpty(q['menuCheckStrictly'])) {
queryCondition.menuCheckStrictly = {
equals: q.menuCheckStrictly,
};
}
if (isNotEmpty(q['deptCheckStrictly'])) {
queryCondition.deptCheckStrictly = {
equals: q.deptCheckStrictly,
};
}
if (isNotEmpty(q['status'])) {
queryCondition.status = {
equals: q.status,
};
}
if (
isNotEmpty(q.params.beginCreateTime) &&
isNotEmpty(q.params.endCreateTime)
) {
queryCondition.createTime = {
lte: q.params.endCreateTime,
gte: q.params.beginCreateTime,
};
}
if (
isNotEmpty(q.params.beginUpdateTime) &&
isNotEmpty(q.params.endUpdateTime)
) {
queryCondition.updateTime = {
lte: q.params.endUpdateTime,
gte: q.params.beginUpdateTime,
};
}
return {
rows: await this.prisma.sysRole.findMany({
skip: (q.pageNum - 1) * q.pageSize,
take: q.pageSize,
where: queryCondition,
}),
total: await this.prisma.sysRole.count({
where: queryCondition,
}),
};
}
/**@description 分页查询属于角色的用户列表 */
async allocatedList(q: QueryAllocatedListDto) {
const queryCondition: Prisma.SysUserWhereInput = {
roles: {
some: {
roleId: q.roleId,
},
},
};
if (isNotEmpty(q.userName)) {
queryCondition.userName = {
contains: q.userName,
};
}
if (isNotEmpty(q.phoneNumber)) {
queryCondition.phonenumber = {
contains: q.phoneNumber,
};
}
return {
rows: await this.prisma.sysUser.findMany({
skip: (q.pageNum - 1) * q.pageSize,
take: q.pageSize,
where: queryCondition,
}),
total: await this.prisma.sysUser.count({
where: queryCondition,
}),
};
}
/**@description 分页查询不属于角色的用户列表 */
async unallocatedList(q: QueryAllocatedListDto) {
const queryCondition: Prisma.SysUserWhereInput = {
roles: {
every: {
roleId: {
not: q.roleId,
},
},
},
};
if (isNotEmpty(q.userName)) {
queryCondition.userName = {
contains: q.userName,
};
}
if (isNotEmpty(q.phoneNumber)) {
queryCondition.phonenumber = {
contains: q.phoneNumber,
};
}
return {
rows: await this.prisma.sysUser.findMany({
skip: (q.pageNum - 1) * q.pageSize,
take: q.pageSize,
where: queryCondition,
}),
total: await this.prisma.sysUser.count({
where: queryCondition,
}),
};
}
//批量添加授权用户
async addRoleUser(roleId: number, userIds: number[]) {
if (!userIds.length) return null;
await this.prisma.sysUserRole.createMany({
data: userIds.map((v) => ({
userId: v,
roleId,
})),
});
userIds.forEach((v) => this.authService.refreshUserInfo(v));
return true;
}
//批量取消授权用户
async cancelRoleUser(roleId: number, userIds: number[]) {
if (!userIds.length) return null;
await this.prisma.sysUserRole.deleteMany({
where: {
roleId,
userId: {
in: userIds,
},
},
});
userIds.forEach((v) => this.authService.refreshUserInfo(v));
return true;
}
/**@description 查询角色管理详情 */
async selectRoleByRoleId(roleId: number) {
return this.prisma.sysRole.findUnique({
where: {
roleId,
},
});
}
/**@description 新增角色管理 */
async addRole(sysRole: CreateSysRoleDto) {
//删除掉空值
for (const key in sysRole) {
!isNotEmpty(sysRole[key]) && delete sysRole[key];
}
return this.prisma.$transaction(async (db) => {
const { menuIds, ...role } = sysRole;
const addRole = await db.sysRole.create({
data: role,
});
if (isArray(menuIds) && menuIds.length) {
await db.sysRoleMenu.createMany({
data: menuIds.map((v) => ({ menuId: v, roleId: addRole.roleId })),
});
}
return addRole;
});
}
/**@description 修改角色管理 */
async updateRole(sysRole: UpdateSysRoleDto) {
//删除掉空值
for (const key in sysRole) {
!isNotEmpty(sysRole[key]) && delete sysRole[key];
}
return this.prisma.$transaction(async (db) => {
const { menuIds, ...role } = sysRole;
await db.sysRoleMenu.deleteMany({ where: { roleId: role.roleId } });
const res = await db.sysRole.update({
where: {
roleId: role.roleId,
},
data: role,
});
if (isArray(menuIds) && menuIds.length) {
await db.sysRoleMenu.createMany({
data: menuIds.map((v) => ({ menuId: v, roleId: res.roleId })),
});
}
//更新属于这个角色的用户的缓存信息
{
const userIds = [
...new Set(
(
await db.sysUserRole.findMany({
where: { roleId: sysRole.roleId },
})
).map((v) => v.userId),
),
];
userIds.forEach((userId) => {
this.authService.refreshUserInfo(userId);
});
}
return res;
});
}
/**@description 批量删除角色管理 */
async deleteRoleByRoleIds(roleIds: number[]) {
const userroles = await this.prisma.sysUserRole.findFirst({
where: {
roleId: { in: roleIds },
},
});
assert(!userroles, '角色已被分配!');
return this.prisma.$transaction(async (db) => {
await db.sysRoleDept.deleteMany({
where: {
roleId: {
in: roleIds,
},
},
});
await db.sysRoleMenu.deleteMany({
where: {
roleId: {
in: roleIds,
},
},
});
return db.sysRole.deleteMany({
where: {
roleId: {
in: roleIds,
},
},
});
});
}
/**@description 单个删除角色管理 */
async deleteRoleByRoleId(roleId: number) {
const userroles = await this.prisma.sysUserRole.findFirst({
where: {
roleId,
},
});
assert(!userroles, '角色已被分配!');
return this.prisma.$transaction(async (db) => {
await db.sysRoleDept.deleteMany({
where: {
roleId,
},
});
await db.sysRoleMenu.deleteMany({
where: {
roleId,
},
});
return db.sysRole.deleteMany({
where: {
roleId,
},
});
});
}
/**@description 导出角色管理所有数据为xlsx */
async exportRole(res: Response) {
const title = [
'角色ID',
'角色名称',
'角色权限字符串',
'显示顺序',
'数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
'菜单树选择项是否关联显示',
'部门树选择项是否关联显示',
'角色状态(0停用 1正常)',
'删除标志(0删除 1存在)',
'创建者',
'创建时间',
'更新者',
'更新时间',
'备注',
];
const data = (await this.prisma.sysRole.findMany()).map((v) =>
Object.values(v),
);
data.unshift(title);
exportTable(data, res);
}
/**@description 更新角色状态 */
async updateStatus(role: UpdateSysRoleStatusDto) {
const res = await this.prisma.sysRole.update({
where: {
roleId: role.roleId,
},
data: role,
});
//更新属于这个角色的用户的缓存信息
{
const userIds = [
...new Set(
(
await this.prisma.sysUserRole.findMany({
where: { roleId: role.roleId },
})
).map((v) => v.userId),
),
];
userIds.forEach((userId) => {
this.authService.refreshUserInfo(userId);
});
}
return res;
}
/**@description 分配数据权限 */
async dataScope(sysRole: UpdateSysRoleDto) {
//删除掉空值
for (const key in sysRole) {
!isNotEmpty(sysRole[key]) && delete sysRole[key];
}
return this.prisma.$transaction(async (db) => {
const { deptIds, ...role } = sysRole;
await db.sysRoleDept.deleteMany({ where: { roleId: role.roleId } });
await db.sysRole.update({
where: {
roleId: role.roleId,
},
data: role,
});
if (isArray(deptIds) && deptIds.length) {
return await db.sysRoleDept.createMany({
data: deptIds.map((v) => ({ deptId: v, roleId: role.roleId })),
});
}
});
}
}
================================================
FILE: server/src/admin/system/role/sys-role.controller.ts
================================================
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Post,
Put,
Query,
Req,
Res,
} from '@nestjs/common';
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import Result from '@/common/result/Result';
import {
ApiBearerAuth,
ApiBody,
ApiOperation,
ApiQuery,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { nowDateTime } from '@/common/utils';
import { RoleService } from './service/sys-role.service';
import {
QuerySysRoleDto,
CreateSysRoleDto,
UpdateSysRoleDto,
UpdateSysRoleStatusDto,
QueryAllocatedListDto,
} from './dto/index';
import { Response } from 'express';
import { SysRole } from '@prismaClient';
import { TableDataInfo } from '@/common/domain/TableDataInfo';
import { DeptService } from '../dept/service/sys-dept.service';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { RequireRole } from '@/common/decorator/require-role.decorator';
@ApiTags('角色管理')
@ApiBearerAuth()
@Controller('system/role')
export class SysRoleController {
constructor(
private roleService: RoleService,
private deptService: DeptService,
private prisma: PrismaService,
) {}
@ApiOperation({ summary: '查询角色管理列表' })
@ApiResponse({ type: TableDataInfo })
@RequirePermission('system:role:query')
@Get('/list')
async listRole(@Query() q: QuerySysRoleDto): Promise> {
return Result.TableData(await this.roleService.selectRoleList(q));
}
@ApiOperation({ summary: '查询属于角色的用户管理列表' })
@RequirePermission('system:role:query')
@Get('/authUser/allocatedList')
async listAllocatedList(@Query() q: QueryAllocatedListDto) {
return Result.TableData(await this.roleService.allocatedList(q));
}
@ApiOperation({ summary: '查询不属于角色的用户管理列表' })
@RequirePermission('system:role:query')
@Get('authUser/unallocatedList')
async listUnallocatedList(@Query() q: QueryAllocatedListDto) {
return Result.TableData(await this.roleService.unallocatedList(q));
}
@ApiOperation({ summary: '批量添加用户到该角色' })
@RequirePermission('system:role:edit')
@Put('authUser/selectAll')
async addAllRoleUser(
@Query('roleId', ParseIntPipe) roleId: number,
@Query('userIds', ParseIntArrayPipe) userIds: number[],
) {
await this.roleService.addRoleUser(roleId, userIds);
return Result.ok();
}
@ApiOperation({ summary: '批量取消用户该角色' })
@RequirePermission('system:role:edit')
@Put('authUser/cancelAll')
async cancelAllRoleUser(
@Query('roleId', ParseIntPipe) roleId: number,
@Query('userIds', ParseIntArrayPipe) userIds: number[],
) {
await this.roleService.cancelRoleUser(roleId, userIds);
return Result.ok();
}
@ApiOperation({ summary: '取消单个用户该角色' })
@RequirePermission('system:role:edit')
@Put('authUser/cancel')
async cancelRoleUser(
@Body('roleId', ParseIntPipe) roleId: number,
@Body('userId', ParseIntPipe) userIds: number,
) {
await this.roleService.cancelRoleUser(roleId, [userIds]);
return Result.ok();
}
@ApiOperation({ summary: '导出角色管理xlsx文件' })
@RequirePermission('system:role:export')
@Get('/export')
async export(@Res() res: Response): Promise {
return this.roleService.exportRole(res);
}
@ApiOperation({ summary: '获取部门树' })
@RequirePermission('system:role:edit')
@Get('/deptTree/:roleId')
async getDeptTrees(@Param('roleId', ParseIntPipe) roleId: number) {
const depts = await this.deptService.getDeptTree();
const checkedKeys = (
await this.prisma.sysRoleDept.findMany({
where: {
roleId,
},
})
)
.map((v) => v.deptId)
.filter((v) => !hasChildren(depts, v));
function hasChildren(arr, id) {
for (const item of arr) {
if (item.id === id) {
return item.children.length > 0;
} else {
const r = hasChildren(item.children, id);
if (r !== null) return r;
}
}
return null;
}
return {
...Result.ok(),
depts,
checkedKeys,
};
}
@ApiOperation({ summary: '查询角色管理详细' })
@ApiResponse({ type: Result })
@RequirePermission('system:role:query')
@Get('/:roleId')
async getRole(
@Param('roleId', ParseIntPipe) roleId: number,
): Promise> {
return Result.ok(await this.roleService.selectRoleByRoleId(roleId));
}
@ApiOperation({ summary: '新增角色管理' })
@ApiResponse({ type: Result })
@ApiBody({ type: CreateSysRoleDto })
@RequirePermission('system:role:add')
@Post('/')
async addRole(
@Body() sysRole: CreateSysRoleDto,
@Req() req,
): Promise> {
sysRole = {
...sysRole,
dataScope: '5', //自定义权限
createTime: nowDateTime(),
updateTime: nowDateTime(),
createBy: req.user?.userName,
updateBy: req.user?.userName,
};
return Result.ok(await this.roleService.addRole(sysRole));
}
@ApiOperation({ summary: '修改角色管理' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysRoleDto })
@RequirePermission('system:role:edit')
@Put('/')
async updateRole(
@Body() sysRole: UpdateSysRoleDto,
@Req() req,
): Promise> {
delete sysRole.dataScope;
sysRole = {
...sysRole,
updateTime: nowDateTime(),
updateBy: req.user?.userName,
};
await this.roleService.updateRole(sysRole);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '分配用户角色' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysRoleDto })
@RequireRole('admin')
@Put('/dataScope')
async dataScope(
@Body() sysRole: UpdateSysRoleDto,
@Req() req,
): Promise> {
sysRole = {
...sysRole,
updateTime: nowDateTime(),
updateBy: req.user?.userName,
};
await this.roleService.dataScope(sysRole);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '修改角色状态' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysRoleDto })
@RequirePermission('system:role:edit')
@Put('/changeStatus')
async updateRoleStatus(
@Body() sysRole: UpdateSysRoleStatusDto,
): Promise> {
await this.roleService.updateStatus(sysRole);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '删除角色管理' })
@ApiResponse({ type: Result })
@RequirePermission('system:role:remove')
@Delete('/:ids')
async delRole(
@Param('ids', ParseIntArrayPipe) roleIds: number[],
): Promise> {
const { count } = await this.roleService.deleteRoleByRoleIds(roleIds);
return Result.toAjax(count);
}
}
================================================
FILE: server/src/admin/system/user/dto/index.ts
================================================
import { BaseDomain } from '@/common/domain/BaseDomain';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import {
IsNotEmpty,
IsNumber,
IsString,
IsOptional,
MinLength,
} from 'class-validator';
import { queryDomain } from '@/common/domain/queryDomain';
/**@description 查询用户管理Dto */
export class QuerySysUserDto extends queryDomain {
@ApiProperty({ description: '部门ID',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
deptId: number | null;
@ApiProperty({ description: '用户账号',required:false })
@IsOptional()
userName: string | null;
@ApiProperty({ description: '用户昵称',required:false })
@IsOptional()
nickName: string | null;
@ApiProperty({ description: '用户类型(00系统用户)',required:false })
@IsOptional()
userType: string | null;
@ApiProperty({ description: '用户邮箱',required:false })
@IsOptional()
email: string | null;
@ApiProperty({ description: '手机号码',required:false })
@IsOptional()
phonenumber: string | null;
@ApiProperty({ description: '用户性别(0男 1女 2未知)',required:false })
@IsOptional()
sex: string | null;
@ApiProperty({ description: '头像地址',required:false })
@IsOptional()
avatar: string | null;
@ApiProperty({ description: '密码',required:false })
@IsOptional()
password: string | null;
@ApiProperty({ description: '帐号状态(0停用,1正常 )',required:false })
@IsOptional()
status: string | null;
@ApiProperty({ description: '最后登录IP',required:false })
@IsOptional()
loginIp: string | null;
}
/**@description 创建用户管理Dto */
export class CreateSysUserDto extends BaseDomain {
@ApiProperty({ description: '部门ID',required:false })
@IsOptional()
@Transform((v) => +v.value)
@IsNumber()
deptId?: number;
@ApiProperty({ description: '用户账号' })
@IsNotEmpty({ message: '用户账号不能为空' })
@IsString()
userName: string;
@ApiProperty({ description: '用户昵称' })
@IsNotEmpty({ message: '用户昵称不能为空' })
@IsString()
nickName: string;
@ApiProperty({ description: '用户类型(00系统用户)',required:false })
@IsOptional()
@IsString()
userType?: string;
@ApiProperty({ description: '用户邮箱',required:false })
@IsOptional()
@IsString()
email?: string;
@ApiProperty({ description: '手机号码',required:false })
@IsOptional()
@IsString()
phonenumber?: string;
@ApiProperty({ description: '用户性别(0男 1女 2未知)',required:false })
@IsOptional()
@IsString()
sex?: string;
@ApiProperty({ description: '头像地址',required:false })
@IsOptional()
@IsString()
avatar?: string;
@ApiProperty({ description: '密码',required:false })
@IsOptional()
@IsString()
password?: string;
@ApiProperty({ description: '帐号状态(0停用,1正常 )',required:false })
@IsOptional()
@IsString()
status?: string;
@ApiProperty({ description: '最后登录IP',required:false })
@IsOptional()
@IsString()
loginIp?: string;
@ApiProperty({ description: '最后登录时间',required:false })
@IsOptional()
@IsString()
loginDate?: string;
@ApiProperty({ description: '创建者',required:false })
@IsOptional()
@IsString()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsOptional()
@IsString()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
@ApiProperty({ description: '角色ids',required:false })
@IsOptional()
roleIds?: number[];
@ApiProperty({ description: '部门ids',required:false })
@IsOptional()
postIds?: number[];
}
/**@description 更新用户管理Dto */
export class UpdateSysUserDto extends BaseDomain {
@ApiProperty({ description: '用户ID' })
@IsNotEmpty({ message: '用户ID不能为空' })
@Transform((v) => +v.value)
@IsNumber()
userId: number;
@ApiProperty({ description: '用户账号' })
@IsNotEmpty({ message: '用户账号不能为空' })
@IsString()
userName: string;
@ApiProperty({ description: '用户昵称' })
@IsNotEmpty({ message: '用户昵称不能为空' })
@IsString()
nickName: string;
@ApiProperty({ description: '用户类型(00系统用户)',required:false })
@IsOptional()
@IsString()
userType?: string;
@ApiProperty({ description: '用户邮箱',required:false })
@IsOptional()
@IsString()
email?: string;
@ApiProperty({ description: '手机号码',required:false })
@IsOptional()
@IsString()
phonenumber?: string;
@ApiProperty({ description: '用户性别(0男 1女 2未知)',required:false })
@IsOptional()
@IsString()
sex?: string;
@ApiProperty({ description: '头像地址',required:false })
@IsOptional()
@IsString()
avatar?: string;
@ApiProperty({ description: '帐号状态(0停用,1正常 )',required:false })
@IsOptional()
@IsString()
status?: string;
@ApiProperty({ description: '最后登录IP',required:false })
@IsOptional()
@IsString()
loginIp?: string;
@ApiProperty({ description: '最后登录时间',required:false })
@IsOptional()
@IsString()
loginDate?: string;
@ApiProperty({ description: '更新者',required:false })
@IsOptional()
@IsString()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsOptional()
@IsString()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsOptional()
@IsString()
remark?: string;
@ApiProperty({ description: '角色ids',required:false })
@IsOptional()
roleIds?: number[];
@ApiProperty({ description: '部门ids',required:false })
@IsOptional()
postIds?: number[];
}
/**@description 更新用户状态 */
export class UpdateSysUserStatusDto extends BaseDomain {
@ApiProperty({ description: '用户ID' })
@IsNotEmpty({ message: '用户ID不能为空' })
@Transform((v) => +v.value)
@IsNumber()
userId?: number;
@ApiProperty({ description: '帐号状态(0停用,1正常 )',required:false })
@IsOptional()
@IsNotEmpty({ message: '请传入状态' })
status?: string;
}
/**@description 重置密码 */
export class resetPasswordDto extends BaseDomain {
@ApiProperty({ description: '用户ID' })
@IsNotEmpty({ message: '用户ID不能为空' })
@Transform((v) => +v.value)
@IsNumber()
userId?: number;
@ApiProperty({ description: '密码' })
@IsNotEmpty({ message: '密码不能为空' })
@MinLength(6, { message: '密码长度不能小于6' })
@IsString()
password?: string;
}
/**@description 修改用户个人信息 */
export class updateProfileDto {
@ApiProperty({ description: '用户昵称' })
@IsNotEmpty({ message: '用户昵称不能为空' })
@IsString()
nickName: string;
@ApiProperty({ description: '用户邮箱' })
@IsNotEmpty({ message: '邮箱不能为空' })
@IsString()
email?: string;
@ApiProperty({ description: '手机号码' })
@IsNotEmpty({ message: '手机号码不能为空' })
@IsString()
phonenumber?: string;
@ApiProperty({ description: '用户性别(0男 1女 2未知)',required:false })
@IsOptional()
@IsString()
sex?: string;
}
================================================
FILE: server/src/admin/system/user/service/sys-user.service.ts
================================================
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import { Response } from 'express';
import { exportTable } from '@/common/utils';
import {
QuerySysUserDto,
CreateSysUserDto,
UpdateSysUserDto,
resetPasswordDto,
UpdateSysUserStatusDto,
updateProfileDto,
} from '../dto/index';
import { Prisma } from '@prismaClient';
import { isNotEmpty } from 'class-validator';
import * as assert from 'assert';
import { AuthService } from '@/common/service/auth/auth.service';
import { isArray } from 'lodash';
import Result from '@/common/result/Result';
import { redisUtils } from '@/common/utils/redisUtils';
import { Constants } from '@/common/constant/Constants';
@Injectable()
export class UserService {
constructor(
private prisma: PrismaService,
private authService: AuthService,
) {}
/**@description 查询用户所有 */
async selectUserAll() {
return this.prisma.sysUser.findMany();
}
/**@description 分页查询用户列表 */
async selectUserList(q: QuerySysUserDto) {
const queryCondition: Prisma.SysUserWhereInput = {};
if (isNotEmpty(q['deptId'])) {
queryCondition.deptId = {
equals: q.deptId,
};
}
if (isNotEmpty(q['userName'])) {
queryCondition.userName = {
contains: q.userName,
};
}
if (isNotEmpty(q['nickName'])) {
queryCondition.nickName = {
contains: q.nickName,
};
}
if (isNotEmpty(q['userType'])) {
queryCondition.userType = {
equals: q.userType,
};
}
if (isNotEmpty(q['email'])) {
queryCondition.email = {
contains: q.email,
};
}
if (isNotEmpty(q['phonenumber'])) {
queryCondition.phonenumber = {
contains: q.phonenumber,
};
}
if (isNotEmpty(q['sex'])) {
queryCondition.sex = {
equals: q.sex,
};
}
if (isNotEmpty(q['avatar'])) {
queryCondition.avatar = {
equals: q.avatar,
};
}
if (isNotEmpty(q['password'])) {
queryCondition.password = {
equals: q.password,
};
}
if (isNotEmpty(q['status'])) {
queryCondition.status = {
equals: q.status,
};
}
if (isNotEmpty(q['loginIp'])) {
queryCondition.loginIp = {
equals: q.loginIp,
};
}
if (
isNotEmpty(q.params.beginLoginDate) &&
isNotEmpty(q.params.endLoginDate)
) {
queryCondition.loginDate = {
lte: q.params.endLoginDate,
gte: q.params.beginLoginDate,
};
}
if (
isNotEmpty(q.params.beginCreateTime) &&
isNotEmpty(q.params.endCreateTime)
) {
queryCondition.createTime = {
lte: q.params.endCreateTime,
gte: q.params.beginCreateTime,
};
}
if (
isNotEmpty(q.params.beginUpdateTime) &&
isNotEmpty(q.params.endUpdateTime)
) {
queryCondition.updateTime = {
lte: q.params.endUpdateTime,
gte: q.params.beginUpdateTime,
};
}
return {
rows: await this.prisma.sysUser.findMany({
skip: (q.pageNum - 1) * q.pageSize,
take: q.pageSize,
where: queryCondition,
include: {
dept: true,
},
}),
total: await this.prisma.sysUser.count({
where: queryCondition,
}),
};
}
/**@description 查询用户详情 */
async selectUserByUserId(userId: number) {
return this.prisma.sysUser.findUnique({
where: {
userId,
},
include: {
roles: true,
posts: true,
},
});
}
/**@description 新增用户 */
async addUser(sysUser: CreateSysUserDto) {
sysUser.password = this.authService.encrypt(sysUser.password);
const { roleIds, postIds, ...user } = sysUser;
//删除掉空值
for (const key in sysUser) {
!isNotEmpty(sysUser[key]) && delete sysUser[key];
}
return this.prisma.$transaction(async (db) => {
//更新用户信息
const addUser = await db.sysUser.create({
data: user,
});
const { userId } = addUser;
//添加用户的部门和角色
if (isArray(roleIds) && roleIds.length) {
await db.sysUserRole.createMany({
data: roleIds.map((v) => ({ userId, roleId: v })),
});
}
if (isArray(postIds) && postIds.length) {
await db.sysUserPost.createMany({
data: postIds.map((v) => ({
userId,
postId: v,
})),
});
}
return addUser;
});
}
/**@description 修改用户 */
async updateUser(sysUser: UpdateSysUserDto) {
const { roleIds, postIds, ...user } = sysUser;
//删除掉空值
for (const key in sysUser) {
!isNotEmpty(sysUser[key]) && delete sysUser[key];
}
await this.prisma.$transaction(async (db) => {
//删除用户的部门和角色
{
await db.sysUserPost.deleteMany({
where: {
userId: sysUser.userId,
},
});
await db.sysUserRole.deleteMany({
where: {
userId: sysUser.userId,
},
});
}
//添加用户的部门和角色
if (isArray(roleIds) && roleIds.length) {
await db.sysUserRole.createMany({
data: roleIds.map((v) => ({
userId: sysUser.userId,
roleId: v,
})),
});
}
if (isArray(postIds) && postIds.length) {
await db.sysUserPost.createMany({
data: postIds.map((v) => ({
userId: sysUser.userId,
postId: v,
})),
});
}
//更新用户信息
return await db.sysUser.update({
where: {
userId: sysUser.userId,
},
data: user,
});
});
//如果为禁用状态,我们把用户的token删除,禁用账户!
if (sysUser.status === '0') {
await redisUtils.del(Constants.LOGIN_TOKEN_KEY + sysUser.userId);
}
return Result.ok();
}
/**@description 修改用户密码 */
async resetPassword(sysUser: resetPasswordDto) {
sysUser.password = this.authService.encrypt(sysUser.password);
//删除掉空值
const res = await this.prisma.sysUser.update({
where: {
userId: sysUser.userId,
},
data: {
password: sysUser.password,
},
});
await redisUtils.del(Constants.LOGIN_TOKEN_KEY + sysUser.userId);
return res;
}
/**@description 修改用户状态 */
async updateStatus(sysUser: UpdateSysUserStatusDto) {
const res = await this.prisma.sysUser.update({
where: {
userId: sysUser.userId,
},
data: {
status: sysUser.status,
},
});
//如果为禁用状态,我们把用户的token删除,禁用账户!
if (sysUser.status === '0') {
await redisUtils.del(Constants.LOGIN_TOKEN_KEY + sysUser.userId);
}
return res;
}
/**@description 批量删除用户 */
async deleteUserByUserIds(userIds: number[]) {
return this.prisma.$transaction(async (db) => {
await db.sysUserPost.deleteMany({
where: {
userId: {
in: userIds,
},
},
});
await db.sysUserRole.deleteMany({
where: {
userId: {
in: userIds,
},
},
});
const res = await db.sysUser.deleteMany({
where: {
userId: {
in: userIds,
},
},
});
//清空用户的登录token
for (const id of userIds) {
await redisUtils.del(Constants.LOGIN_TOKEN_KEY + id);
}
return res;
});
}
/**@description 单个删除用户 */
async deleteUserByUserId(userId: number) {
return this.prisma.$transaction(async (db) => {
await db.sysUserPost.deleteMany({
where: {
userId,
},
});
await db.sysUserRole.deleteMany({
where: {
userId,
},
});
const res = await db.sysUser.delete({
where: {
userId,
},
});
await redisUtils.del(Constants.LOGIN_TOKEN_KEY + userId);
return res;
});
}
/**@description 导出用户所有数据为xlsx */
async exportUser(res: Response) {
const title = [
'用户ID',
'部门ID',
'用户账号',
'用户昵称',
'用户类型(00系统用户)',
'用户邮箱',
'手机号码',
'用户性别(0男 1女 2未知)',
'头像地址',
'密码',
'帐号状态(0停用,1正常 )',
'删除标志(0删除,1可用)',
'最后登录IP',
'最后登录时间',
'创建者',
'创建时间',
'更新者',
'更新时间',
'备注',
];
const data = (await this.selectUserAll()).map((v) => Object.values(v));
data.unshift(title);
exportTable(data, res);
}
/**
* @description 查询授权角色
*/
async getAuthRole(userId: number) {
const user = await this.prisma.sysUser.findUnique({
where: {
userId,
},
include: {
dept: true,
roles: {
include: {
role: true,
},
},
},
});
return {
...user,
roles: user.roles.map((v) => v.role),
};
}
/**
* @description 保存授权角色
*/
async updateAuthRole(userId: number, roleIds: number[]) {
await this.prisma.$transaction(async (db) => {
await db.sysUserRole.deleteMany({
where: {
userId,
},
});
await db.sysUserRole.createMany({
data: roleIds.map((roleId) => ({
userId,
roleId,
})),
});
});
return this.authService.refreshUserInfo(userId);
}
/**
* @description 查询用户个人信息
*/
async getUserProfile(userId) {
const user = await this.prisma.sysUser.findUnique({
where: {
userId,
},
include: {
dept: true,
posts: {
include: {
post: true,
},
},
roles: {
include: {
role: true,
},
},
},
});
return {
...user,
roleGroup: user.roles.map((v) => v.role.roleName).join(','),
postGroup: user.posts.map((v) => v.post.postName).join(','),
};
}
/**
* @description 修改用户个人信息
*/
async updateUserProfile(userId: number, user: updateProfileDto) {
await this.prisma.sysUser.update({
where: {
userId,
},
data: user,
});
return this.authService.refreshUserInfo(userId);
}
/** 修改头像 */
async updateAvatar(userId: number, avatar: string) {
await this.prisma.sysUser.update({
where: {
userId,
},
data: {
avatar,
},
});
return this.authService.refreshUserInfo(userId);
}
/** 修改密码 */
async updateUserPwd(
userId: number,
oldPassword: string,
newPassword: string,
) {
assert(isNotEmpty(oldPassword) && isNotEmpty(newPassword), '请检查参数!');
assert(oldPassword.length > 5 && newPassword.length > 5, '请检查参数!');
const user = await this.prisma.sysUser.findUnique({
where: {
userId,
},
});
assert(
this.authService.encrypt(oldPassword) === user.password,
'验证失败:旧密码不正确!',
);
const res = await this.prisma.sysUser.update({
where: {
userId,
},
data: {
password: this.authService.encrypt(newPassword),
},
});
await redisUtils.del(Constants.LOGIN_TOKEN_KEY + userId);
return res;
}
}
================================================
FILE: server/src/admin/system/user/sys-user.controller.ts
================================================
import {
BadRequestException,
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Post,
Put,
Query,
Req,
Res,
UploadedFile,
UseInterceptors,
} from '@nestjs/common';
import { ParseIntArrayPipe } from '@/common/pipe/parse-int-array.pipe';
import Result from '@/common/result/Result';
import {
ApiBearerAuth,
ApiBody,
ApiOperation,
ApiQuery,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { RequirePermission } from '@/common/decorator/require-premission.decorator';
import { nowDateTime, tree } from '@/common/utils';
import { UserService } from './service/sys-user.service';
import {
QuerySysUserDto,
CreateSysUserDto,
UpdateSysUserDto,
resetPasswordDto,
UpdateSysUserStatusDto,
updateProfileDto,
} from './dto/index';
import { Response } from 'express';
import { SysDept, SysUser } from '@prismaClient';
import { TableDataInfo } from '@/common/domain/TableDataInfo';
import { QuerySysDeptDto } from '../dept/dto';
import { DeptService } from '../dept/service/sys-dept.service';
import { RequireRole } from '@/common/decorator/require-role.decorator';
import { PrismaService } from '@/common/service/prisma/prisma.service';
import {
getFilePath,
uploadAvatarConfig,
} from '@/admin/common/upload/config/uploadConfig';
import { FileInterceptor } from '@nestjs/platform-express';
@ApiTags('用户管理')
@ApiBearerAuth()
@Controller('system/user')
export class SysUserController {
constructor(
private userService: UserService,
private deptService: DeptService,
private prisma: PrismaService,
) {}
@ApiOperation({ summary: '获取岗位和角色选择' })
@RequirePermission('system:user:add')
@Get('/')
async getRolePost() {
const roles = await this.prisma.sysRole.findMany({
where: { roleId: { not: 1 } },
});
const posts = await this.prisma.sysPost.findMany();
return {
...Result.ok(),
roles,
posts,
};
}
@ApiOperation({ summary: '查询用户管理列表' })
@ApiResponse({ type: TableDataInfo })
@RequirePermission('system:user:query')
@Get('/list')
async listUser(@Query() q: QuerySysUserDto): Promise> {
return Result.TableData(await this.userService.selectUserList(q));
}
@ApiOperation({ summary: '查询部门列表' })
@ApiResponse({ type: Result })
@RequirePermission('system:dept:query')
@Get('/deptTree')
async listDept(@Query() q: QuerySysDeptDto): Promise> {
const depts = (await this.deptService.selectDeptList(q)).map((v) => ({
...v,
id: v.deptId,
label: v.deptName,
}));
return Result.ok(tree(depts, 'id', 'parentId', 0));
}
@ApiOperation({ summary: '导出用户管理xlsx文件' })
@RequirePermission('system:user:export')
@Get('/export')
async export(@Res() res: Response): Promise {
return this.userService.exportUser(res);
}
@ApiOperation({ summary: '查询授权角色' })
@RequireRole('admin')
@Get('/authRole/:userId')
async getAuthRole(
@Param('userId', ParseIntPipe) userId: number,
): Promise {
const userInfo = await this.userService.getAuthRole(userId);
const roles = (
await this.prisma.sysRole.findMany({
where: {
roleId: {
not: 1,
},
},
orderBy: {
roleSort: 'asc',
},
})
).map((v) => {
return {
...v,
flag: userInfo.roles.find((z) => z.roleId === v.roleId),
};
});
return {
...Result.ok(),
user: userInfo,
roles,
};
}
@ApiOperation({ summary: '保存授权角色' })
@RequireRole('admin')
@ApiResponse({ type: Result })
@Put('/authRole')
async updateAuthRole(
@Query('userId', ParseIntPipe) userId: number,
@Query('roleIds', ParseIntArrayPipe) roleIds: number[],
): Promise> {
await this.userService.updateAuthRole(userId, roleIds);
return Result.ok();
}
@ApiOperation({ summary: '查询用户信息' })
@Get('/profile')
async getUserProfile(@Req() req): Promise {
const userInfo = await this.userService.getUserProfile(req.userId);
return {
...Result.ok(userInfo),
roleGroup: userInfo.roleGroup,
postGroup: userInfo.postGroup,
};
}
@ApiOperation({ summary: '修改用户个人基础信息' })
@Put('/profile')
async updateUserProfile(
@Req() req,
@Body() user: updateProfileDto,
): Promise> {
await this.userService.updateUserProfile(req.userId, user);
return Result.ok();
}
@ApiOperation({ summary: '修改个人密码' })
@Put('/profile/updatePwd')
async updateUserPwd(
@Req() req,
@Query('oldPassword') oldPassword: string,
@Query('newPassword') newPassword: string,
): Promise> {
await this.userService.updateUserPwd(req.userId, oldPassword, newPassword);
return Result.ok();
}
/**
* @description 用户头像上传
*/
@UseInterceptors(FileInterceptor('avatarfile', uploadAvatarConfig))
@Post('/profile/avatar')
async updateAvatar(@UploadedFile() file: Express.Multer.File, @Req() req) {
const userId = req.userId;
if (!file) {
return Result.BadRequest('请选择上传图片!');
}
const avatar = getFilePath(file);
await this.userService.updateAvatar(userId, avatar);
return {
...Result.ok(),
imgUrl: avatar,
};
}
@ApiOperation({ summary: '查询用户管理详细' })
@RequirePermission('system:user:query')
@Get('/:userId')
async getUser(@Param('userId', ParseIntPipe) userId: number): Promise {
const user = await this.userService.selectUserByUserId(userId);
const roles = await this.prisma.sysRole.findMany({
where: { roleId: { not: 1 } },
});
const posts = await this.prisma.sysPost.findMany();
return {
...Result.ok(user),
roles,
posts,
roleIds: user.roles.map((v) => v.roleId),
postIds: user.posts.map((v) => v.postId),
};
}
@ApiOperation({ summary: '新增用户管理' })
@ApiResponse({ type: Result })
@ApiBody({ type: CreateSysUserDto })
@RequirePermission('system:user:add')
@Post('/')
async addUser(
@Body() sysUser: CreateSysUserDto,
@Req() req,
): Promise> {
sysUser = {
...sysUser,
createTime: nowDateTime(),
updateTime: nowDateTime(),
createBy: req.user?.userName,
updateBy: req.user?.userName,
};
//过滤掉设置超级管理员角色
sysUser.roleIds = sysUser.roleIds.filter((v) => v !== 1);
return Result.ok(await this.userService.addUser(sysUser));
}
@ApiOperation({ summary: '修改用户管理' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysUserDto })
@RequirePermission('system:user:edit')
@Put('/')
async updateUser(
@Body() sysUser: UpdateSysUserDto,
@Req() req,
): Promise> {
//不能修改超级管理员
if (sysUser.userId === 1) throw new BadRequestException('非法操作!');
//过滤掉设置超级管理员角色
sysUser.roleIds = sysUser.roleIds.filter((v) => v !== 1);
//当前用户不能修改自己的状态
if (sysUser.userId === req.userId) {
delete sysUser.status;
}
sysUser = {
...sysUser,
updateTime: nowDateTime(),
updateBy: req.user?.userName,
};
await this.userService.updateUser(sysUser);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '删除用户管理' })
@ApiResponse({ type: Result })
@RequirePermission('system:user:remove')
@Delete('/:ids')
async delUser(
@Req() req,
@Param('ids', ParseIntArrayPipe) userIds: number[],
): Promise> {
//不能删除自己或者超级管理员的账号
userIds = userIds.filter((v) => v !== 1 && v != req.userId);
const { count } = await this.userService.deleteUserByUserIds(userIds);
return Result.toAjax(count);
}
@ApiOperation({ summary: '重置用户密码' })
@ApiResponse({ type: Result })
@ApiBody({ type: resetPasswordDto })
@RequireRole('admin')
@Put('/resetPwd')
async resetPassword(@Body() sysUser: resetPasswordDto): Promise> {
await this.userService.resetPassword(sysUser);
return Result.ok('修改成功!');
}
@ApiOperation({ summary: '修改用户状态' })
@ApiResponse({ type: Result })
@ApiBody({ type: UpdateSysUserStatusDto })
@RequireRole('admin')
@Put('/changeStatus')
async updateUserStatus(
@Body() sysUser: UpdateSysUserStatusDto,
): Promise> {
await this.userService.updateStatus(sysUser);
return Result.ok('修改成功!');
}
}
================================================
FILE: server/src/app.module.ts
================================================
import {
MiddlewareConsumer,
Module,
NestModule,
ValidationError,
ValidationPipe,
} from '@nestjs/common';
import { AdminModule } from './admin/admin.module';
import { CommonModule } from './common/common.module';
import { AuthMiddleware } from './common/middleware/auth/auth.middleware';
import { AuthService } from './common/service/auth/auth.service';
import { Config } from './config';
import { PermissionGuard } from './common/guard/permission/permission.guard';
import { RoleGuard } from './common/guard/permission/role.guard';
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core';
import {
AssertionErrorFilter,
AuthorizationFilter,
BadRequestFilter,
ForbiddenExceptionFilter,
GlobalErrorFilter,
MulterErrFilter,
NotFoundErrFilter,
PayloadTooLargeFilter,
ThrottlerExceptionFilter,
ValidationExceptionFilter,
} from '@/common/filter/global-error.filter';
import { ValidationException } from './common/exception/ValidationException';
import { ThrottlerModule } from '@nestjs/throttler';
import { ThrottlerCustomGuard } from './common/guard/throttler/throttler-custom.guard';
import { RemoveThrottleHeadersInterceptor } from './common/interceptors/remove-throttle-headers.interceptor';
import '@/common/utils/email';
import { ScheduleModule } from '@nestjs/schedule';
import { TasksService } from './schedule';
import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
import Result from './common/result/Result';
@Module({
imports: [
AdminModule,
CommonModule,
ThrottlerModule.forRoot({
throttlers: [
{
name: 'default',
ttl: Config.rateLimit.ttl,
limit: Config.rateLimit.limit,
},
],
storage:
Config.rateLimit.storage === 'redis'
? new ThrottlerStorageRedisService({
...Config.redis,
disconnectTimeout: 60 * 5 * 1000,
})
: null,
}),
ScheduleModule.forRoot(),
],
controllers: [],
providers: [
TasksService,
AuthService,
PermissionGuard,
RoleGuard,
{
provide: APP_GUARD,
useClass: ThrottlerCustomGuard,
},
{
provide: APP_GUARD,
useClass: PermissionGuard,
},
{
provide: APP_GUARD,
useClass: RoleGuard,
},
{
provide: APP_FILTER,
useClass: GlobalErrorFilter,
},
{
provide: APP_FILTER,
useClass: BadRequestFilter,
},
{
provide: APP_FILTER,
useClass: ThrottlerExceptionFilter,
},
{
provide: APP_FILTER,
useClass: PayloadTooLargeFilter,
},
{
provide: APP_FILTER,
useClass: AuthorizationFilter,
},
{
provide: APP_FILTER,
useClass: ForbiddenExceptionFilter,
},
{
provide: APP_FILTER,
useClass: AssertionErrorFilter,
},
{
provide: APP_FILTER,
useClass: ValidationExceptionFilter,
},
{
provide: APP_FILTER,
useClass: MulterErrFilter,
},
{
provide: APP_FILTER,
useClass: NotFoundErrFilter,
},
{
provide: APP_PIPE,
useFactory() {
return new ValidationPipe({
whitelist: true, // 自动剔除非 DTO 类中的字段
// forbidNonWhitelisted: true, // 如果存在非 DTO 类中的字段则抛出异常
exceptionFactory: (errors: ValidationError[]) => {
const messages = errors
.map((error) => Object.values(error.constraints))
.flat();
return new ValidationException(`参数验证失败: ${messages[0]}`);
// return new ValidationException(`参数验证失败: ${messages.join(', ')}`);
},
});
},
},
{
provide: APP_INTERCEPTOR,
useClass: RemoveThrottleHeadersInterceptor,
},
],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
const demo:any = (req, res, next) => {
if (Config.is_demo && req.method !== "GET") {
return res.send(Result.Error("演示模式,不允许操作"));
}
else {
next();
}
};
const middlewares = [AuthMiddleware]
if (Config.is_demo) {
middlewares.push(demo);
}
consumer
.apply(...middlewares)
.exclude('/login', '/logout', '/captchaImage')
.forRoutes('*');
}
}
================================================
FILE: server/src/common/common.module.ts
================================================
import { Global, Module } from '@nestjs/common';
import { PrismaService } from './service/prisma/prisma.service';
import { AuthService } from './service/auth/auth.service';
import { GenService } from './service/gen/gen.service';
@Global()
@Module({
providers: [PrismaService, AuthService, GenService],
exports: [PrismaService, AuthService],
imports: [],
})
export class CommonModule {}
================================================
FILE: server/src/common/constant/Constants.ts
================================================
/**
* 通用常量信息
*/
export class Constants {
/**
* UTF-8 字符集
*/
public static readonly UTF8: string = 'UTF-8';
/**
* GBK 字符集
*/
public static readonly GBK: string = 'GBK';
/**
* http请求
*/
public static readonly HTTP: string = 'http://';
/**
* https请求
*/
public static readonly HTTPS: string = 'https://';
/**
* 通用成功标识
*/
public static readonly SUCCESS: string = '0';
/**
* 通用失败标识
*/
public static readonly FAIL: string = '1';
/**
* 登录成功
*/
public static readonly LOGIN_SUCCESS: string = 'Success';
/**
* 注销
*/
public static readonly LOGOUT: string = 'Logout';
/**
* 登录失败
*/
public static readonly LOGIN_FAIL: string = 'Error';
/**
* 验证码 redis key
*/
public static readonly CAPTCHA_CODE_KEY: string = 'captcha_codes:';
/**
* 登录用户 redis key
*/
public static readonly LOGIN_TOKEN_KEY: string = 'login_tokens:';
/**
* 缓存用户信息 redis key
*/
public static readonly LOGIN_CACHE_TOKEN_KEY: string = 'login_cache_tokens:';
/**
* 防重提交 redis key
*/
public static readonly REPEAT_SUBMIT_KEY: string = 'repeat_submit:';
/**
* 验证码有效期(分钟)
*/
public static readonly CAPTCHA_EXPIRATION: number = 2;
/**
* 令牌
*/
public static readonly TOKEN: string = 'token';
/**
* 令牌前缀
*/
public static readonly TOKEN_PREFIX: string = 'Bearer ';
/**
* 登录用户 key
*/
public static readonly LOGIN_USER_KEY: string = 'login_user_key';
/**
* 用户ID
*/
public static readonly JWT_USERID: string = 'userid';
/**
* 用户名称
*/
public static readonly JWT_USERNAME: string = 'sub';
/**
* 用户头像
*/
public static readonly JWT_AVATAR: string = 'avatar';
/**
* 创建时间
*/
public static readonly JWT_CREATED: string = 'created';
/**
* 参数管理 cache key
*/
public static readonly SYS_CONFIG_KEY: string = 'sys_config:';
/**
* 字典管理 cache key
*/
public static readonly SYS_DICT_KEY: string = 'sys_dict:';
/**
* 文件访问前缀
*/
public static readonly FILE_PREFIX: string = '/upload';
}
================================================
FILE: server/src/common/constant/GenConstants.ts
================================================
/**
* GenConstants类
*/
export class GenConstants {
/**
* 单表(增删改查)
*/
static TPL_CRUD = 'crud';
/**
* 树表(增删改查)
*/
static TPL_TREE = 'tree';
/**
* 主子表(增删改查)
*/
static TPL_SUB = 'sub';
/**
* 树编码字段
*/
static TREE_CODE = 'treeCode';
/**
* 树父编码字段
*/
static TREE_PARENT_CODE = 'treeParentCode';
/**
* 树名称字段
*/
static TREE_NAME = 'treeName';
/**
* 上级菜单ID字段
*/
static PARENT_MENU_ID = 'parentMenuId';
/**
* 上级菜单名称字段
*/
static PARENT_MENU_NAME = 'parentMenuName';
/**
* 数据库字符串类型
*/
static COLUMNTYPE_STR = ['char', 'varchar', 'nvarchar', 'varchar2'];
/**
* 数据库文本类型
*/
static COLUMNTYPE_TEXT = ['tinytext', 'text', 'mediumtext', 'longtext'];
/**
* 数据库时间类型
*/
static COLUMNTYPE_TIME = ['datetime', 'time', 'date', 'timestamp'];
/**
* 数据库数字类型
*/
static COLUMNTYPE_NUMBER = [
'tinyint',
'smallint',
'mediumint',
'int',
'number',
'integer',
'bit',
'bigint',
'float',
'double',
'decimal',
];
/**
* 页面不需要编辑字段
*/
static COLUMNNAME_NOT_EDIT = ['id', 'create_by', 'create_time', 'del_flag'];
/**
* 页面不需要显示的列表字段
*/
static COLUMNNAME_NOT_LIST = [
'id',
'create_by',
'create_time',
'del_flag',
'update_by',
'update_time',
];
/**
* 页面不需要查询字段
*/
static COLUMNNAME_NOT_QUERY = [
'id',
'create_by',
'create_time',
'del_flag',
'update_by',
'update_time',
'remark',
];
/**
* Entity基类字段
*/
static BASE_ENTITY = [
'createBy',
'createTime',
'updateBy',
'updateTime',
'remark',
];
/**
* Tree基类字段
*/
static TREE_ENTITY = [
'parentName',
'parentId',
'orderNum',
'ancestors',
'children',
];
/**
* 文本框
*/
static HTML_INPUT = 'input';
/**
* 文本域
*/
static HTML_TEXTAREA = 'textarea';
/**
* 下拉框
*/
static HTML_SELECT = 'select';
/**
* 单选框
*/
static HTML_RADIO = 'radio';
/**
* 复选框
*/
static HTML_CHECKBOX = 'checkbox';
/**
* 日期控件
*/
static HTML_DATETIME = 'datetime';
/**
* 图片上传控件
*/
static HTML_IMAGE_UPLOAD = 'imageUpload';
/**
* 文件上传控件
*/
static HTML_FILE_UPLOAD = 'fileUpload';
/**
* 富文本控件
*/
static HTML_EDITOR = 'editor';
/**
* 字符串类型
*/
static TYPE_STRING = 'String';
/**
* 数字
*/
static TYPE_NUMBER = 'Number';
/**
* 整型
*/
static TYPE_INTEGER = 'Integer';
/**
* 长整型
*/
static TYPE_LONG = 'Long';
/**
* 浮点型
*/
static TYPE_DOUBLE = 'Double';
/**
* 高精度计算类型
*/
static TYPE_BIGDECIMAL = 'BigDecimal';
/**
* 时间类型
*/
static TYPE_DATE = 'Date';
/**
* 模糊查询
*/
static QUERY_LIKE = 'LIKE';
/**
* 日期区间查询
*/
static QUERY_BETWEEN = 'BETWEEN';
/**
* 相等查询
*/
static QUERY_EQ = 'EQ';
/**
* 需要
*/
static REQUIRE = '1';
}
================================================
FILE: server/src/common/constant/HttpStatus.ts
================================================
/**
* 返回状态码
*/
export enum HttpStatus {
/**
* 操作成功
*/
SUCCESS = 200,
/**
* 对象创建成功
*/
CREATED = 201,
/**
* 请求已经被接受
*/
ACCEPTED = 202,
/**
* 操作已经执行成功,但是没有返回数据
*/
NO_CONTENT = 204,
/**
* 资源已被移除
*/
MOVED_PERM = 301,
/**
* 重定向
*/
SEE_OTHER = 303,
/**
* 资源没有被修改
*/
NOT_MODIFIED = 304,
/**
* 参数列表错误(缺少,格式不匹配)
*/
BAD_REQUEST = 400,
/**
* 未授权
*/
UNAUTHORIZED = 401,
/**
* 访问受限,授权过期
*/
FORBIDDEN = 403,
/**
* 资源,服务未找到
*/
NOT_FOUND = 404,
/**
* 不允许的http方法
*/
BAD_METHOD = 405,
/**
* 资源冲突,或者资源被锁
*/
CONFLICT = 409,
/**
* 不支持的数据,媒体类型
*/
UNSUPPORTED_TYPE = 415,
/**
* 参数验证不通过
*/
Validation = 422,
/**
* 请求频繁
*/
FREQUENT_REQUESTS = 429,
/**
* 系统内部错误
*/
ERROR = 500,
/**
* 接口未实现
*/
NOT_IMPLEMENTED = 501,
}
================================================
FILE: server/src/common/decorator/require-premission.decorator.ts
================================================
import { SetMetadata } from '@nestjs/common';
export const RequirePermission = (permission: string) =>
SetMetadata('permission', permission);
================================================
FILE: server/src/common/decorator/require-role.decorator.ts
================================================
import { SetMetadata } from '@nestjs/common';
export const RequireRole = (role: string) => SetMetadata('role', role);
================================================
FILE: server/src/common/decorator/throttle-user.ts
================================================
import { SetMetadata } from '@nestjs/common';
export const THROTTLE_USER_KEY = 'throttleUser';
export const ThrottleUser = () => SetMetadata(THROTTLE_USER_KEY, true);
================================================
FILE: server/src/common/domain/BaseDomain.ts
================================================
import { ApiProperty } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator';
export class BaseDomain {
@ApiProperty({ description: '创建者',required:false })
@IsString()
@IsOptional()
createBy?: string;
@ApiProperty({ description: '创建时间',required:false })
@IsString()
@IsOptional()
createTime?: string;
@ApiProperty({ description: '更新者',required:false })
@IsString()
@IsOptional()
updateBy?: string;
@ApiProperty({ description: '更新时间',required:false })
@IsString()
@IsOptional()
updateTime?: string;
@ApiProperty({ description: '备注',required:false })
@IsString()
@IsOptional()
remark?: string;
}
================================================
FILE: server/src/common/domain/PageDomain.ts
================================================
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNumber, IsOptional } from 'class-validator';
export class PageDomain {
@ApiProperty({ description: '当前页码',required:false })
@IsNumber()
@IsOptional()
@Transform((v) => +v.value)
pageNum: number = 1;
@ApiProperty({ description: '每页的数据条目', required:false })
@IsNumber()
@IsOptional()
@Transform((v) => +v.value)
pageSize: number = 10;
}
================================================
FILE: server/src/common/domain/TableDataInfo.ts
================================================
import { HttpStatus } from '@/common/constant/HttpStatus';
import { ApiProperty } from '@nestjs/swagger';
export class TableDataInfo {
@ApiProperty({
example: 0,
description: '总记录数',
})
total: number;
@ApiProperty({
default: null,
description: '列表数据',
})
rows: T[];
@ApiProperty({
example: 200,
description: '消息状态码',
})
code: number;
@ApiProperty({
example: '查询成功',
description: '消息内容',
})
msg: string;
constructor(rows: T[], total: number, code?: number, msg?: string) {
this.total = total;
this.rows = rows;
this.code = code || HttpStatus.SUCCESS;
this.msg = msg || '查询成功';
}
}
================================================
FILE: server/src/common/domain/queryDomain.ts
================================================
import { IsOptional } from 'class-validator';
import { PageDomain } from './PageDomain';
import { ApiProperty } from '@nestjs/swagger';
export class queryDomain extends PageDomain {
@ApiProperty({ description: '查询附加参数', required: false })
@IsOptional()
params: { [key: string]: any } = {};
}
================================================
FILE: server/src/common/exception/AuthorizationException.ts
================================================
export class AuthorizationException extends Error {
constructor(props) {
super(props);
}
}
================================================
FILE: server/src/common/exception/ValidationException.ts
================================================
export class ValidationException extends Error {
constructor(props) {
super(props);
}
}
================================================
FILE: server/src/common/filter/global-error.filter.ts
================================================
import * as assert from 'assert';
import {
ArgumentsHost,
BadRequestException,
Catch,
ExceptionFilter,
ForbiddenException,
NotFoundException,
PayloadTooLargeException,
} from '@nestjs/common';
import { ValidationException } from '@/common/exception/ValidationException';
import Result from '@/common/result/Result';
import { Response } from 'express';
import { AuthorizationException } from '@/common/exception/AuthorizationException';
import { MulterError } from 'multer';
import { ThrottlerException } from '@nestjs/throttler';
/**
* @desc 参数验证不通过
*/
@Catch(ValidationException)
export class ValidationExceptionFilter implements ExceptionFilter {
catch(exception: ValidationException, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
res.send(Result.Validation(exception.message));
}
}
/**
* @desc 断言不通过
*/
@Catch(assert.AssertionError)
export class AssertionErrorFilter implements ExceptionFilter {
catch(exception: assert.AssertionError, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
res.send(Result.Validation(exception.message));
}
}
/**
* @desc 身份验证不通过
*/
@Catch(AuthorizationException)
export class AuthorizationFilter implements ExceptionFilter {
catch(exception: ValidationException, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
res.send(Result.Unauthorized(exception.message));
}
}
/**
* @desc 权限不足
*/
@Catch(ForbiddenException)
export class ForbiddenExceptionFilter implements ExceptionFilter {
catch(exception: ForbiddenException, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
res.send(Result.Forbidden());
}
}
/**
* @desc 资源路径不存在
*/
@Catch(NotFoundException)
export class NotFoundErrFilter implements ExceptionFilter {
catch(exception: NotFoundException, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
res.send(Result.NotFound());
}
}
/**
* @desc 文件上传失败
*/
@Catch(MulterError)
export class MulterErrFilter implements ExceptionFilter {
catch(exception: MulterError, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
const errMap = {
TypeError: '不允许上传的文件类型!',
LIMIT_PART_COUNT: '部件太多',
LIMIT_FILE_SIZE: '文件大小不通过',
LIMIT_FILE_COUNT: '文件数量不通过',
LIMIT_FIELD_KEY: '字段名太长',
LIMIT_FIELD_VALUE: '字段值太长',
LIMIT_FIELD_COUNT: '字段太多',
LIMIT_UNEXPECTED_FILE: '不包含此表单字段',
MISSING_FIELD_NAME: '字段名缺失',
};
res.send(
Result.BadRequest(
'文件上传失败:' + (errMap?.[exception?.code] || exception?.message),
),
);
}
}
/**
* @desc 文件大小超出限制
*/
@Catch(PayloadTooLargeException)
export class PayloadTooLargeFilter implements ExceptionFilter {
catch(exception: PayloadTooLargeException, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
res.send(Result.BadRequest('文件大小超出限制!'));
}
}
/**
* @desc badRquest错误处理
*/
@Catch(BadRequestException)
export class BadRequestFilter implements ExceptionFilter {
catch(exception: BadRequestException, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
console.log(exception);
res.send(Result.BadRequest(exception.message));
}
}
/**
* @desc ratelimit处理
*/
@Catch(ThrottlerException)
export class ThrottlerExceptionFilter implements ExceptionFilter {
catch(exception: ThrottlerException, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
res.send(Result.Error('您的ip访问频繁,请稍后重试!', 429));
}
}
/**
* @desc 全局错误处理
*/
@Catch()
export class GlobalErrorFilter implements ExceptionFilter {
catch(exception: any, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
console.log(exception);
res.send(Result.Error('error'));
}
}
================================================
FILE: server/src/common/guard/permission/permission.guard.ts
================================================
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
import { Reflector } from '@nestjs/core';
import { AuthService } from '@/common/service/auth/auth.service';
@Injectable()
export class PermissionGuard implements CanActivate {
constructor(
private reflector: Reflector,
private authService: AuthService,
) {}
canActivate(
context: ExecutionContext,
): boolean | Promise | Observable {
const req = context.switchToHttp().getRequest();
const prem = this.reflector.getAllAndOverride('permission', [
context.getClass(),
context.getHandler(),
]);
//不需要鉴权
if (prem === undefined) return true;
//调用鉴权
return this.authService.hasPermission(prem, req.userId);
}
}
================================================
FILE: server/src/common/guard/permission/role.guard.ts
================================================
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
import { Reflector } from '@nestjs/core';
import { AuthService } from '@/common/service/auth/auth.service';
@Injectable()
export class RoleGuard implements CanActivate {
constructor(
private authService: AuthService,
private reflector: Reflector,
) {}
canActivate(
context: ExecutionContext,
): boolean | Promise | Observable {
const req = context.switchToHttp().getRequest();
const role = this.reflector.getAllAndOverride('role', [
context.getClass(),
context.getHandler(),
]);
//不需要鉴权
if (role === undefined) return true;
//调用鉴权
return this.authService.hasRole(role, req.userId);
}
}
================================================
FILE: server/src/common/guard/throttler/throttler-custom.guard.ts
================================================
import { ThrottlerGuard } from '@nestjs/throttler';
import { ExecutionContext, Inject, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { THROTTLE_USER_KEY } from '@/common/decorator/throttle-user';
@Injectable()
export class ThrottlerCustomGuard extends ThrottlerGuard {
@Inject()
protected reflector: Reflector;
protected generateKey(
context: ExecutionContext,
suffix: string,
name: string,
): string {
const req = context.switchToHttp().getRequest();
const isThrottleUser = this.reflector.getAllAndOverride(
THROTTLE_USER_KEY,
[context.getClass(), context.getHandler()],
);
return isThrottleUser && req.userId !== undefined
? `rate-limit:${context.getClass().name}-${context.getHandler().name}-${name}-user-${req.userId}`
: `rate-limit:${context.getClass().name}-${context.getHandler().name}-${name}-ip-${req.ips.length ? req.ips[0] : req.ip}`;
}
}
================================================
FILE: server/src/common/interceptors/remove-throttle-headers.interceptor.ts
================================================
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class RemoveThrottleHeadersInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable {
const response = context.switchToHttp().getResponse();
response.removeHeader('X-RateLimit-Limit');
response.removeHeader('X-RateLimit-Remaining');
response.removeHeader('X-RateLimit-Reset');
response.removeHeader('Retry-After');
return next.handle();
}
}
================================================
FILE: server/src/common/middleware/auth/auth.middleware.ts
================================================
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { Constants } from '@/common/constant/Constants';
import { AuthorizationException } from '@/common/exception/AuthorizationException';
import { AuthService } from '@/common/service/auth/auth.service';
import { redisUtils } from '@/common/utils/redisUtils';
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';
@Injectable()
export class AuthMiddleware implements NestMiddleware {
constructor(private authService: AuthService) {}
async use(req: Request, res: Response, next: () => void) {
let token = req.headers['authorization'];
if (!token || token.length < 20 || !token.startsWith('Bearer ')) {
throw new AuthorizationException('无效的token!');
}
token = token.slice(7);
try {
const { userId, tokenId } = (await this.authService.verifyToken(
token,
)) as { userId: number; tokenId: string };
if (!(await redisUtils.get(Constants.LOGIN_TOKEN_KEY + tokenId)))
throw new AuthorizationException('无效的token!');
const userInfo = JSON.parse(
(await redisUtils.get(Constants.LOGIN_CACHE_TOKEN_KEY + userId)) ||
null,
);
if (!userInfo) throw new AuthorizationException('无效的token!');
//@ts-ignore
req.userId = userId;
//@ts-ignore
req.token = token;
//@ts-ignore
req.user = userInfo;
next();
} catch (error) {
throw new AuthorizationException('无效的token!');
}
}
}
================================================
FILE: server/src/common/pipe/parse-int-array.pipe.ts
================================================
import { ValidationException } from '@/common/exception/ValidationException';
import { PipeTransform, Injectable } from '@nestjs/common';
@Injectable()
export class ParseIntArrayPipe implements PipeTransform {
transform(value: string): number[] {
// 将字符串按逗号分割成数组
const array = value
.split(',')
.filter((v) => v !== '')
.map((item) => parseInt(item.trim(), 10));
// 检查是否所有元素都成功转换为数字
if (array.some(Number.isNaN)) {
throw new ValidationException('参数不正确');
}
return array;
}
}
================================================
FILE: server/src/common/pipe/validation.pipe.ts
================================================
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';
import { plainToClass } from 'class-transformer';
import { validate } from 'class-validator';
import { ValidationException } from '@/common/exception/ValidationException';
@Injectable()
export class ValidationPipe implements PipeTransform {
async transform(value: any, { metatype }: ArgumentMetadata) {
if (!metatype || !this.toValidate(metatype)) {
return value;
}
const object = plainToClass(metatype, value);
const errors = await validate(object, {});
if (errors.length > 0) {
const error = Object.values(errors[0].constraints)[0];
throw new ValidationException(error);
}
return object;
}
private toValidate(metatype: Function): boolean {
const types: Function[] = [String, Boolean, Number, Array, Object];
return !types.includes(metatype);
}
}
================================================
FILE: server/src/common/prisma-client/default.d.ts
================================================
export * from './index'
================================================
FILE: server/src/common/prisma-client/default.js
================================================
module.exports = { ...require('.') }
================================================
FILE: server/src/common/prisma-client/edge.d.ts
================================================
export * from './default'
================================================
FILE: server/src/common/prisma-client/edge.js
================================================
Object.defineProperty(exports, "__esModule", { value: true });
const {
PrismaClientKnownRequestError,
PrismaClientUnknownRequestError,
PrismaClientRustPanicError,
PrismaClientInitializationError,
PrismaClientValidationError,
NotFoundError,
getPrismaClient,
sqltag,
empty,
join,
raw,
Decimal,
Debug,
objectEnumValues,
makeStrictEnum,
Extensions,
warnOnce,
defineDmmfProperty,
Public,
getRuntime
} = require('./runtime/edge.js')
const Prisma = {}
exports.Prisma = Prisma
exports.$Enums = {}
/**
* Prisma Client JS version: 5.15.0
* Query Engine version: 12e25d8d06f6ea5a0252864dd9a03b1bb51f3022
*/
Prisma.prismaVersion = {
client: "5.15.0",
engine: "12e25d8d06f6ea5a0252864dd9a03b1bb51f3022"
}
Prisma.PrismaClientKnownRequestError = PrismaClientKnownRequestError;
Prisma.PrismaClientUnknownRequestError = PrismaClientUnknownRequestError
Prisma.PrismaClientRustPanicError = PrismaClientRustPanicError
Prisma.PrismaClientInitializationError = PrismaClientInitializationError
Prisma.PrismaClientValidationError = PrismaClientValidationError
Prisma.NotFoundError = NotFoundError
Prisma.Decimal = Decimal
/**
* Re-export of sql-template-tag
*/
Prisma.sql = sqltag
Prisma.empty = empty
Prisma.join = join
Prisma.raw = raw
Prisma.validator = Public.validator
/**
* Extensions
*/
Prisma.getExtensionContext = Extensions.getExtensionContext
Prisma.defineExtension = Extensions.defineExtension
/**
* Shorthand utilities for JSON filtering
*/
Prisma.DbNull = objectEnumValues.instances.DbNull
Prisma.JsonNull = objectEnumValues.instances.JsonNull
Prisma.AnyNull = objectEnumValues.instances.AnyNull
Prisma.NullTypes = {
DbNull: objectEnumValues.classes.DbNull,
JsonNull: objectEnumValues.classes.JsonNull,
AnyNull: objectEnumValues.classes.AnyNull
}
/**
* Enums
*/
exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
ReadUncommitted: 'ReadUncommitted',
ReadCommitted: 'ReadCommitted',
RepeatableRead: 'RepeatableRead',
Serializable: 'Serializable'
});
exports.Prisma.GenTableScalarFieldEnum = {
tableId: 'tableId',
tableName: 'tableName',
tableComment: 'tableComment',
subTableName: 'subTableName',
subTableFkName: 'subTableFkName',
className: 'className',
tplCategory: 'tplCategory',
tplWebType: 'tplWebType',
packageName: 'packageName',
moduleName: 'moduleName',
businessName: 'businessName',
functionName: 'functionName',
functionAuthor: 'functionAuthor',
genType: 'genType',
genPath: 'genPath',
options: 'options',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.RelationLoadStrategy = {
query: 'query',
join: 'join'
};
exports.Prisma.GenTableColumnScalarFieldEnum = {
columnId: 'columnId',
tableId: 'tableId',
columnName: 'columnName',
columnComment: 'columnComment',
columnType: 'columnType',
javaType: 'javaType',
javaField: 'javaField',
isPk: 'isPk',
isIncrement: 'isIncrement',
isRequired: 'isRequired',
isInsert: 'isInsert',
isEdit: 'isEdit',
isList: 'isList',
isQuery: 'isQuery',
queryType: 'queryType',
htmlType: 'htmlType',
dictType: 'dictType',
sort: 'sort',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime'
};
exports.Prisma.SysConfigScalarFieldEnum = {
configId: 'configId',
configName: 'configName',
configKey: 'configKey',
configValue: 'configValue',
configType: 'configType',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysDeptScalarFieldEnum = {
deptId: 'deptId',
parentId: 'parentId',
ancestors: 'ancestors',
deptName: 'deptName',
orderNum: 'orderNum',
leader: 'leader',
phone: 'phone',
email: 'email',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime'
};
exports.Prisma.SysDictDataScalarFieldEnum = {
dictCode: 'dictCode',
dictSort: 'dictSort',
dictLabel: 'dictLabel',
dictValue: 'dictValue',
dictType: 'dictType',
cssClass: 'cssClass',
listClass: 'listClass',
isDefault: 'isDefault',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysDictTypeScalarFieldEnum = {
dictId: 'dictId',
dictName: 'dictName',
dictType: 'dictType',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysLogininforScalarFieldEnum = {
infoId: 'infoId',
userName: 'userName',
ipaddr: 'ipaddr',
loginLocation: 'loginLocation',
browser: 'browser',
os: 'os',
status: 'status',
msg: 'msg',
loginTime: 'loginTime'
};
exports.Prisma.SysMenuScalarFieldEnum = {
menuId: 'menuId',
menuName: 'menuName',
parentId: 'parentId',
orderNum: 'orderNum',
path: 'path',
component: 'component',
query: 'query',
isFrame: 'isFrame',
isCache: 'isCache',
menuType: 'menuType',
visible: 'visible',
status: 'status',
perms: 'perms',
icon: 'icon',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysNoticeScalarFieldEnum = {
noticeId: 'noticeId',
noticeTitle: 'noticeTitle',
noticeType: 'noticeType',
noticeContent: 'noticeContent',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysPostScalarFieldEnum = {
postId: 'postId',
postCode: 'postCode',
postName: 'postName',
postSort: 'postSort',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysUserPostScalarFieldEnum = {
userId: 'userId',
postId: 'postId'
};
exports.Prisma.SysRoleDeptScalarFieldEnum = {
roleId: 'roleId',
deptId: 'deptId'
};
exports.Prisma.SysRoleMenuScalarFieldEnum = {
roleId: 'roleId',
menuId: 'menuId'
};
exports.Prisma.SysUserScalarFieldEnum = {
userId: 'userId',
deptId: 'deptId',
userName: 'userName',
nickName: 'nickName',
userType: 'userType',
email: 'email',
phonenumber: 'phonenumber',
sex: 'sex',
avatar: 'avatar',
password: 'password',
status: 'status',
loginIp: 'loginIp',
loginDate: 'loginDate',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysRoleScalarFieldEnum = {
roleId: 'roleId',
roleName: 'roleName',
roleKey: 'roleKey',
roleSort: 'roleSort',
dataScope: 'dataScope',
menuCheckStrictly: 'menuCheckStrictly',
deptCheckStrictly: 'deptCheckStrictly',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysUserRoleScalarFieldEnum = {
userId: 'userId',
roleId: 'roleId'
};
exports.Prisma.SortOrder = {
asc: 'asc',
desc: 'desc'
};
exports.Prisma.NullsOrder = {
first: 'first',
last: 'last'
};
exports.Prisma.ModelName = {
GenTable: 'GenTable',
GenTableColumn: 'GenTableColumn',
SysConfig: 'SysConfig',
SysDept: 'SysDept',
SysDictData: 'SysDictData',
SysDictType: 'SysDictType',
SysLogininfor: 'SysLogininfor',
SysMenu: 'SysMenu',
SysNotice: 'SysNotice',
SysPost: 'SysPost',
SysUserPost: 'SysUserPost',
SysRoleDept: 'SysRoleDept',
SysRoleMenu: 'SysRoleMenu',
SysUser: 'SysUser',
SysRole: 'SysRole',
SysUserRole: 'SysUserRole'
};
/**
* Create the Client
*/
const config = {
"generator": {
"name": "client",
"provider": {
"fromEnvVar": null,
"value": "prisma-client-js"
},
"output": {
"value": "/Users/carole/project/carole-admin/server/src/common/prisma-client",
"fromEnvVar": null
},
"config": {
"engineType": "library"
},
"binaryTargets": [
{
"fromEnvVar": null,
"value": "darwin",
"native": true
}
],
"previewFeatures": [
"views",
"relationJoins",
"prismaSchemaFolder",
"omitApi"
],
"isCustomOutput": true
},
"relativeEnvPaths": {
"rootEnvPath": null,
"schemaEnvPath": "../../.env"
},
"relativePath": "../..",
"clientVersion": "5.15.0",
"engineVersion": "12e25d8d06f6ea5a0252864dd9a03b1bb51f3022",
"datasourceNames": [
"db"
],
"activeProvider": "mysql",
"postinstall": true,
"inlineDatasources": {
"db": {
"url": {
"fromEnvVar": "DATABASE_URL",
"value": null
}
}
},
"inlineSchema": "model GenTable {\n tableId Int @id @default(autoincrement()) @map(\"table_id\") @db.UnsignedInt\n tableName String? @default(\"\") @map(\"table_name\") @db.VarChar(200)\n tableComment String? @default(\"\") @map(\"table_comment\") @db.VarChar(500)\n subTableName String? @map(\"sub_table_name\") @db.VarChar(64)\n subTableFkName String? @map(\"sub_table_fk_name\") @db.VarChar(64)\n className String? @default(\"\") @map(\"class_name\") @db.VarChar(100)\n tplCategory String? @default(\"crud\") @map(\"tpl_category\") @db.VarChar(200)\n tplWebType String? @default(\"\") @map(\"tpl_web_type\") @db.VarChar(30)\n packageName String? @map(\"package_name\") @db.VarChar(100)\n moduleName String? @map(\"module_name\") @db.VarChar(30)\n businessName String? @map(\"business_name\") @db.VarChar(30)\n functionName String? @map(\"function_name\") @db.VarChar(50)\n functionAuthor String? @map(\"function_author\") @db.VarChar(50)\n genType String? @default(\"0\") @map(\"gen_type\") @db.Char(1)\n genPath String? @default(\"/\") @map(\"gen_path\") @db.VarChar(200)\n options String? @map(\"options\") @db.VarChar(1000)\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n remark String? @db.VarChar(500)\n tableColumns GenTableColumn[]\n\n @@map(\"gen_table\")\n}\n\nmodel GenTableColumn {\n columnId Int @id @default(autoincrement()) @map(\"column_id\") @db.UnsignedInt\n tableId Int? @map(\"table_id\") @db.UnsignedInt\n columnName String? @map(\"column_name\") @db.VarChar(200)\n columnComment String? @map(\"column_comment\") @db.VarChar(500)\n columnType String? @map(\"column_type\") @db.VarChar(100)\n javaType String? @map(\"java_type\") @db.VarChar(500)\n javaField String? @map(\"java_field\") @db.VarChar(200)\n isPk String? @map(\"is_pk\") @db.Char(1)\n isIncrement String? @map(\"is_increment\") @db.Char(1)\n isRequired String? @map(\"is_required\") @db.Char(1)\n isInsert String? @map(\"is_insert\") @db.Char(1)\n isEdit String? @map(\"is_edit\") @db.Char(1)\n isList String? @map(\"is_list\") @db.Char(1)\n isQuery String? @map(\"is_query\") @db.Char(1)\n queryType String? @default(\"EQ\") @map(\"query_type\") @db.VarChar(200)\n htmlType String? @map(\"html_type\") @db.VarChar(200)\n dictType String? @default(\"\") @map(\"dict_type\") @db.VarChar(200)\n sort Int? @map(\"sort\")\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n table GenTable? @relation(fields: [tableId], references: [tableId])\n\n @@index([tableId])\n @@map(\"gen_table_column\")\n}\n\nmodel SysConfig {\n configId Int @id @default(autoincrement()) @map(\"config_id\")\n configName String? @default(\"\") @map(\"config_name\") @db.VarChar(100)\n configKey String? @default(\"\") @map(\"config_key\") @db.VarChar(100)\n configValue String? @default(\"\") @map(\"config_value\") @db.VarChar(500)\n configType String? @default(\"N\") @map(\"config_type\") @db.Char(1)\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n remark String? @map(\"remark\") @db.VarChar(500)\n\n @@map(\"sys_config\")\n}\n\nmodel SysDept {\n deptId Int @id @default(autoincrement()) @map(\"dept_id\") @db.UnsignedInt\n parentId Int? @default(0) @map(\"parent_id\") @db.UnsignedInt\n ancestors String? @default(\"\") @map(\"ancestors\") @db.VarChar(50)\n deptName String? @default(\"\") @map(\"dept_name\") @db.VarChar(30)\n orderNum Int? @default(0) @map(\"order_num\")\n leader String? @map(\"leader\") @db.VarChar(20)\n phone String? @map(\"phone\") @db.VarChar(11)\n email String? @map(\"email\") @db.VarChar(50)\n status String? @default(\"1\") @map(\"status\") @db.Char(1)\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n users SysUser[]\n roles SysRoleDept[]\n\n @@map(\"sys_dept\")\n}\n\nmodel SysDictData {\n dictCode Int @id @default(autoincrement()) @map(\"dict_code\") @db.UnsignedInt\n dictSort Int? @default(0) @map(\"dict_sort\")\n dictLabel String? @default(\"\") @map(\"dict_label\") @db.VarChar(100)\n dictValue String? @default(\"\") @map(\"dict_value\") @db.VarChar(100)\n dictType String? @default(\"\") @map(\"dict_type\") @db.VarChar(100)\n cssClass String? @map(\"css_class\") @db.VarChar(100)\n listClass String? @map(\"list_class\") @db.VarChar(100)\n isDefault String? @default(\"N\") @map(\"is_default\") @db.Char(1)\n status String? @default(\"1\") @map(\"status\") @db.Char(1)\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n remark String? @map(\"remark\") @db.VarChar(500)\n sysDictType SysDictType? @relation(fields: [dictType], references: [dictType])\n\n @@index([dictType])\n @@map(\"sys_dict_data\")\n}\n\nmodel SysDictType {\n dictId Int @id @default(autoincrement()) @map(\"dict_id\") @db.UnsignedInt\n dictName String? @default(\"\") @map(\"dict_name\") @db.VarChar(100)\n dictType String? @unique(map: \"dict_type\") @default(\"\") @map(\"dict_type\") @db.VarChar(100)\n status String? @default(\"1\") @map(\"status\") @db.Char(1)\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n remark String? @map(\"remark\") @db.VarChar(500)\n dictDatas SysDictData[]\n\n @@map(\"sys_dict_type\")\n}\n\nmodel SysLogininfor {\n infoId Int @id @default(autoincrement()) @map(\"info_id\") @db.UnsignedInt\n userName String? @default(\"\") @map(\"user_name\") @db.VarChar(50)\n ipaddr String? @default(\"\") @map(\"ipaddr\") @db.VarChar(128)\n loginLocation String? @default(\"\") @map(\"login_location\") @db.VarChar(255)\n browser String? @default(\"\") @map(\"browser\") @db.VarChar(50)\n os String? @default(\"\") @map(\"os\") @db.VarChar(50)\n status String? @default(\"1\") @map(\"status\") @db.Char(1)\n msg String? @default(\"\") @map(\"msg\") @db.VarChar(255)\n loginTime String? @map(\"login_time\") @db.VarChar(25)\n\n @@index([loginTime], map: \"idx_sys_logininfor_lt\")\n @@index([status], map: \"idx_sys_logininfor_s\")\n @@map(\"sys_logininfor\")\n}\n\nmodel SysMenu {\n menuId Int @id @default(autoincrement()) @map(\"menu_id\") @db.UnsignedInt\n menuName String @map(\"menu_name\") @db.VarChar(50)\n parentId Int? @default(0) @map(\"parent_id\") @db.UnsignedInt\n orderNum Int? @default(0) @map(\"order_num\")\n path String? @default(\"\") @map(\"path\") @db.VarChar(200)\n component String? @map(\"component\") @db.VarChar(255)\n query String? @map(\"query\") @db.VarChar(255)\n isFrame Int? @default(0) @map(\"is_frame\")\n isCache Int? @default(1) @map(\"is_cache\")\n menuType String? @default(\"\") @map(\"menu_type\") @db.Char(1)\n visible String? @default(\"1\") @map(\"visible\") @db.Char(1)\n status String? @default(\"1\") @map(\"status\") @db.Char(1)\n perms String? @map(\"perms\") @db.VarChar(100)\n icon String? @default(\"#\") @map(\"icon\") @db.VarChar(100)\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n remark String? @default(\"\") @map(\"remark\") @db.VarChar(500)\n roles SysRoleMenu[]\n\n @@map(\"sys_menu\")\n}\n\nmodel SysNotice {\n noticeId Int @id @default(autoincrement()) @map(\"notice_id\")\n noticeTitle String @map(\"notice_title\") @db.VarChar(50)\n noticeType String @map(\"notice_type\") @db.Char(1)\n noticeContent String? @map(\"notice_content\") @db.MediumText\n status String? @default(\"1\") @map(\"status\") @db.Char(1)\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n remark String? @map(\"remark\") @db.VarChar(255)\n\n @@map(\"sys_notice\")\n}\n\nmodel SysPost {\n postId Int @id @default(autoincrement()) @map(\"post_id\") @db.UnsignedInt\n postCode String @map(\"post_code\") @db.VarChar(64)\n postName String @map(\"post_name\") @db.VarChar(50)\n postSort Int @map(\"post_sort\")\n status String @default(\"1\") @map(\"status\") @db.Char(1)\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n remark String? @map(\"remark\") @db.VarChar(500)\n users SysUserPost[]\n\n @@map(\"sys_post\")\n}\n\nmodel SysUserPost {\n userId Int @map(\"user_id\") @db.UnsignedInt\n postId Int @map(\"post_id\") @db.UnsignedInt\n user SysUser @relation(fields: [userId], references: [userId])\n post SysPost @relation(fields: [postId], references: [postId])\n\n @@id([userId, postId])\n @@index([postId])\n @@map(\"sys_user_post\")\n}\n\nmodel SysRoleDept {\n roleId Int @map(\"role_id\") @db.UnsignedInt\n deptId Int @map(\"dept_id\") @db.UnsignedInt\n role SysRole @relation(fields: [roleId], references: [roleId])\n dept SysDept @relation(fields: [deptId], references: [deptId])\n\n @@id([roleId, deptId])\n @@index([deptId])\n @@map(\"sys_role_dept\")\n}\n\nmodel SysRoleMenu {\n roleId Int @map(\"role_id\") @db.UnsignedInt\n menuId Int @map(\"menu_id\") @db.UnsignedInt\n menu SysMenu @relation(fields: [menuId], references: [menuId])\n role SysRole @relation(fields: [roleId], references: [roleId])\n\n @@id([roleId, menuId])\n @@index([menuId])\n @@map(\"sys_role_menu\")\n}\n\nmodel SysUser {\n userId Int @id @default(autoincrement()) @map(\"user_id\") @db.UnsignedInt\n deptId Int? @map(\"dept_id\") @db.UnsignedInt\n userName String @map(\"user_name\") @db.VarChar(30)\n nickName String @map(\"nick_name\") @db.VarChar(30)\n userType String? @default(\"00\") @map(\"user_type\") @db.VarChar(2)\n email String? @default(\"\") @map(\"email\") @db.VarChar(50)\n phonenumber String? @default(\"\") @map(\"phonenumber\") @db.VarChar(11)\n sex String? @default(\"0\") @map(\"sex\") @db.Char(1)\n avatar String? @default(\"\") @map(\"avatar\") @db.VarChar(100)\n password String? @default(\"\") @map(\"password\") @db.VarChar(100)\n status String? @default(\"1\") @map(\"status\") @db.Char(1)\n loginIp String? @default(\"\") @map(\"login_ip\") @db.VarChar(128)\n loginDate String? @map(\"login_date\") @db.VarChar(25)\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n remark String? @map(\"remark\") @db.VarChar(500)\n dept SysDept? @relation(fields: [deptId], references: [deptId])\n roles SysUserRole[]\n posts SysUserPost[]\n\n @@index([deptId])\n @@map(\"sys_user\")\n}\n\nmodel SysRole {\n roleId Int @id @default(autoincrement()) @map(\"role_id\") @db.UnsignedInt\n roleName String @map(\"role_name\") @db.VarChar(30)\n roleKey String @map(\"role_key\") @db.VarChar(100)\n roleSort Int @map(\"role_sort\")\n dataScope String? @default(\"5\") @map(\"data_scope\") @db.Char(1)\n menuCheckStrictly Int? @default(1) @map(\"menu_check_strictly\") @db.TinyInt\n deptCheckStrictly Int? @default(1) @map(\"dept_check_strictly\") @db.TinyInt\n status String @default(\"1\") @map(\"status\") @db.Char(1)\n createBy String? @default(\"\") @map(\"create_by\") @db.VarChar(64)\n createTime String? @map(\"create_time\") @db.VarChar(25)\n updateBy String? @default(\"\") @map(\"update_by\") @db.VarChar(64)\n updateTime String? @map(\"update_time\") @db.VarChar(25)\n remark String? @map(\"remark\") @db.VarChar(500)\n users SysUserRole[]\n menus SysRoleMenu[]\n depts SysRoleDept[]\n\n @@map(\"sys_role\")\n}\n\nmodel SysUserRole {\n userId Int @map(\"user_id\") @db.UnsignedInt\n roleId Int @map(\"role_id\") @db.UnsignedInt\n user SysUser @relation(fields: [userId], references: [userId])\n role SysRole @relation(fields: [roleId], references: [roleId])\n\n @@id([userId, roleId])\n @@index([roleId])\n @@map(\"sys_user_role\")\n}\n\ngenerator client {\n provider = \"prisma-client-js\"\n output = \"./common/prisma-client\"\n previewFeatures = [\"views\", \"relationJoins\", \"prismaSchemaFolder\", \"omitApi\"]\n //这里可以指定平台引擎,native就是当前系统, 如果需要其他系统的自行添加,或者到目标系统执行npx prisma generate\n binaryTargets = [\"native\"]\n // binaryTargets = [\"native\", \"windows\", \"linux-musl\",\"debian-openssl-3.0.x\",\"darwin\",\"darwin-arm64\"]\n}\n\ndatasource db {\n provider = \"mysql\"\n url = env(\"DATABASE_URL\")\n relationMode = \"prisma\"\n}\n",
"inlineSchemaHash": "0b0d574d7aafbd1cd7ba47583488b808df1af0e6a2ca704e20a74708d2aad32a",
"copyEngine": true
}
config.dirname = '/'
config.runtimeDataModel = JSON.parse("{\"models\":{\"GenTable\":{\"dbName\":\"gen_table\",\"fields\":[{\"name\":\"tableId\",\"dbName\":\"table_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tableName\",\"dbName\":\"table_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tableComment\",\"dbName\":\"table_comment\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"subTableName\",\"dbName\":\"sub_table_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"subTableFkName\",\"dbName\":\"sub_table_fk_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"className\",\"dbName\":\"class_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tplCategory\",\"dbName\":\"tpl_category\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"crud\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tplWebType\",\"dbName\":\"tpl_web_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"packageName\",\"dbName\":\"package_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"moduleName\",\"dbName\":\"module_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"businessName\",\"dbName\":\"business_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"functionName\",\"dbName\":\"function_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"functionAuthor\",\"dbName\":\"function_author\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"genType\",\"dbName\":\"gen_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"0\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"genPath\",\"dbName\":\"gen_path\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"/\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"options\",\"dbName\":\"options\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"remark\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tableColumns\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"GenTableColumn\",\"relationName\":\"GenTableToGenTableColumn\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"GenTableColumn\":{\"dbName\":\"gen_table_column\",\"fields\":[{\"name\":\"columnId\",\"dbName\":\"column_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tableId\",\"dbName\":\"table_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"columnName\",\"dbName\":\"column_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"columnComment\",\"dbName\":\"column_comment\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"columnType\",\"dbName\":\"column_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"javaType\",\"dbName\":\"java_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"javaField\",\"dbName\":\"java_field\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isPk\",\"dbName\":\"is_pk\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isIncrement\",\"dbName\":\"is_increment\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isRequired\",\"dbName\":\"is_required\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isInsert\",\"dbName\":\"is_insert\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isEdit\",\"dbName\":\"is_edit\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isList\",\"dbName\":\"is_list\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isQuery\",\"dbName\":\"is_query\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"queryType\",\"dbName\":\"query_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"EQ\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"htmlType\",\"dbName\":\"html_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dictType\",\"dbName\":\"dict_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sort\",\"dbName\":\"sort\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"table\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"GenTable\",\"relationName\":\"GenTableToGenTableColumn\",\"relationFromFields\":[\"tableId\"],\"relationToFields\":[\"tableId\"],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysConfig\":{\"dbName\":\"sys_config\",\"fields\":[{\"name\":\"configId\",\"dbName\":\"config_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"configName\",\"dbName\":\"config_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"configKey\",\"dbName\":\"config_key\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"configValue\",\"dbName\":\"config_value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"configType\",\"dbName\":\"config_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"N\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"remark\",\"dbName\":\"remark\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysDept\":{\"dbName\":\"sys_dept\",\"fields\":[{\"name\":\"deptId\",\"dbName\":\"dept_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"parentId\",\"dbName\":\"parent_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"ancestors\",\"dbName\":\"ancestors\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deptName\",\"dbName\":\"dept_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"orderNum\",\"dbName\":\"order_num\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"leader\",\"dbName\":\"leader\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phone\",\"dbName\":\"phone\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"dbName\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"dbName\":\"status\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"1\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"users\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysUser\",\"relationName\":\"SysDeptToSysUser\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysRoleDept\",\"relationName\":\"SysDeptToSysRoleDept\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysDictData\":{\"dbName\":\"sys_dict_data\",\"fields\":[{\"name\":\"dictCode\",\"dbName\":\"dict_code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dictSort\",\"dbName\":\"dict_sort\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dictLabel\",\"dbName\":\"dict_label\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dictValue\",\"dbName\":\"dict_value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dictType\",\"dbName\":\"dict_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cssClass\",\"dbName\":\"css_class\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"listClass\",\"dbName\":\"list_class\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDefault\",\"dbName\":\"is_default\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"N\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"dbName\":\"status\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"1\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"remark\",\"dbName\":\"remark\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sysDictType\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysDictType\",\"relationName\":\"SysDictDataToSysDictType\",\"relationFromFields\":[\"dictType\"],\"relationToFields\":[\"dictType\"],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysDictType\":{\"dbName\":\"sys_dict_type\",\"fields\":[{\"name\":\"dictId\",\"dbName\":\"dict_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dictName\",\"dbName\":\"dict_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dictType\",\"dbName\":\"dict_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"dbName\":\"status\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"1\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"remark\",\"dbName\":\"remark\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dictDatas\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysDictData\",\"relationName\":\"SysDictDataToSysDictType\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysLogininfor\":{\"dbName\":\"sys_logininfor\",\"fields\":[{\"name\":\"infoId\",\"dbName\":\"info_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"userName\",\"dbName\":\"user_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"ipaddr\",\"dbName\":\"ipaddr\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"loginLocation\",\"dbName\":\"login_location\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"browser\",\"dbName\":\"browser\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"os\",\"dbName\":\"os\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"dbName\":\"status\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"1\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"msg\",\"dbName\":\"msg\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"loginTime\",\"dbName\":\"login_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysMenu\":{\"dbName\":\"sys_menu\",\"fields\":[{\"name\":\"menuId\",\"dbName\":\"menu_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"menuName\",\"dbName\":\"menu_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"parentId\",\"dbName\":\"parent_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"orderNum\",\"dbName\":\"order_num\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"path\",\"dbName\":\"path\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"component\",\"dbName\":\"component\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"query\",\"dbName\":\"query\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isFrame\",\"dbName\":\"is_frame\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isCache\",\"dbName\":\"is_cache\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":1,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"menuType\",\"dbName\":\"menu_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"visible\",\"dbName\":\"visible\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"1\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"dbName\":\"status\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"1\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"perms\",\"dbName\":\"perms\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"icon\",\"dbName\":\"icon\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"#\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"remark\",\"dbName\":\"remark\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysRoleMenu\",\"relationName\":\"SysMenuToSysRoleMenu\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysNotice\":{\"dbName\":\"sys_notice\",\"fields\":[{\"name\":\"noticeId\",\"dbName\":\"notice_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"noticeTitle\",\"dbName\":\"notice_title\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"noticeType\",\"dbName\":\"notice_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"noticeContent\",\"dbName\":\"notice_content\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"dbName\":\"status\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"1\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"remark\",\"dbName\":\"remark\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysPost\":{\"dbName\":\"sys_post\",\"fields\":[{\"name\":\"postId\",\"dbName\":\"post_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"postCode\",\"dbName\":\"post_code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"postName\",\"dbName\":\"post_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"postSort\",\"dbName\":\"post_sort\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"dbName\":\"status\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"1\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"remark\",\"dbName\":\"remark\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"users\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysUserPost\",\"relationName\":\"SysPostToSysUserPost\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysUserPost\":{\"dbName\":\"sys_user_post\",\"fields\":[{\"name\":\"userId\",\"dbName\":\"user_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"postId\",\"dbName\":\"post_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysUser\",\"relationName\":\"SysUserToSysUserPost\",\"relationFromFields\":[\"userId\"],\"relationToFields\":[\"userId\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"post\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysPost\",\"relationName\":\"SysPostToSysUserPost\",\"relationFromFields\":[\"postId\"],\"relationToFields\":[\"postId\"],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"userId\",\"postId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysRoleDept\":{\"dbName\":\"sys_role_dept\",\"fields\":[{\"name\":\"roleId\",\"dbName\":\"role_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deptId\",\"dbName\":\"dept_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysRole\",\"relationName\":\"SysRoleToSysRoleDept\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"roleId\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dept\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysDept\",\"relationName\":\"SysDeptToSysRoleDept\",\"relationFromFields\":[\"deptId\"],\"relationToFields\":[\"deptId\"],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"roleId\",\"deptId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysRoleMenu\":{\"dbName\":\"sys_role_menu\",\"fields\":[{\"name\":\"roleId\",\"dbName\":\"role_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"menuId\",\"dbName\":\"menu_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"menu\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysMenu\",\"relationName\":\"SysMenuToSysRoleMenu\",\"relationFromFields\":[\"menuId\"],\"relationToFields\":[\"menuId\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysRole\",\"relationName\":\"SysRoleToSysRoleMenu\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"roleId\"],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"roleId\",\"menuId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysUser\":{\"dbName\":\"sys_user\",\"fields\":[{\"name\":\"userId\",\"dbName\":\"user_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deptId\",\"dbName\":\"dept_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"userName\",\"dbName\":\"user_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"nickName\",\"dbName\":\"nick_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"userType\",\"dbName\":\"user_type\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"00\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"dbName\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phonenumber\",\"dbName\":\"phonenumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sex\",\"dbName\":\"sex\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"0\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"avatar\",\"dbName\":\"avatar\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"password\",\"dbName\":\"password\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"dbName\":\"status\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"1\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"loginIp\",\"dbName\":\"login_ip\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"loginDate\",\"dbName\":\"login_date\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"remark\",\"dbName\":\"remark\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dept\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysDept\",\"relationName\":\"SysDeptToSysUser\",\"relationFromFields\":[\"deptId\"],\"relationToFields\":[\"deptId\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysUserRole\",\"relationName\":\"SysUserToSysUserRole\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"posts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysUserPost\",\"relationName\":\"SysUserToSysUserPost\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysRole\":{\"dbName\":\"sys_role\",\"fields\":[{\"name\":\"roleId\",\"dbName\":\"role_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roleName\",\"dbName\":\"role_name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roleKey\",\"dbName\":\"role_key\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roleSort\",\"dbName\":\"role_sort\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dataScope\",\"dbName\":\"data_scope\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"5\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"menuCheckStrictly\",\"dbName\":\"menu_check_strictly\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":1,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deptCheckStrictly\",\"dbName\":\"dept_check_strictly\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":1,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"dbName\":\"status\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"1\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createBy\",\"dbName\":\"create_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createTime\",\"dbName\":\"create_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateBy\",\"dbName\":\"update_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updateTime\",\"dbName\":\"update_time\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"remark\",\"dbName\":\"remark\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"users\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysUserRole\",\"relationName\":\"SysRoleToSysUserRole\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"menus\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysRoleMenu\",\"relationName\":\"SysRoleToSysRoleMenu\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"depts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysRoleDept\",\"relationName\":\"SysRoleToSysRoleDept\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SysUserRole\":{\"dbName\":\"sys_user_role\",\"fields\":[{\"name\":\"userId\",\"dbName\":\"user_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roleId\",\"dbName\":\"role_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysUser\",\"relationName\":\"SysUserToSysUserRole\",\"relationFromFields\":[\"userId\"],\"relationToFields\":[\"userId\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SysRole\",\"relationName\":\"SysRoleToSysUserRole\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"roleId\"],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"userId\",\"roleId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{},\"types\":{}}")
defineDmmfProperty(exports.Prisma, config.runtimeDataModel)
config.engineWasm = undefined
config.injectableEdgeEnv = () => ({
parsed: {
DATABASE_URL: typeof globalThis !== 'undefined' && globalThis['DATABASE_URL'] || typeof process !== 'undefined' && process.env && process.env.DATABASE_URL || undefined
}
})
if (typeof globalThis !== 'undefined' && globalThis['DEBUG'] || typeof process !== 'undefined' && process.env && process.env.DEBUG || undefined) {
Debug.enable(typeof globalThis !== 'undefined' && globalThis['DEBUG'] || typeof process !== 'undefined' && process.env && process.env.DEBUG || undefined)
}
const PrismaClient = getPrismaClient(config)
exports.PrismaClient = PrismaClient
Object.assign(exports, Prisma)
================================================
FILE: server/src/common/prisma-client/index-browser.js
================================================
Object.defineProperty(exports, "__esModule", { value: true });
const {
Decimal,
objectEnumValues,
makeStrictEnum,
Public,
getRuntime,
} = require('./runtime/index-browser.js')
const Prisma = {}
exports.Prisma = Prisma
exports.$Enums = {}
/**
* Prisma Client JS version: 5.15.0
* Query Engine version: 12e25d8d06f6ea5a0252864dd9a03b1bb51f3022
*/
Prisma.prismaVersion = {
client: "5.15.0",
engine: "12e25d8d06f6ea5a0252864dd9a03b1bb51f3022"
}
Prisma.PrismaClientKnownRequestError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientKnownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)};
Prisma.PrismaClientUnknownRequestError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientUnknownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.PrismaClientRustPanicError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientRustPanicError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.PrismaClientInitializationError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientInitializationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.PrismaClientValidationError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientValidationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.NotFoundError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`NotFoundError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.Decimal = Decimal
/**
* Re-export of sql-template-tag
*/
Prisma.sql = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`sqltag is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.empty = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`empty is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.join = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`join is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.raw = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`raw is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.validator = Public.validator
/**
* Extensions
*/
Prisma.getExtensionContext = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`Extensions.getExtensionContext is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.defineExtension = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`Extensions.defineExtension is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
/**
* Shorthand utilities for JSON filtering
*/
Prisma.DbNull = objectEnumValues.instances.DbNull
Prisma.JsonNull = objectEnumValues.instances.JsonNull
Prisma.AnyNull = objectEnumValues.instances.AnyNull
Prisma.NullTypes = {
DbNull: objectEnumValues.classes.DbNull,
JsonNull: objectEnumValues.classes.JsonNull,
AnyNull: objectEnumValues.classes.AnyNull
}
/**
* Enums
*/
exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
ReadUncommitted: 'ReadUncommitted',
ReadCommitted: 'ReadCommitted',
RepeatableRead: 'RepeatableRead',
Serializable: 'Serializable'
});
exports.Prisma.GenTableScalarFieldEnum = {
tableId: 'tableId',
tableName: 'tableName',
tableComment: 'tableComment',
subTableName: 'subTableName',
subTableFkName: 'subTableFkName',
className: 'className',
tplCategory: 'tplCategory',
tplWebType: 'tplWebType',
packageName: 'packageName',
moduleName: 'moduleName',
businessName: 'businessName',
functionName: 'functionName',
functionAuthor: 'functionAuthor',
genType: 'genType',
genPath: 'genPath',
options: 'options',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.RelationLoadStrategy = {
query: 'query',
join: 'join'
};
exports.Prisma.GenTableColumnScalarFieldEnum = {
columnId: 'columnId',
tableId: 'tableId',
columnName: 'columnName',
columnComment: 'columnComment',
columnType: 'columnType',
javaType: 'javaType',
javaField: 'javaField',
isPk: 'isPk',
isIncrement: 'isIncrement',
isRequired: 'isRequired',
isInsert: 'isInsert',
isEdit: 'isEdit',
isList: 'isList',
isQuery: 'isQuery',
queryType: 'queryType',
htmlType: 'htmlType',
dictType: 'dictType',
sort: 'sort',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime'
};
exports.Prisma.SysConfigScalarFieldEnum = {
configId: 'configId',
configName: 'configName',
configKey: 'configKey',
configValue: 'configValue',
configType: 'configType',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysDeptScalarFieldEnum = {
deptId: 'deptId',
parentId: 'parentId',
ancestors: 'ancestors',
deptName: 'deptName',
orderNum: 'orderNum',
leader: 'leader',
phone: 'phone',
email: 'email',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime'
};
exports.Prisma.SysDictDataScalarFieldEnum = {
dictCode: 'dictCode',
dictSort: 'dictSort',
dictLabel: 'dictLabel',
dictValue: 'dictValue',
dictType: 'dictType',
cssClass: 'cssClass',
listClass: 'listClass',
isDefault: 'isDefault',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysDictTypeScalarFieldEnum = {
dictId: 'dictId',
dictName: 'dictName',
dictType: 'dictType',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysLogininforScalarFieldEnum = {
infoId: 'infoId',
userName: 'userName',
ipaddr: 'ipaddr',
loginLocation: 'loginLocation',
browser: 'browser',
os: 'os',
status: 'status',
msg: 'msg',
loginTime: 'loginTime'
};
exports.Prisma.SysMenuScalarFieldEnum = {
menuId: 'menuId',
menuName: 'menuName',
parentId: 'parentId',
orderNum: 'orderNum',
path: 'path',
component: 'component',
query: 'query',
isFrame: 'isFrame',
isCache: 'isCache',
menuType: 'menuType',
visible: 'visible',
status: 'status',
perms: 'perms',
icon: 'icon',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysNoticeScalarFieldEnum = {
noticeId: 'noticeId',
noticeTitle: 'noticeTitle',
noticeType: 'noticeType',
noticeContent: 'noticeContent',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysPostScalarFieldEnum = {
postId: 'postId',
postCode: 'postCode',
postName: 'postName',
postSort: 'postSort',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysUserPostScalarFieldEnum = {
userId: 'userId',
postId: 'postId'
};
exports.Prisma.SysRoleDeptScalarFieldEnum = {
roleId: 'roleId',
deptId: 'deptId'
};
exports.Prisma.SysRoleMenuScalarFieldEnum = {
roleId: 'roleId',
menuId: 'menuId'
};
exports.Prisma.SysUserScalarFieldEnum = {
userId: 'userId',
deptId: 'deptId',
userName: 'userName',
nickName: 'nickName',
userType: 'userType',
email: 'email',
phonenumber: 'phonenumber',
sex: 'sex',
avatar: 'avatar',
password: 'password',
status: 'status',
loginIp: 'loginIp',
loginDate: 'loginDate',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysRoleScalarFieldEnum = {
roleId: 'roleId',
roleName: 'roleName',
roleKey: 'roleKey',
roleSort: 'roleSort',
dataScope: 'dataScope',
menuCheckStrictly: 'menuCheckStrictly',
deptCheckStrictly: 'deptCheckStrictly',
status: 'status',
createBy: 'createBy',
createTime: 'createTime',
updateBy: 'updateBy',
updateTime: 'updateTime',
remark: 'remark'
};
exports.Prisma.SysUserRoleScalarFieldEnum = {
userId: 'userId',
roleId: 'roleId'
};
exports.Prisma.SortOrder = {
asc: 'asc',
desc: 'desc'
};
exports.Prisma.NullsOrder = {
first: 'first',
last: 'last'
};
exports.Prisma.ModelName = {
GenTable: 'GenTable',
GenTableColumn: 'GenTableColumn',
SysConfig: 'SysConfig',
SysDept: 'SysDept',
SysDictData: 'SysDictData',
SysDictType: 'SysDictType',
SysLogininfor: 'SysLogininfor',
SysMenu: 'SysMenu',
SysNotice: 'SysNotice',
SysPost: 'SysPost',
SysUserPost: 'SysUserPost',
SysRoleDept: 'SysRoleDept',
SysRoleMenu: 'SysRoleMenu',
SysUser: 'SysUser',
SysRole: 'SysRole',
SysUserRole: 'SysUserRole'
};
/**
* This is a stub Prisma Client that will error at runtime if called.
*/
class PrismaClient {
constructor() {
return new Proxy(this, {
get(target, prop) {
let message
const runtime = getRuntime()
if (runtime.isEdge) {
message = `PrismaClient is not configured to run in ${runtime.prettyName}. In order to run Prisma Client on edge runtime, either:
- Use Prisma Accelerate: https://pris.ly/d/accelerate
- Use Driver Adapters: https://pris.ly/d/driver-adapters
`;
} else {
message = 'PrismaClient is unable to run in this browser environment, or has been bundled for the browser (running in `' + runtime.prettyName + '`).'
}
message += `
If this is unexpected, please open an issue: https://pris.ly/prisma-prisma-bug-report`
throw new Error(message)
}
})
}
}
exports.PrismaClient = PrismaClient
Object.assign(exports, Prisma)
================================================
FILE: server/src/common/prisma-client/index.d.ts
================================================
/**
* Client
**/
import * as runtime from './runtime/library.js';
import $Types = runtime.Types // general types
import $Public = runtime.Types.Public
import $Utils = runtime.Types.Utils
import $Extensions = runtime.Types.Extensions
import $Result = runtime.Types.Result
export type PrismaPromise = $Public.PrismaPromise
/**
* Model GenTable
*
*/
export type GenTable = $Result.DefaultSelection
/**
* Model GenTableColumn
*
*/
export type GenTableColumn = $Result.DefaultSelection
/**
* Model SysConfig
*
*/
export type SysConfig = $Result.DefaultSelection
/**
* Model SysDept
*
*/
export type SysDept = $Result.DefaultSelection
/**
* Model SysDictData
*
*/
export type SysDictData = $Result.DefaultSelection
/**
* Model SysDictType
*
*/
export type SysDictType = $Result.DefaultSelection
/**
* Model SysLogininfor
*
*/
export type SysLogininfor = $Result.DefaultSelection
/**
* Model SysMenu
*
*/
export type SysMenu = $Result.DefaultSelection
/**
* Model SysNotice
*
*/
export type SysNotice = $Result.DefaultSelection
/**
* Model SysPost
*
*/
export type SysPost = $Result.DefaultSelection
/**
* Model SysUserPost
*
*/
export type SysUserPost = $Result.DefaultSelection
/**
* Model SysRoleDept
*
*/
export type SysRoleDept = $Result.DefaultSelection
/**
* Model SysRoleMenu
*
*/
export type SysRoleMenu = $Result.DefaultSelection
/**
* Model SysUser
*
*/
export type SysUser = $Result.DefaultSelection
/**
* Model SysRole
*
*/
export type SysRole = $Result.DefaultSelection
/**
* Model SysUserRole
*
*/
export type SysUserRole = $Result.DefaultSelection
/**
* ## Prisma Client ʲˢ
*
* Type-safe database client for TypeScript & Node.js
* @example
* ```
* const prisma = new PrismaClient()
* // Fetch zero or more GenTables
* const genTables = await prisma.genTable.findMany()
* ```
*
*
* Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client).
*/
export class PrismaClient<
T extends Prisma.PrismaClientOptions = Prisma.PrismaClientOptions,
U = 'log' extends keyof T ? T['log'] extends Array ? Prisma.GetEvents : never : never,
ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs
> {
[K: symbol]: { types: Prisma.TypeMap['other'] }
/**
* ## Prisma Client ʲˢ
*
* Type-safe database client for TypeScript & Node.js
* @example
* ```
* const prisma = new PrismaClient()
* // Fetch zero or more GenTables
* const genTables = await prisma.genTable.findMany()
* ```
*
*
* Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client).
*/
constructor(optionsArg ?: Prisma.Subset);
$on(eventType: V, callback: (event: V extends 'query' ? Prisma.QueryEvent : Prisma.LogEvent) => void): void;
/**
* Connect with the database
*/
$connect(): $Utils.JsPromise;
/**
* Disconnect from the database
*/
$disconnect(): $Utils.JsPromise;
/**
* Add a middleware
* @deprecated since 4.16.0. For new code, prefer client extensions instead.
* @see https://pris.ly/d/extensions
*/
$use(cb: Prisma.Middleware): void
/**
* Executes a prepared raw query and returns the number of affected rows.
* @example
* ```
* const result = await prisma.$executeRaw`UPDATE User SET cool = ${true} WHERE email = ${'user@email.com'};`
* ```
*
* Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access).
*/
$executeRaw(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise;
/**
* Executes a raw query and returns the number of affected rows.
* Susceptible to SQL injections, see documentation.
* @example
* ```
* const result = await prisma.$executeRawUnsafe('UPDATE User SET cool = $1 WHERE email = $2 ;', true, 'user@email.com')
* ```
*
* Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access).
*/
$executeRawUnsafe(query: string, ...values: any[]): Prisma.PrismaPromise;
/**
* Performs a prepared raw query and returns the `SELECT` data.
* @example
* ```
* const result = await prisma.$queryRaw`SELECT * FROM User WHERE id = ${1} OR email = ${'user@email.com'};`
* ```
*
* Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access).
*/
$queryRaw(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise;
/**
* Performs a raw query and returns the `SELECT` data.
* Susceptible to SQL injections, see documentation.
* @example
* ```
* const result = await prisma.$queryRawUnsafe('SELECT * FROM User WHERE id = $1 OR email = $2;', 1, 'user@email.com')
* ```
*
* Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access).
*/
$queryRawUnsafe(query: string, ...values: any[]): Prisma.PrismaPromise;
/**
* Allows the running of a sequence of read/write operations that are guaranteed to either succeed or fail as a whole.
* @example
* ```
* const [george, bob, alice] = await prisma.$transaction([
* prisma.user.create({ data: { name: 'George' } }),
* prisma.user.create({ data: { name: 'Bob' } }),
* prisma.user.create({ data: { name: 'Alice' } }),
* ])
* ```
*
* Read more in our [docs](https://www.prisma.io/docs/concepts/components/prisma-client/transactions).
*/
$transaction[]>(arg: [...P], options?: { isolationLevel?: Prisma.TransactionIsolationLevel }): $Utils.JsPromise>
$transaction(fn: (prisma: Omit) => $Utils.JsPromise, options?: { maxWait?: number, timeout?: number, isolationLevel?: Prisma.TransactionIsolationLevel }): $Utils.JsPromise
$extends: $Extensions.ExtendsHook<'extends', Prisma.TypeMapCb, ExtArgs>
/**
* `prisma.genTable`: Exposes CRUD operations for the **GenTable** model.
* Example usage:
* ```ts
* // Fetch zero or more GenTables
* const genTables = await prisma.genTable.findMany()
* ```
*/
get genTable(): Prisma.GenTableDelegate;
/**
* `prisma.genTableColumn`: Exposes CRUD operations for the **GenTableColumn** model.
* Example usage:
* ```ts
* // Fetch zero or more GenTableColumns
* const genTableColumns = await prisma.genTableColumn.findMany()
* ```
*/
get genTableColumn(): Prisma.GenTableColumnDelegate;
/**
* `prisma.sysConfig`: Exposes CRUD operations for the **SysConfig** model.
* Example usage:
* ```ts
* // Fetch zero or more SysConfigs
* const sysConfigs = await prisma.sysConfig.findMany()
* ```
*/
get sysConfig(): Prisma.SysConfigDelegate;
/**
* `prisma.sysDept`: Exposes CRUD operations for the **SysDept** model.
* Example usage:
* ```ts
* // Fetch zero or more SysDepts
* const sysDepts = await prisma.sysDept.findMany()
* ```
*/
get sysDept(): Prisma.SysDeptDelegate;
/**
* `prisma.sysDictData`: Exposes CRUD operations for the **SysDictData** model.
* Example usage:
* ```ts
* // Fetch zero or more SysDictData
* const sysDictData = await prisma.sysDictData.findMany()
* ```
*/
get sysDictData(): Prisma.SysDictDataDelegate;
/**
* `prisma.sysDictType`: Exposes CRUD operations for the **SysDictType** model.
* Example usage:
* ```ts
* // Fetch zero or more SysDictTypes
* const sysDictTypes = await prisma.sysDictType.findMany()
* ```
*/
get sysDictType(): Prisma.SysDictTypeDelegate;
/**
* `prisma.sysLogininfor`: Exposes CRUD operations for the **SysLogininfor** model.
* Example usage:
* ```ts
* // Fetch zero or more SysLogininfors
* const sysLogininfors = await prisma.sysLogininfor.findMany()
* ```
*/
get sysLogininfor(): Prisma.SysLogininforDelegate;
/**
* `prisma.sysMenu`: Exposes CRUD operations for the **SysMenu** model.
* Example usage:
* ```ts
* // Fetch zero or more SysMenus
* const sysMenus = await prisma.sysMenu.findMany()
* ```
*/
get sysMenu(): Prisma.SysMenuDelegate;
/**
* `prisma.sysNotice`: Exposes CRUD operations for the **SysNotice** model.
* Example usage:
* ```ts
* // Fetch zero or more SysNotices
* const sysNotices = await prisma.sysNotice.findMany()
* ```
*/
get sysNotice(): Prisma.SysNoticeDelegate;
/**
* `prisma.sysPost`: Exposes CRUD operations for the **SysPost** model.
* Example usage:
* ```ts
* // Fetch zero or more SysPosts
* const sysPosts = await prisma.sysPost.findMany()
* ```
*/
get sysPost(): Prisma.SysPostDelegate;
/**
* `prisma.sysUserPost`: Exposes CRUD operations for the **SysUserPost** model.
* Example usage:
* ```ts
* // Fetch zero or more SysUserPosts
* const sysUserPosts = await prisma.sysUserPost.findMany()
* ```
*/
get sysUserPost(): Prisma.SysUserPostDelegate;
/**
* `prisma.sysRoleDept`: Exposes CRUD operations for the **SysRoleDept** model.
* Example usage:
* ```ts
* // Fetch zero or more SysRoleDepts
* const sysRoleDepts = await prisma.sysRoleDept.findMany()
* ```
*/
get sysRoleDept(): Prisma.SysRoleDeptDelegate;
/**
* `prisma.sysRoleMenu`: Exposes CRUD operations for the **SysRoleMenu** model.
* Example usage:
* ```ts
* // Fetch zero or more SysRoleMenus
* const sysRoleMenus = await prisma.sysRoleMenu.findMany()
* ```
*/
get sysRoleMenu(): Prisma.SysRoleMenuDelegate;
/**
* `prisma.sysUser`: Exposes CRUD operations for the **SysUser** model.
* Example usage:
* ```ts
* // Fetch zero or more SysUsers
* const sysUsers = await prisma.sysUser.findMany()
* ```
*/
get sysUser(): Prisma.SysUserDelegate;
/**
* `prisma.sysRole`: Exposes CRUD operations for the **SysRole** model.
* Example usage:
* ```ts
* // Fetch zero or more SysRoles
* const sysRoles = await prisma.sysRole.findMany()
* ```
*/
get sysRole(): Prisma.SysRoleDelegate;
/**
* `prisma.sysUserRole`: Exposes CRUD operations for the **SysUserRole** model.
* Example usage:
* ```ts
* // Fetch zero or more SysUserRoles
* const sysUserRoles = await prisma.sysUserRole.findMany()
* ```
*/
get sysUserRole(): Prisma.SysUserRoleDelegate;
}
export namespace Prisma {
export import DMMF = runtime.DMMF
export type PrismaPromise = $Public.PrismaPromise
/**
* Validator
*/
export import validator = runtime.Public.validator
/**
* Prisma Errors
*/
export import PrismaClientKnownRequestError = runtime.PrismaClientKnownRequestError
export import PrismaClientUnknownRequestError = runtime.PrismaClientUnknownRequestError
export import PrismaClientRustPanicError = runtime.PrismaClientRustPanicError
export import PrismaClientInitializationError = runtime.PrismaClientInitializationError
export import PrismaClientValidationError = runtime.PrismaClientValidationError
export import NotFoundError = runtime.NotFoundError
/**
* Re-export of sql-template-tag
*/
export import sql = runtime.sqltag
export import empty = runtime.empty
export import join = runtime.join
export import raw = runtime.raw
export import Sql = runtime.Sql
/**
* Decimal.js
*/
export import Decimal = runtime.Decimal
export type DecimalJsLike = runtime.DecimalJsLike
/**
* Metrics
*/
export type Metrics = runtime.Metrics
export type Metric = runtime.Metric
export type MetricHistogram = runtime.MetricHistogram
export type MetricHistogramBucket = runtime.MetricHistogramBucket
/**
* Extensions
*/
export import Extension = $Extensions.UserArgs
export import getExtensionContext = runtime.Extensions.getExtensionContext
export import Args = $Public.Args
export import Payload = $Public.Payload
export import Result = $Public.Result
export import Exact = $Public.Exact
/**
* Prisma Client JS version: 5.15.0
* Query Engine version: 12e25d8d06f6ea5a0252864dd9a03b1bb51f3022
*/
export type PrismaVersion = {
client: string
}
export const prismaVersion: PrismaVersion
/**
* Utility Types
*/
/**
* From https://github.com/sindresorhus/type-fest/
* Matches a JSON object.
* This type can be useful to enforce some input to be JSON-compatible or as a super-type to be extended from.
*/
export type JsonObject = {[Key in string]?: JsonValue}
/**
* From https://github.com/sindresorhus/type-fest/
* Matches a JSON array.
*/
export interface JsonArray extends Array {}
/**
* From https://github.com/sindresorhus/type-fest/
* Matches any valid JSON value.
*/
export type JsonValue = string | number | boolean | JsonObject | JsonArray | null
/**
* Matches a JSON object.
* Unlike `JsonObject`, this type allows undefined and read-only properties.
*/
export type InputJsonObject = {readonly [Key in string]?: InputJsonValue | null}
/**
* Matches a JSON array.
* Unlike `JsonArray`, readonly arrays are assignable to this type.
*/
export interface InputJsonArray extends ReadonlyArray {}
/**
* Matches any valid value that can be used as an input for operations like
* create and update as the value of a JSON field. Unlike `JsonValue`, this
* type allows read-only arrays and read-only object properties and disallows
* `null` at the top level.
*
* `null` cannot be used as the value of a JSON field because its meaning
* would be ambiguous. Use `Prisma.JsonNull` to store the JSON null value or
* `Prisma.DbNull` to clear the JSON value and set the field to the database
* NULL value instead.
*
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-by-null-values
*/
export type InputJsonValue = string | number | boolean | InputJsonObject | InputJsonArray | { toJSON(): unknown }
/**
* Types of the values used to represent different kinds of `null` values when working with JSON fields.
*
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/
namespace NullTypes {
/**
* Type of `Prisma.DbNull`.
*
* You cannot use other instances of this class. Please use the `Prisma.DbNull` value.
*
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/
class DbNull {
private DbNull: never
private constructor()
}
/**
* Type of `Prisma.JsonNull`.
*
* You cannot use other instances of this class. Please use the `Prisma.JsonNull` value.
*
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/
class JsonNull {
private JsonNull: never
private constructor()
}
/**
* Type of `Prisma.AnyNull`.
*
* You cannot use other instances of this class. Please use the `Prisma.AnyNull` value.
*
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/
class AnyNull {
private AnyNull: never
private constructor()
}
}
/**
* Helper for filtering JSON entries that have `null` on the database (empty on the db)
*
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/
export const DbNull: NullTypes.DbNull
/**
* Helper for filtering JSON entries that have JSON `null` values (not empty on the db)
*
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/
export const JsonNull: NullTypes.JsonNull
/**
* Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`
*
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/
export const AnyNull: NullTypes.AnyNull
type SelectAndInclude = {
select: any
include: any
}
type SelectAndOmit = {
select: any
omit: any
}
/**
* Get the type of the value, that the Promise holds.
*/
export type PromiseType> = T extends PromiseLike ? U : T;
/**
* Get the return type of a function which returns a Promise.
*/
export type PromiseReturnType $Utils.JsPromise> = PromiseType>
/**
* From T, pick a set of properties whose keys are in the union K
*/
type Prisma__Pick = {
[P in K]: T[P];
};
export type Enumerable = T | Array;
export type RequiredKeys = {
[K in keyof T]-?: {} extends Prisma__Pick ? never : K
}[keyof T]
export type TruthyKeys = keyof {
[K in keyof T as T[K] extends false | undefined | null ? never : K]: K
}
export type TrueKeys = TruthyKeys>>
/**
* Subset
* @desc From `T` pick properties that exist in `U`. Simple version of Intersection
*/
export type Subset = {
[key in keyof T]: key extends keyof U ? T[key] : never;
};
/**
* SelectSubset
* @desc From `T` pick properties that exist in `U`. Simple version of Intersection.
* Additionally, it validates, if both select and include are present. If the case, it errors.
*/
export type SelectSubset = {
[key in keyof T]: key extends keyof U ? T[key] : never
} &
(T extends SelectAndInclude
? 'Please either choose `select` or `include`.'
: T extends SelectAndOmit
? 'Please either choose `select` or `omit`.'
: {})
/**
* Subset + Intersection
* @desc From `T` pick properties that exist in `U` and intersect `K`
*/
export type SubsetIntersection = {
[key in keyof T]: key extends keyof U ? T[key] : never
} &
K
type Without = { [P in Exclude]?: never };
/**
* XOR is needed to have a real mutually exclusive union type
* https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types
*/
type XOR =
T extends object ?
U extends object ?
(Without & U) | (Without & T)
: U : T
/**
* Is T a Record?
*/
type IsObject = T extends Array
? False
: T extends Date
? False
: T extends Uint8Array
? False
: T extends BigInt
? False
: T extends object
? True
: False
/**
* If it's T[], return T
*/
export type UnEnumerate = T extends Array ? U : T
/**
* From ts-toolbelt
*/
type __Either = Omit &
{
// Merge all but K
[P in K]: Prisma__Pick // With K possibilities
}[K]
type EitherStrict = Strict<__Either>
type EitherLoose = ComputeRaw<__Either>
type _Either<
O extends object,
K extends Key,
strict extends Boolean
> = {
1: EitherStrict
0: EitherLoose
}[strict]
type Either<
O extends object,
K extends Key,
strict extends Boolean = 1
> = O extends unknown ? _Either : never
export type Union = any
type PatchUndefined = {
[K in keyof O]: O[K] extends undefined ? At : O[K]
} & {}
/** Helper Types for "Merge" **/
export type IntersectOf = (
U extends unknown ? (k: U) => void : never
) extends (k: infer I) => void
? I
: never
export type Overwrite = {
[K in keyof O]: K extends keyof O1 ? O1[K] : O[K];
} & {};
type _Merge = IntersectOf;
}>>;
type Key = string | number | symbol;
type AtBasic = K extends keyof O ? O[K] : never;
type AtStrict = O[K & keyof O];
type AtLoose = O extends unknown ? AtStrict : never;
export type At = {
1: AtStrict;
0: AtLoose;
}[strict];
export type ComputeRaw = A extends Function ? A : {
[K in keyof A]: A[K];
} & {};
export type OptionalFlat = {
[K in keyof O]?: O[K];
} & {};
type _Record = {
[P in K]: T;
};
// cause typescript not to expand types and preserve names
type NoExpand = T extends unknown ? T : never;
// this type assumes the passed object is entirely optional
type AtLeast = NoExpand<
O extends unknown
? | (K extends keyof O ? { [P in K]: O[P] } & O : O)
| {[P in keyof O as P extends K ? K : never]-?: O[P]} & O
: never>;
type _Strict = U extends unknown ? U & OptionalFlat<_Record, keyof U>, never>> : never;
export type Strict = ComputeRaw<_Strict>;
/** End Helper Types for "Merge" **/
export type Merge = ComputeRaw<_Merge>>;
/**
A [[Boolean]]
*/
export type Boolean = True | False
// /**
// 1
// */
export type True = 1
/**
0
*/
export type False = 0
export type Not = {
0: 1
1: 0
}[B]
export type Extends = [A1] extends [never]
? 0 // anything `never` is false
: A1 extends A2
? 1
: 0
export type Has = Not<
Extends