├── .dockerignore ├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .prettierrc ├── .vscode └── settings.json ├── Dockerfile ├── LICENSE ├── README.md ├── nest-cli.json ├── nest.sql ├── package.json ├── public └── index.html ├── src ├── app.controller.ts ├── app.module.ts ├── app.service.ts ├── config │ ├── constants.ts │ ├── env │ │ ├── development.ts │ │ ├── production.ts │ │ └── test.ts │ ├── index.ts │ └── log4js.ts ├── core │ ├── code.enum.ts │ ├── resultBean.ts │ └── transform.ts ├── entities │ ├── AdCodelist.ts │ ├── AdCodelistType.ts │ ├── Dept.ts │ ├── Dynamictables.ts │ ├── Form.ts │ ├── Person.ts │ ├── PersonEducation.ts │ ├── PersonResume.ts │ ├── Role.ts │ └── Users.ts ├── events │ ├── events.gateway.ts │ └── events.module.ts ├── filter │ ├── any-exception.filter.ts │ ├── api-exception.filter.ts │ └── http-exception.filter.ts ├── guards │ ├── auth-guards.ts │ ├── customize.ts │ ├── jwt-auth.guard.ts │ └── jwt.strategy.ts ├── interceptor │ └── transform.interceptor.ts ├── main.ts ├── middleware │ └── logger.middleware.ts ├── module │ ├── ad-codelist-type │ │ ├── ad-codelist-type.controller.ts │ │ ├── ad-codelist-type.module.ts │ │ └── ad-codelist-type.service.ts │ ├── ad-codelist │ │ ├── ad-codelist.controller.ts │ │ ├── ad-codelist.module.ts │ │ └── ad-codelist.service.ts │ ├── auth │ │ ├── auth.module.ts │ │ └── auth.service.ts │ ├── base │ │ ├── base.controller.ts │ │ └── base.service.ts │ ├── dept │ │ ├── dept.controller.ts │ │ ├── dept.module.ts │ │ └── dept.service.ts │ ├── dynamictables │ │ ├── dynamictables.controller.ts │ │ ├── dynamictables.module.ts │ │ └── dynamictables.service.ts │ ├── form │ │ ├── form.controller.ts │ │ ├── form.module.ts │ │ └── form.service.ts │ ├── person │ │ ├── education │ │ │ ├── education.controller.ts │ │ │ ├── education.module.ts │ │ │ └── education.service.ts │ │ ├── person.controller.ts │ │ ├── person.module.ts │ │ ├── person.service.ts │ │ └── resume │ │ │ ├── resume.controller.ts │ │ │ ├── resume.module.ts │ │ │ └── resume.service.ts │ ├── role │ │ ├── role.controller.ts │ │ ├── role.module.ts │ │ └── role.service.ts │ ├── upload │ │ ├── upload.controller.ts │ │ ├── upload.module.ts │ │ └── upload.service.ts │ └── users │ │ ├── users.controller.ts │ │ ├── users.module.ts │ │ └── users.service.ts └── utils │ ├── file.ts │ └── log4js.ts ├── test ├── app.e2e-spec.ts └── jest-e2e.json ├── tsconfig.build.json ├── tsconfig.json └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | # Versioning and metadata 2 | .git 3 | .gitignore 4 | .dockerignore 5 | 6 | # Build dependencies 7 | dist 8 | node_modules 9 | coverage 10 | 11 | # Environment (contains sensitive data) 12 | .env 13 | 14 | # Files not required for production 15 | .editorconfig 16 | Dockerfile 17 | README.md 18 | tslint.json 19 | nodemon.json -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // .eslintrc.js 2 | module.exports = { 3 | parser: '@typescript-eslint/parser', 4 | extends: ['plugin:@typescript-eslint/recommended'], 5 | plugins: ['@typescript-eslint'], 6 | rules: { 7 | // 这条规则是为了防止写class interface的member时,分隔符和prettier产生冲突 8 | '@typescript-eslint/ban-ts-comment': 'off', 9 | '@typescript-eslint/no-var-requires': 'off', 10 | '@typescript-eslint/explicit-module-boundary-types': 'off', 11 | '@typescript-eslint/no-explicit-any': 'off', 12 | '@typescript-eslint/no-empty-function': 'off', 13 | '@typescript-eslint/member-delimiter-style': [ 14 | 'error', 15 | { 16 | multiline: { 17 | delimiter: 'none', 18 | requireLast: false 19 | }, 20 | singleline: { 21 | delimiter: 'comma', 22 | requireLast: false 23 | } 24 | } 25 | ] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sql linguist-language=TypeScript 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | /public/affix 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # OS 14 | .DS_Store 15 | 16 | # Tests 17 | /coverage 18 | /.nyc_output 19 | 20 | # IDEs and editors 21 | /.idea 22 | .project 23 | .classpath 24 | .c9/ 25 | *.launch 26 | .settings/ 27 | *.sublime-workspace 28 | 29 | # IDE - VSCode 30 | .vscode/* 31 | !.vscode/settings.json 32 | !.vscode/tasks.json 33 | !.vscode/launch.json 34 | !.vscode/extensions.json 35 | package-lock.json -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": false 4 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": [ 3 | "javascript", 4 | "typescript" 5 | ], 6 | "editor.codeActionsOnSave": { 7 | "source.fixAll.eslint": true 8 | } 9 | } -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16-alpine as builder 2 | 3 | ENV NODE_ENV build 4 | 5 | USER node 6 | WORKDIR /home/node 7 | 8 | COPY package*.json yarn.lock ./ 9 | RUN npm ci 10 | 11 | COPY --chown=node:node . . 12 | RUN npm run build \ 13 | && npm prune --production 14 | 15 | # --- 16 | 17 | FROM node:16-alpine 18 | 19 | ENV NODE_ENV production 20 | 21 | USER node 22 | WORKDIR /home/node 23 | 24 | COPY --from=builder --chown=node:node /home/node/package*.json ./ 25 | COPY --from=builder --chown=node:node /home/node/node_modules/ ./node_modules/ 26 | COPY --from=builder --chown=node:node /home/node/dist/ ./dist/ 27 | 28 | CMD ["npm", "run pm2"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 BoBoooooo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BoBo-NestJS-Server 2 | 3 |

4 | Nest Logo 5 |

6 | 7 | [travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master 8 | [travis-url]: https://travis-ci.org/nestjs/nest 9 | [linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux 10 | [linux-url]: https://travis-ci.org/nestjs/nest 11 | 12 |

A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.

13 |

14 | NPM Version 15 | Package License 16 | NPM Downloads 17 | Travis 18 | Linux 19 | Coverage 20 | Gitter 21 | Backers on Open Collective 22 | Sponsors on Open Collective 23 | 24 | 25 |

26 | 28 | 29 | 30 | 🚀 轻量级 `NestJS-API` 脚手架,欢迎 Star! 31 | 32 | ## Demo 33 | 34 | **域名&服务器已过期...暂时没法访问,抱歉** 35 | 36 | 37 | ## 1. 开始使用 38 | 39 | * git clone https://github.com/BoBoooooo/NestJS-API-Server.git 40 | * yarn 41 | * 配置mysql数据库 42 | * 新建数据库 `nest` 43 | * 导入 `nest.sql` 44 | * 修改以下相关数据库配置 45 | * `package.json->scripts->db` 46 | * `/src/config/env/*` 47 | * yarn start 48 | * yarn db 49 | 50 | ## 2.目录结构 51 | 52 | ```bash 53 | ├── public # public 54 | │   └── index.html # 测试socket.io页面 55 | ├── src # src 56 | │   ├── config # 环境变量等配置文件 57 | │   ├── core # 通用定义文件 58 | │   ├── entities # 数据库ORM Entity 59 | │   ├── events # webSocket 60 | │   ├── filter # 全局异常filter 61 | │   ├── guards # 路由守卫(鉴权) 62 | │   ├── interceptor # interceptor 63 | │   ├── logs # logs 64 | │   ├── middleware # middleware logs 65 | │   ├── module # 各个业务模块,包含base module 66 | │   ├── utils # 工具函数 67 | ├── test # 测试 68 | ```` 69 | 70 | ## 3. 功能 71 | 72 | - 登录、JWT鉴权 73 | 74 | - Socket.IO 75 | 76 | 默认Socket.IO监听8080端口 `/src/events/events.gateway.ts` 77 | 78 | client端实现查看 `/public/index.html` 79 | 80 | - `BaseController` `BaseService` 封装基础CRUD接口 81 | - /xxx/add 82 | - /xxx/update 83 | - /xxx/delete 84 | - /xxx/list 85 | - /xxx/tree 86 | - /xxx/detail 87 | 88 | - list接口支持`高级查询`,具体实现查看`BaseService` 89 | 90 | ```javascript 91 | 示例: 92 | curl - POST /users/list 93 | { 94 | "searchCondition":[{ 95 | "field":"userName", 96 | "operator":"like", 97 | "value":"ce" 98 | }, 99 | { 100 | "field":"userName", 101 | "operator":"like", 102 | "value":"shi" 103 | }], 104 | "pageIndex":1, 105 | "pageSize":1, 106 | "orderCondition":"id desc" 107 | } 108 | === 109 | 最后生成的sql: 110 | select * from users where userName like '%ce%' and userName like '%shi%' order by id desc limit 1,1 111 | 112 | ``` 113 | 114 | - 全局`http异常处理`以及`代码异常`处理 115 | 116 | - log 日志 117 | 118 | - HTTP返回值统一ResultBean封装 119 | 120 | - 文件上传,静态资源服务 121 | 122 | - 一键生成数据库模型 `yarn db` (typeorm-model-generator) 123 | ## 4. 部署 124 | 125 | ``` javascript 126 | // 项目提供了 /src/config/env/dev,prod,test 三种环境变量配置文件 127 | 128 | // main入口监听端口号 129 | await app.listen(process.env.PORT || 3000); 130 | 131 | // 采用不同的npm命令实现多环境部署 132 | cross-env NODE_ENV=production // npm 命令 cross-env指定当前环境 133 | PORT=3000 // 指定监听端口 134 | ``` 135 | 136 | 具体流程 137 | * npm run build 138 | * 拷贝dist文件夹 139 | * 拷贝package.json 140 | * 服务器上执行 npm install 安装所需依赖 (此处大坑,依赖并不会被打包到dist文件夹中) 141 | * npm run start:prod / npm run pm2 142 | -------------------------------------------------------------------------------- /nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": "@nestjs/schematics", 3 | "sourceRoot": "src" 4 | } 5 | -------------------------------------------------------------------------------- /nest.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | 4 | Source Server : localhost 5 | Source Server Type : MySQL 6 | Source Server Version : 80027 7 | Source Host : localhost:3306 8 | Source Schema : nest 9 | 10 | Target Server Type : MySQL 11 | Target Server Version : 80027 12 | File Encoding : 65001 13 | 14 | Date: 26/01/2022 17:14:24 15 | */ 16 | 17 | SET NAMES utf8mb4; 18 | SET FOREIGN_KEY_CHECKS = 0; 19 | 20 | -- ---------------------------- 21 | -- Table structure for ad_codelist 22 | -- ---------------------------- 23 | DROP TABLE IF EXISTS `ad_codelist`; 24 | CREATE TABLE `ad_codelist` ( 25 | `id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID', 26 | `codeValue` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '字典值', 27 | `codeName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '字典值描述', 28 | `codeType` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '字典类型', 29 | `codeOrder` decimal(8,0) DEFAULT NULL COMMENT '排序', 30 | `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '备注', 31 | `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 32 | PRIMARY KEY (`id`) USING BTREE 33 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='字典表'; 34 | 35 | -- ---------------------------- 36 | -- Records of ad_codelist 37 | -- ---------------------------- 38 | BEGIN; 39 | INSERT INTO `ad_codelist` VALUES ('0a6d30ed-8670-4f65-9b92-5a5e24b53049', 'P6', 'P6', 'ac3f1996-bcec-4604-b465-eaf5d1208e79', 2, NULL, '2020-12-20 10:58:01'); 40 | INSERT INTO `ad_codelist` VALUES ('154ba39b-4d6f-4e7e-8197-dcf7be5037da', 'P8', 'P8', 'ac3f1996-bcec-4604-b465-eaf5d1208e79', 4, NULL, '2020-12-20 10:58:23'); 41 | INSERT INTO `ad_codelist` VALUES ('212c3189-e913-4b51-8e0c-6993d9c9f9fa', 'P5', 'P5', 'ac3f1996-bcec-4604-b465-eaf5d1208e79', 1, NULL, '2020-12-20 10:57:55'); 42 | INSERT INTO `ad_codelist` VALUES ('2d09a14f-4032-4a27-9b16-946ab3950689', '8,15', '密度长度', 'f844cb90-1738-4013-b9f2-b0755b63b9dc', 4, 'passwordLength', '2020-12-20 11:46:35'); 43 | INSERT INTO `ad_codelist` VALUES ('2dcba704-af95-44b9-9ad2-72b3d1992b81', '本科', '本科', '962e3a39-928d-4470-a9f3-8efda17f2692', 5, NULL, '2020-12-20 10:57:05'); 44 | INSERT INTO `ad_codelist` VALUES ('3008950a-6246-4fbe-b0d0-538e0cdd0139', '大专及以下', '大专及以下', '962e3a39-928d-4470-a9f3-8efda17f2692', 6, NULL, '2020-12-20 10:56:59'); 45 | INSERT INTO `ad_codelist` VALUES ('58fa976e-b0f1-464d-814b-afe172a6f023', 'P9', 'P9', 'ac3f1996-bcec-4604-b465-eaf5d1208e79', 5, NULL, '2020-12-20 10:58:28'); 46 | INSERT INTO `ad_codelist` VALUES ('59778b04-2ed4-42ef-a3d4-aa330d0e3d54', '7', '密码过期时间(天)', 'f844cb90-1738-4013-b9f2-b0755b63b9dc', 2, 'passwordTime', '2020-09-17 10:31:39'); 47 | INSERT INTO `ad_codelist` VALUES ('63aa209d-264a-4e38-8c4c-e83172e2a5f6', '1', '开发人员模式', 'f844cb90-1738-4013-b9f2-b0755b63b9dc', 5, 'isDev', '2020-12-20 12:25:07'); 48 | INSERT INTO `ad_codelist` VALUES ('7461d8d4-45c5-4fd5-a87f-f04320a487d5', 'P7', 'P7', 'ac3f1996-bcec-4604-b465-eaf5d1208e79', 3, NULL, '2020-12-20 10:58:08'); 49 | INSERT INTO `ad_codelist` VALUES ('7f81d7b5-c6b9-4412-8b00-8c9cf2482357', '20', '客户端超时时间(分钟)', 'f844cb90-1738-4013-b9f2-b0755b63b9dc', 3, 'clientTimeOut', '2020-09-17 10:31:39'); 50 | INSERT INTO `ad_codelist` VALUES ('8062ca78-ce7f-402f-9623-22a185d4ff1b', '博士', '博士', '962e3a39-928d-4470-a9f3-8efda17f2692', 3, NULL, '2020-12-20 10:57:18'); 51 | INSERT INTO `ad_codelist` VALUES ('8d6dcf21-8e7b-4ec6-ae8a-cacb3912870b', 'P10', 'P10', 'ac3f1996-bcec-4604-b465-eaf5d1208e79', 6, NULL, '2020-12-20 10:58:34'); 52 | INSERT INTO `ad_codelist` VALUES ('9233c640-272a-4a4c-92c2-8952ec3dde7e', '研究生', '研究生', '962e3a39-928d-4470-a9f3-8efda17f2692', 4, NULL, '2020-12-20 10:57:13'); 53 | INSERT INTO `ad_codelist` VALUES ('a42d675f-5f5e-4770-8587-53c9c04c9e72', '博士后', '博士后', '962e3a39-928d-4470-a9f3-8efda17f2692', 2, NULL, '2020-12-20 10:57:24'); 54 | INSERT INTO `ad_codelist` VALUES ('b670bc8e-7a73-4fcc-875d-f2c9af01e329', 'BoBo Admin', '系统名称', 'f844cb90-1738-4013-b9f2-b0755b63b9dc', 1, 'systemName', '2020-09-17 10:31:39'); 55 | INSERT INTO `ad_codelist` VALUES ('da332909-bef0-49c3-819e-e189f996bca0', '女', '女', '01eb097e-0d94-44cf-8796-157bba54f0bb', 2, NULL, '2020-09-17 10:31:39'); 56 | INSERT INTO `ad_codelist` VALUES ('dd96514d-87cb-49c7-9191-5021aeabb639', '男', '男', '01eb097e-0d94-44cf-8796-157bba54f0bb', 1, NULL, '2020-09-17 10:31:39'); 57 | COMMIT; 58 | 59 | -- ---------------------------- 60 | -- Table structure for ad_codelist_type 61 | -- ---------------------------- 62 | DROP TABLE IF EXISTS `ad_codelist_type`; 63 | CREATE TABLE `ad_codelist_type` ( 64 | `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID', 65 | `typeName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '字典类型名称', 66 | `order` decimal(8,0) DEFAULT NULL COMMENT '排序', 67 | `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '备注', 68 | `parentId` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '父级ID', 69 | `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 70 | PRIMARY KEY (`id`) USING BTREE 71 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='字典类型表'; 72 | 73 | -- ---------------------------- 74 | -- Records of ad_codelist_type 75 | -- ---------------------------- 76 | BEGIN; 77 | INSERT INTO `ad_codelist_type` VALUES ('01eb097e-0d94-44cf-8796-157bba54f0bb', '性别', 1, '', 'bedac4aa-41c8-4fcd-911d-d79b3b5a2392', '2020-09-17 10:31:39'); 78 | INSERT INTO `ad_codelist_type` VALUES ('962e3a39-928d-4470-a9f3-8efda17f2692', '文化程度', 0, '', 'bedac4aa-41c8-4fcd-911d-d79b3b5a2392', '2020-12-20 10:56:28'); 79 | INSERT INTO `ad_codelist_type` VALUES ('ac3f1996-bcec-4604-b465-eaf5d1208e79', '职级', 0, '', 'bedac4aa-41c8-4fcd-911d-d79b3b5a2392', '2020-12-20 10:57:39'); 80 | INSERT INTO `ad_codelist_type` VALUES ('bedac4aa-41c8-4fcd-911d-d79b3b5a2392', '常用', 0, '常用', 'fe980574-2552-4754-88c8-366eb5a22861', '2021-01-12 17:09:06'); 81 | INSERT INTO `ad_codelist_type` VALUES ('f844cb90-1738-4013-b9f2-b0755b63b9dc', '系统配置', 2, '系统相关', 'fe980574-2552-4754-88c8-366eb5a22861', '2021-01-12 17:09:16'); 82 | INSERT INTO `ad_codelist_type` VALUES ('fe980574-2552-4754-88c8-366eb5a22861', '数据字典', 1, '', '0', '2020-09-17 10:31:39'); 83 | COMMIT; 84 | 85 | -- ---------------------------- 86 | -- Table structure for dept 87 | -- ---------------------------- 88 | DROP TABLE IF EXISTS `dept`; 89 | CREATE TABLE `dept` ( 90 | `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, 91 | `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '部门名称', 92 | `rank` int DEFAULT NULL COMMENT '排序码', 93 | `parentId` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '上级ID', 94 | `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 95 | PRIMARY KEY (`id`) USING BTREE, 96 | UNIQUE KEY `index_id` (`id`) USING BTREE 97 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 98 | 99 | -- ---------------------------- 100 | -- Records of dept 101 | -- ---------------------------- 102 | BEGIN; 103 | INSERT INTO `dept` VALUES ('2f8447de-5732-4fa4-8286-9a71b41dd1e7', '总部', 1, '0', '2020-09-18 15:17:45'); 104 | INSERT INTO `dept` VALUES ('b987afc3-6969-4b87-85a4-f8e2029e4bee', '开发部', 1, '2f8447de-5732-4fa4-8286-9a71b41dd1e7', '2020-09-17 10:31:39'); 105 | COMMIT; 106 | 107 | -- ---------------------------- 108 | -- Table structure for dynamictables 109 | -- ---------------------------- 110 | DROP TABLE IF EXISTS `dynamictables`; 111 | CREATE TABLE `dynamictables` ( 112 | `id` char(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, 113 | `tableName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '表名', 114 | `formJson` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '数据', 115 | `position` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '使用位置', 116 | `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 117 | PRIMARY KEY (`id`) USING BTREE 118 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='表格设计'; 119 | 120 | -- ---------------------------- 121 | -- Records of dynamictables 122 | -- ---------------------------- 123 | BEGIN; 124 | INSERT INTO `dynamictables` VALUES ('054cfb12-7db2-400b-9917-27d3105dbb09', 'dept', '{\"columns\":[{\"prop\":\"name\",\"label\":\"部门名称\",\"minWidth\":\"200\",\"sortable\":\"false\",\"searchable\":false,\"align\":\"left\",\"headerAlign\":\"center\"},{\"prop\":\"\",\"label\":\"操作\",\"minWidth\":\"280\",\"align\":\"center\",\"headerAlign\":\"center\",\"slotName\":\"actionColumn\",\"fixed\":\"right\",\"sortable\":\"false\",\"searchable\":false}]}', 'Dept.vue/部门设置', '2020-09-17 10:32:10'); 125 | INSERT INTO `dynamictables` VALUES ('3be21467-5c60-42eb-81ae-2e7bb81b6d64', 'person_resume', '{\"columns\":[{\"prop\":\"time\",\"label\":\"起止时间\",\"minWidth\":140,\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true},{\"prop\":\"workunit\",\"label\":\"工作单位\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"minWidth\":140,\"sortable\":\"custom\",\"searchable\":true},{\"prop\":\"workduty\",\"label\":\"职务\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"minWidth\":140,\"sortable\":\"custom\",\"searchable\":true},{\"prop\":\"\",\"label\":\"操作\",\"minWidth\":180,\"align\":\"center\",\"headerAlign\":\"center\",\"slotName\":\"actionColumn\",\"fixed\":\"right\",\"sortable\":\"false\",\"searchable\":false}]}', '员工履历', '2020-12-20 10:37:25'); 126 | INSERT INTO `dynamictables` VALUES ('58da681b-af8f-4733-b7b0-9c037e9d0d8f', 'users', '{\"columns\":[{\"prop\":\"realName\",\"label\":\"姓名\",\"minWidth\":\"100\",\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true,\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true},{\"prop\":\"userName\",\"label\":\"登录名\",\"minWidth\":\"100\",\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true,\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true},{\"prop\":\"roleName\",\"label\":\"角色\",\"minWidth\":\"100\",\"sortable\":\"custom\",\"slotName\":\"\",\"option\":{\"width\":\"\",\"placeholder\":\"\",\"remote\":\"custom\",\"remoteFunc\":\"funcGetRole\",\"props\":{\"label\":\"label\",\"value\":\"value\"},\"type\":\"select\",\"selectBy\":\"label\"},\"searchable\":true,\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true},{\"prop\":\"deptName\",\"label\":\"部门\",\"minWidth\":\"100\",\"sortable\":\"custom\",\"searchable\":true,\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true},{\"prop\":\"photo\",\"label\":\"头像\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"minWidth\":140,\"sortable\":\"custom\",\"searchable\":false,\"slotName\":\"columnFormatter\"},{\"prop\":\"\",\"label\":\"操作\",\"minWidth\":\"270\",\"slotName\":\"actionColumn\",\"fixed\":\"right\",\"sortable\":\"false\",\"searchable\":false,\"align\":\"center\",\"headerAlign\":\"center\"}],\"name\":\"users\",\"position\":\"Users.vue系统设置/角色管理\"}', 'Users.vue系统设置/角色管理', '2021-01-08 09:16:22'); 127 | INSERT INTO `dynamictables` VALUES ('72269942-3b4a-4000-b722-12c70febbab2', 'params', '{\"columns\":[{\"prop\":\"codeName\",\"label\":\"参数名称\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"minWidth\":140,\"sortable\":\"custom\",\"searchable\":true},{\"prop\":\"remark\",\"label\":\"参数键名\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"minWidth\":140,\"sortable\":\"custom\",\"searchable\":true},{\"prop\":\"codeValue\",\"label\":\"参数键值\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"minWidth\":140,\"sortable\":\"custom\",\"searchable\":true},{\"prop\":\"\",\"label\":\"操作\",\"minWidth\":180,\"align\":\"center\",\"headerAlign\":\"center\",\"slotName\":\"actionColumn\",\"fixed\":\"right\",\"sortable\":\"false\",\"searchable\":false}]}', '参数设置', '2020-09-17 10:15:02'); 128 | INSERT INTO `dynamictables` VALUES ('e2d577ac-6900-432f-a45c-ec086f668825', 'person', '{\"columns\":[{\"prop\":\"jobno\",\"label\":\"工号\",\"minWidth\":\"100\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"jobno\",\"searchable\":true},{\"prop\":\"personname\",\"label\":\"姓名\",\"minWidth\":\"70\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"personname\",\"searchable\":true},{\"prop\":\"jobtime\",\"label\":\"入职时间\",\"minWidth\":140,\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true},{\"prop\":\"deptname\",\"label\":\"所在部门\",\"minWidth\":\"100\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true},{\"prop\":\"post\",\"label\":\"岗位\",\"minWidth\":\"100\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true},{\"prop\":\"level\",\"label\":\"职级\",\"minWidth\":\"100\",\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true,\"option\":{\"remote\":\"dict\",\"remoteFunc\":\"\",\"type\":\"select\",\"props\":{\"value\":\"\",\"label\":\"\"},\"dictType\":\"ac3f1996-bcec-4604-b465-eaf5d1208e79\"}},{\"prop\":\"mobile\",\"label\":\"联系方式\",\"minWidth\":140,\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true},{\"prop\":\"\",\"label\":\"操作\",\"minWidth\":\"240\",\"align\":\"center\",\"headerAlign\":\"center\",\"slotName\":\"actionColumn\",\"fixed\":\"right\",\"sortable\":\"false\",\"searchable\":false}],\"name\":\"person\",\"position\":\"员工管理\"}', '员工管理', '2021-01-12 17:02:22'); 129 | INSERT INTO `dynamictables` VALUES ('eb9388de-aa0c-4027-8653-b4e0c9a9cb1d', 'ad_codelist', '{\"columns\":[{\"prop\":\"codeName\",\"label\":\"字典名\",\"minWidth\":140,\"align\":\"left\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true},{\"prop\":\"codeValue\",\"label\":\"字典值\",\"minWidth\":140,\"align\":\"left\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true},{\"prop\":\"typeName\",\"label\":\"所属分类\",\"minWidth\":140,\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true,\"option\":{\"width\":\"\",\"placeholder\":\"\",\"remote\":\"custom\",\"remoteFunc\":\"getDictType\",\"props\":{\"value\":\"value\",\"label\":\"label\"},\"options\":[{\"value\":\"下拉框1\"},{\"value\":\"下拉框2\"},{\"value\":\"下拉框3\"}],\"type\":\"select\",\"selectBy\":\"label\"}},{\"prop\":\"codeOrder\",\"label\":\"字典排序\",\"minWidth\":140,\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true},{\"prop\":\"remark\",\"label\":\"备注\",\"minWidth\":140,\"align\":\"center\",\"headerAlign\":\"center\",\"showOverflowTooltip\":true,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true},{\"prop\":\"\",\"label\":\"操作\",\"minWidth\":180,\"align\":\"center\",\"headerAlign\":\"center\",\"slotName\":\"actionColumn\",\"fixed\":\"right\",\"sortable\":\"false\",\"searchable\":false}]}', '字典管理', '2020-12-20 11:05:38'); 130 | INSERT INTO `dynamictables` VALUES ('f2ad95ae-61d7-4bc3-94d6-dc00e867fdbe', 'dynamictables', '{\"columns\":[{\"prop\":\"tableName\",\"label\":\"表名\",\"minWidth\":140,\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true,\"align\":\"left\",\"headerAlign\":\"center\"},{\"prop\":\"position\",\"label\":\"使用位置\",\"minWidth\":\"300\",\"sortable\":\"custom\",\"slotName\":\"\",\"searchable\":true,\"align\":\"left\",\"headerAlign\":\"center\"},{\"prop\":\"timestamp\",\"label\":\"更新时间\",\"minWidth\":140,\"sortable\":\"custom\",\"searchable\":true,\"align\":\"center\",\"headerAlign\":\"center\"},{\"prop\":\"\",\"label\":\"操作\",\"minWidth\":\"150\",\"slotName\":\"actionColumn\",\"fixed\":\"right\",\"sortable\":\"false\",\"searchable\":false,\"align\":\"center\",\"headerAlign\":\"center\",\"width\":\"200\"}]}', 'TableDesigner.vue开发人员工具/表格设计', '2020-09-17 10:15:02'); 131 | INSERT INTO `dynamictables` VALUES ('fb8a5d7c-2fda-4936-9da0-dc09354adfdc', 'form', '{\"columns\":[{\"prop\":\"tableName\",\"label\":\"表名\",\"minWidth\":140,\"sortable\":\"custom\",\"searchable\":true,\"align\":\"left\",\"headerAlign\":\"center\"},{\"prop\":\"position\",\"label\":\"使用位置\",\"minWidth\":\"300\",\"sortable\":\"custom\",\"searchable\":true,\"align\":\"left\",\"headerAlign\":\"center\"},{\"prop\":\"timestamp\",\"label\":\"更新时间\",\"minWidth\":140,\"sortable\":\"custom\",\"searchable\":true,\"align\":\"center\",\"headerAlign\":\"center\"},{\"prop\":\"\",\"label\":\"操作\",\"minWidth\":\"150\",\"slotName\":\"actionColumn\",\"fixed\":\"right\",\"sortable\":\"false\",\"searchable\":false,\"align\":\"center\",\"headerAlign\":\"center\"}]}', 'FormDesigner.vue开发人员工具/表单设计', '2020-09-18 10:14:02'); 132 | INSERT INTO `dynamictables` VALUES ('fc442e2b-a7f9-4fab-8d59-2803ae2a9215', 'role', '{\"columns\":[{\"prop\":\"roleName\",\"label\":\"角色\",\"minWidth\":140,\"sortable\":\"custom\",\"slotName\":\"\",\"align\":\"left\",\"headerAlign\":\"center\",\"searchable\":true},{\"prop\":\"roleAuthNameDict\",\"label\":\"菜单\",\"minWidth\":140,\"sortable\":\"custom\",\"slotName\":\"\",\"align\":\"left\",\"headerAlign\":\"center\",\"searchable\":true,\"showOverflowTooltip\":true},{\"prop\":\"rank\",\"label\":\"排序\",\"minWidth\":140,\"sortable\":\"custom\",\"slotName\":\"\",\"align\":\"center\",\"headerAlign\":\"center\",\"searchable\":true},{\"prop\":\"\",\"label\":\"操作\",\"minWidth\":180,\"slotName\":\"actionColumn\",\"fixed\":\"right\",\"sortable\":\"false\",\"searchable\":false,\"headerAlign\":\"center\",\"align\":\"center\"}]}', 'Role.vue系统设置/角色管理', '2020-09-18 10:14:50'); 133 | COMMIT; 134 | 135 | -- ---------------------------- 136 | -- Table structure for form 137 | -- ---------------------------- 138 | DROP TABLE IF EXISTS `form`; 139 | CREATE TABLE `form` ( 140 | `id` char(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, 141 | `tableName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '表名', 142 | `formJson` longtext CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '数据', 143 | `position` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '使用位置', 144 | `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 145 | PRIMARY KEY (`id`) USING BTREE 146 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='表单设计'; 147 | 148 | -- ---------------------------- 149 | -- Records of form 150 | -- ---------------------------- 151 | BEGIN; 152 | INSERT INTO `form` VALUES ('08d0b5e4-92e4-431b-9b48-6189881335ed', 'role', '{\"list\":[{\"columns\":[{\"list\":[{\"name\":\"角色\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1543672671000_92966\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"roleName\",\"rules\":[{\"type\":\"string\",\"message\":\"角色格式不正确\"}],\"type\":\"input\",\"key\":\"1543672671000_92966\"}],\"span\":12},{\"list\":[{\"name\":\"排序\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1543672693000_86312\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"rank\",\"rules\":[],\"type\":\"input\",\"key\":\"1543672693000_86312\"}],\"span\":12}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1543672665000_69434\",\"gutter\":0,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"1543672665000_69434\",\"rules\":[],\"type\":\"grid\",\"key\":\"1543672665000_69434\"},{\"type\":\"grid\",\"name\":\"栅格布局\",\"icon\":\"th\",\"columns\":[{\"span\":24,\"list\":[{\"type\":\"input\",\"name\":\"首页\",\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_1554347848000_34718\"},\"key\":\"1554347848000_34718\",\"model\":\"homePageDict\",\"rules\":[{\"type\":\"string\",\"message\":\"单行文本格式不正确\"}]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1554347841000_92183\"},\"key\":\"1554347841000_92183\",\"model\":\"1554347841000_92183\",\"rules\":[]},{\"columns\":[{\"list\":[{\"name\":\"对应菜单\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1543672717000_46620\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"roleAuthNameDict\",\"rules\":[{\"type\":\"string\",\"message\":\"对应菜单格式不正确\"}],\"type\":\"input\",\"key\":\"1543672717000_46620\"}],\"span\":24}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1543672710000_2784\",\"gutter\":0,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"1543672710000_2784\",\"rules\":[],\"type\":\"grid\",\"key\":\"1543672710000_2784\"}],\"config\":{\"size\":\"small\",\"labelPosition\":\"right\",\"labelWidth\":0,\"name\":\"role\"}}', 'Role.vue/角色设置', '2020-12-20 12:39:06'); 153 | INSERT INTO `form` VALUES ('139d4ebc-d6a1-40bb-b063-2086c31e743d', 'ad_codelist_type', '{\"list\":[{\"columns\":[{\"list\":[{\"name\":\"字典类型名称\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1542852872000_82944\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"codeValue\",\"rules\":[{\"type\":\"string\",\"message\":\"字典类型名称格式不正确\"}],\"type\":\"input\",\"key\":\"1542852872000_82944\"}],\"span\":12},{\"list\":[{\"name\":\"字典类型描述\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1542852908000_20406\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"codeName\",\"rules\":[],\"type\":\"input\",\"key\":\"1542852908000_20406\"}],\"span\":12}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1542852751000_26540\",\"gutter\":10,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"1542852751000_26540\",\"rules\":[],\"type\":\"grid\",\"key\":\"1542852751000_26540\"},{\"columns\":[{\"list\":[{\"name\":\"排序\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1542852959000_72602\",\"defaultValue\":\"\",\"dataType\":\"number\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"codeOrder\",\"rules\":[{\"type\":\"number\",\"message\":\"排序格式不正确\"}],\"type\":\"input\",\"key\":\"1542852959000_72602\"}],\"span\":12},{\"list\":[{\"name\":\"备注\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1542852978000_87249\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"remark\",\"rules\":[{\"type\":\"string\",\"message\":\"备注格式不正确\"}],\"type\":\"input\",\"key\":\"1542852978000_87249\"}],\"span\":12}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1542852934000_45834\",\"gutter\":10,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"1542852934000_45834\",\"rules\":[],\"type\":\"grid\",\"key\":\"1542852934000_45834\"}],\"config\":{\"size\":\"small\",\"labelPosition\":\"top\",\"labelWidth\":0,\"name\":\"ad_codelist_type\"}}', 'DictType.vue开发人员工具/字典类型管理/字典类型列表', '2020-12-20 12:39:08'); 154 | INSERT INTO `form` VALUES ('22727b7c-7d23-4f3f-ad5b-526eca8f8779', 'users', '{\"list\":[{\"columns\":[{\"list\":[{\"name\":\"姓名\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1543692259000_97262\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":true},\"model\":\"realName\",\"rules\":[{\"type\":\"string\",\"message\":\"姓名格式不正确\"},{\"required\":true,\"message\":\"姓名必须填写\"}],\"type\":\"input\",\"key\":\"1543692259000_97262\"}],\"span\":12},{\"list\":[{\"type\":\"input\",\"name\":\"登录名\",\"labelWidth\":\"\",\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":true,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_1599720592000_96541\"},\"key\":\"1599720592000_96541\",\"model\":\"userName\",\"rules\":[{\"type\":\"string\",\"message\":\"单行文本格式不正确\"},{\"required\":true,\"message\":\"登录名必须填写\"}]}],\"span\":12}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1543692232000_18760\",\"gutter\":0,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"1543692232000_18760\",\"rules\":[],\"type\":\"grid\",\"key\":\"1543692232000_18760\"},{\"columns\":[{\"list\":[{\"name\":\"密码\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1543692382000_41790\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":true,\"message\":\"\"},\"model\":\"password\",\"rules\":[{\"type\":\"string\",\"message\":\"联系方式格式不正确\"},{\"required\":true,\"message\":\"密码必须填写\"}],\"type\":\"input\",\"key\":\"1543692382000_41790\"}],\"span\":24}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1543692369000_62178\",\"gutter\":0,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"1543692369000_62178\",\"rules\":[],\"type\":\"grid\",\"key\":\"1543692369000_62178\"},{\"type\":\"grid\",\"name\":\"栅格布局(1列)\",\"icon\":\"th\",\"columns\":[{\"span\":12,\"list\":[{\"type\":\"treeselect\",\"name\":\"部门\",\"icon\":\"tree\",\"options\":{\"remoteFunc\":\"funcGetDeptTree\",\"placeholder\":\"\",\"width\":\"\",\"maxHeight\":\"100\",\"multiple\":false,\"remote\":\"custom\",\"props\":{\"value\":\"name\",\"label\":\"id\",\"children\":\"children\"},\"clearable\":true,\"searchable\":true,\"noChildrenText\":\"暂无数据\",\"noOptionsText\":\"暂无数据\",\"noResultsText\":\"暂无数据\",\"searchNested\":true,\"required\":true,\"showValueLabelSlot\":false,\"disabled\":false,\"showCount\":false,\"disableBranchNodes\":false,\"remoteOptions\":[],\"tips\":\"选择所属部门\",\"defaultValue\":\"\"},\"key\":\"deptId\",\"model\":\"deptId\",\"rules\":[{\"required\":true,\"message\":\"部门必须填写\"}]}]},{\"span\":12,\"list\":[{\"type\":\"select\",\"name\":\"角色\",\"labelWidth\":\"\",\"hidden\":false,\"icon\":\"regular/caret-square-down\",\"options\":{\"defaultValue\":\"\",\"multiple\":false,\"disabled\":false,\"clearable\":false,\"placeholder\":\"\",\"required\":true,\"showLabel\":false,\"allowCreate\":false,\"width\":\"\",\"options\":[{\"value\":\"下拉框1\"},{\"value\":\"下拉框2\"},{\"value\":\"下拉框3\"}],\"remote\":\"custom\",\"remoteOptions\":[],\"props\":{\"value\":\"value\",\"label\":\"label\"},\"remoteFunc\":\"funcGetRole\"},\"key\":\"1599722385000_17600\",\"model\":\"roleId\",\"rules\":[{\"required\":true,\"message\":\"角色必须填写\"}]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1599722356000_92731\"},\"key\":\"1599722356000_92731\",\"model\":\"1599722356000_92731\",\"rules\":[]},{\"columns\":[{\"span\":12,\"list\":[{\"name\":\"排序\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1543692390000_91729\",\"defaultValue\":\"\",\"dataType\":\"number\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"rank\",\"rules\":[{\"type\":\"number\",\"message\":\"排序格式不正确\"}],\"type\":\"input\",\"key\":\"rank\"}]}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1543692434000_13772\",\"gutter\":0,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"1543692434000_13772\",\"rules\":[],\"type\":\"grid\",\"key\":\"1543692434000_13772\"}],\"config\":{\"size\":\"small\",\"labelPosition\":\"right\",\"labelWidth\":0,\"name\":\"users\"}}', 'Users.vue系统设置/用户管理', '2021-01-07 17:14:54'); 155 | INSERT INTO `form` VALUES ('2875cabf-19ca-46ee-abce-026dccbd9d6f', 'person_resume', '{\"list\":[{\"type\":\"grid\",\"name\":\"栅格布局\",\"icon\":\"th\",\"columns\":[{\"span\":24,\"list\":[{\"type\":\"date\",\"name\":\"起止时间\",\"labelWidth\":\"\",\"hidden\":false,\"icon\":\"regular/calendar-alt\",\"options\":{\"defaultValue\":false,\"readonly\":false,\"disabled\":false,\"editable\":true,\"clearable\":true,\"placeholder\":\"\",\"startPlaceholder\":\"\",\"endPlaceholder\":\"\",\"type\":\"monthrange\",\"format\":\"yyyy-MM\",\"timestamp\":false,\"required\":false,\"width\":\"100%\",\"remoteFunc\":\"func_1608434790000_9491\"},\"key\":\"1608434790000_9491\",\"model\":\"time\",\"rules\":[]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1575516929000_36539\"},\"key\":\"1575516931000_0.7269407990573393\",\"model\":\"1575516929000_36539\",\"rules\":[]},{\"type\":\"grid\",\"name\":\"栅格布局\",\"icon\":\"th\",\"columns\":[{\"span\":12,\"list\":[{\"type\":\"input\",\"name\":\"工作单位\",\"labelWidth\":0,\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_1575516931000_89639\"},\"key\":\"workunit\",\"model\":\"workunit\",\"rules\":[]}]},{\"span\":12,\"list\":[{\"type\":\"input\",\"name\":\"职务\",\"labelWidth\":0,\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_1575516931000_89639\"},\"key\":\"workduty\",\"model\":\"workduty\",\"rules\":[]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1575516929000_36539\"},\"key\":\"1575516931000_0.0967080797051183\",\"model\":\"1575516929000_36539\",\"rules\":[]},{\"type\":\"grid\",\"name\":\"栅格布局(1列)\",\"icon\":\"th\",\"columns\":[{\"span\":24,\"list\":[{\"type\":\"richtext\",\"name\":\"备注\",\"icon\":\"text-width\",\"hidden\":false,\"options\":{\"defaultValue\":\"\",\"readonly\":false,\"remoteFunc\":\"func_1608431672000_50519\"},\"key\":\"1608431672000_50519\",\"model\":\"remark\",\"rules\":[]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1608431652000_51550\"},\"key\":\"1608431652000_51550\",\"model\":\"1608431652000_51550\",\"rules\":[]}],\"config\":{\"labelWidth\":140,\"labelPosition\":\"right\",\"size\":\"small\",\"isTableClass\":true}}', '员工履历', '2020-12-20 11:29:37'); 156 | INSERT INTO `form` VALUES ('45a0da67-2713-42cb-bdb4-4e5cdbb8d436', 'ad_codelist', '{\"list\":[{\"columns\":[{\"list\":[{\"name\":\"字典值\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1542782929000_93584\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"codeValue\",\"rules\":[{\"type\":\"string\",\"message\":\"字典值格式不正确\"}],\"type\":\"input\",\"key\":\"1542782929000_93584\"}],\"span\":12},{\"list\":[{\"name\":\"字典名\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1542782931000_42300\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"codeName\",\"rules\":[{\"type\":\"string\",\"message\":\"字典名格式不正确\"}],\"type\":\"input\",\"key\":\"1542782931000_42300\"}],\"span\":12}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1542782926000_16479\",\"gutter\":0,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"1542782926000_16479\",\"rules\":[],\"type\":\"grid\",\"key\":\"1542782926000_16479\"},{\"type\":\"grid\",\"name\":\"栅格布局(1列)\",\"icon\":\"th\",\"columns\":[{\"span\":24,\"list\":[{\"type\":\"select\",\"name\":\"所属分类\",\"labelWidth\":0,\"hidden\":false,\"icon\":\"regular/caret-square-down\",\"options\":{\"defaultValue\":\"\",\"multiple\":false,\"disabled\":false,\"clearable\":false,\"placeholder\":\"\",\"required\":false,\"showLabel\":false,\"allowCreate\":false,\"width\":\"\",\"options\":[{\"value\":\"下拉框1\"},{\"value\":\"下拉框2\"},{\"value\":\"下拉框3\"}],\"remote\":\"custom\",\"remoteOptions\":[],\"props\":{\"value\":\"value\",\"label\":\"label\"},\"remoteFunc\":\"getDictType\"},\"key\":\"1576489740000_96446\",\"model\":\"codeType\",\"rules\":[]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1576489735000_66792\"},\"key\":\"1576489735000_66792\",\"model\":\"1576489735000_66792\",\"rules\":[]},{\"columns\":[{\"list\":[{\"name\":\"字典排序\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1542783014000_32619\",\"defaultValue\":\"\",\"dataType\":\"number\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"codeOrder\",\"rules\":[{\"type\":\"number\",\"message\":\"字典排序格式不正确\"}],\"type\":\"input\",\"key\":\"codeorder\"}],\"span\":12},{\"list\":[{\"name\":\"备注\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1542783045000_37663\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"remark\",\"rules\":[{\"type\":\"string\",\"message\":\"备注格式不正确\"}],\"type\":\"input\",\"key\":\"remark\"}],\"span\":12}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1542782963000_76757\",\"gutter\":0,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"1542782963000_76757\",\"rules\":[],\"type\":\"grid\",\"key\":\"1542782963000_76757\"}],\"config\":{\"size\":\"small\",\"labelPosition\":\"right\",\"labelWidth\":0,\"name\":\"ad_codelist\"}}', 'Dict.vue开发人员工具/字典管理', '2020-12-20 12:39:11'); 157 | INSERT INTO `form` VALUES ('6ce2aa72-c969-43cf-8370-c669e50b300b', 'dept', '{\"list\":[{\"columns\":[{\"list\":[{\"name\":\"部门名称\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1542344382000_98751\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":true},\"model\":\"name\",\"rules\":[{\"type\":\"string\",\"message\":\"部门名称格式不正确\"},{\"required\":true,\"message\":\"部门名称必须填写\"}],\"type\":\"input\",\"key\":\"1542344382000_98751\"}],\"span\":12},{\"span\":12,\"list\":[{\"type\":\"input\",\"name\":\"部门排序\",\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"number\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_rank\"},\"key\":\"rank\",\"model\":\"rank\",\"rules\":[{\"type\":\"number\",\"message\":\"部门排序格式不正确\"}]}]}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1542344310000_82263\",\"gutter\":0,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"grid_1542344310000_82263\",\"rules\":[],\"type\":\"grid\",\"key\":\"1542344310000_82263\"}],\"config\":{\"size\":\"small\",\"labelPosition\":\"right\",\"labelWidth\":0,\"name\":\"dept\"}}', 'Dept.vue/系统设置/部门设置', '2020-12-20 12:39:12'); 158 | INSERT INTO `form` VALUES ('786506c7-7d3a-4bec-a9fb-f374b9eecbb7', 'dynamictables', '{\"list\":[{\"columns\":[{\"list\":[{\"name\":\"表名\",\"icon\":\"regular/caret-square-down\",\"options\":{\"remoteFunc\":\"getTablesOfDB\",\"clearable\":false,\"defaultValue\":\"\",\"remoteOptions\":[],\"multiple\":false,\"remote\":\"custom\",\"required\":false,\"showLabel\":false,\"props\":{\"label\":\"label\",\"value\":\"value\"},\"allowCreate\":true,\"width\":\"100%\",\"options\":[{\"value\":\"下拉框1\"},{\"value\":\"下拉框2\"},{\"value\":\"下拉框3\"}],\"disabled\":false,\"placeholder\":\"\"},\"model\":\"tableName\",\"rules\":[],\"type\":\"select\",\"key\":\"1544270970000_6013\",\"labelWidth\":\"40\"}],\"span\":12},{\"list\":[{\"name\":\"使用位置\",\"icon\":\"regular/keyboard\",\"options\":{\"remoteFunc\":\"func_1544159524000_20194\",\"defaultValue\":\"\",\"dataType\":\"string\",\"width\":\"100%\",\"pattern\":\"\",\"placeholder\":\"\",\"required\":false},\"model\":\"position\",\"rules\":[{\"type\":\"string\",\"message\":\"使用位置格式不正确\"}],\"type\":\"input\",\"key\":\"1544159524000_20194\"}],\"span\":12}],\"name\":\"栅格布局\",\"icon\":\"th\",\"options\":{\"remoteFunc\":\"func_1544159335000_25819\",\"gutter\":10,\"justify\":\"start\",\"align\":\"top\"},\"model\":\"1544159335000_25819\",\"rules\":[],\"type\":\"grid\",\"key\":\"1544159335000_25819\"}],\"config\":{\"size\":\"small\",\"labelPosition\":\"right\",\"labelWidth\":80,\"name\":\"dynamictables\"}}', 'TableDesigner.vue开发人员工具/表格设计', '2020-12-20 12:39:14'); 159 | INSERT INTO `form` VALUES ('bd70c78e-7678-4c06-a466-6760f29f73ad', 'person', '{\"list\":[{\"type\":\"grid\",\"name\":\"栅格布局\",\"icon\":\"th\",\"columns\":[{\"span\":12,\"list\":[{\"type\":\"input\",\"name\":\"工号\",\"labelWidth\":0,\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"请输入工号\",\"remoteFunc\":\"func_1575516931000_89639\"},\"key\":\"jobno\",\"model\":\"jobno\",\"rules\":[{\"type\":\"string\",\"message\":\"工号格式不正确\"}]}]},{\"span\":12,\"list\":[{\"type\":\"input\",\"name\":\"姓名\",\"labelWidth\":0,\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_1575516931000_89639\"},\"key\":\"personname\",\"model\":\"personname\",\"rules\":[{\"type\":\"string\",\"message\":\"姓名1格式不正确\"}]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1575516929000_36539\"},\"key\":\"1575516931000_0.0578278502302394\",\"model\":\"1575516929000_36539\",\"rules\":[]},{\"type\":\"grid\",\"name\":\"栅格布局\",\"icon\":\"th\",\"columns\":[{\"span\":12,\"list\":[{\"type\":\"radio\",\"name\":\"性别\",\"icon\":\"regular/dot-circle\",\"labelWidth\":\"\",\"hidden\":false,\"options\":{\"inline\":true,\"defaultValue\":\"\",\"showLabel\":false,\"options\":[{\"value\":\"男\",\"label\":\"选项1\"},{\"value\":\"女\",\"label\":\"选项2\"}],\"required\":false,\"disabled\":false,\"width\":\"\",\"remote\":false,\"remoteOptions\":[],\"props\":{\"value\":\"value\",\"label\":\"label\"},\"remoteFunc\":\"func_1608432399000_10952\"},\"key\":\"1608432399000_10952\",\"model\":\"sex\",\"rules\":[{\"type\":\"string\",\"message\":\"性别格式不正确\"}]}]},{\"span\":12,\"list\":[{\"type\":\"select\",\"name\":\"文化程度\",\"labelWidth\":\"\",\"hidden\":false,\"icon\":\"regular/caret-square-down\",\"options\":{\"defaultValue\":\"\",\"multiple\":false,\"disabled\":false,\"clearable\":false,\"placeholder\":\"\",\"required\":false,\"showLabel\":false,\"allowCreate\":false,\"width\":\"100%\",\"options\":[{\"value\":\"下拉框1\"},{\"value\":\"下拉框2\"},{\"value\":\"下拉框3\"}],\"remote\":\"dict\",\"remoteOptions\":[{\"value\":\"本科\",\"label\":\"本科\"},{\"value\":\"大专及以下\",\"label\":\"大专及以下\"},{\"value\":\"博士\",\"label\":\"博士\"},{\"value\":\"研究生\",\"label\":\"研究生\"},{\"value\":\"博士后\",\"label\":\"博士后\"}],\"props\":{\"value\":\"value\",\"label\":\"label\"},\"remoteFunc\":\"func_1608433134000_41081\",\"dictType\":\"962e3a39-928d-4470-a9f3-8efda17f2692\"},\"key\":\"1608433134000_41081\",\"model\":\"education\",\"rules\":[]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1575516929000_36539\"},\"key\":\"1575516931000_0.4979627182416866\",\"model\":\"1575516929000_36539\",\"rules\":[]},{\"type\":\"grid\",\"name\":\"栅格布局\",\"icon\":\"th\",\"columns\":[{\"span\":12,\"list\":[{\"type\":\"input\",\"name\":\"所在部门\",\"labelWidth\":0,\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_1575516931000_89639\"},\"key\":\"deptname\",\"model\":\"deptname\",\"rules\":[]}]},{\"span\":12,\"list\":[{\"type\":\"input\",\"name\":\"岗位\",\"labelWidth\":0,\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_1575516931000_89639\"},\"key\":\"post\",\"model\":\"post\",\"rules\":[{\"type\":\"string\",\"message\":\"岗位格式不正确\"}]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1575516929000_36539\"},\"key\":\"1575516931000_0.6063054944523363\",\"model\":\"1575516929000_36539\",\"rules\":[]},{\"type\":\"grid\",\"name\":\"栅格布局\",\"icon\":\"th\",\"columns\":[{\"span\":12,\"list\":[{\"type\":\"select\",\"name\":\"职级\",\"labelWidth\":\"\",\"hidden\":false,\"icon\":\"regular/caret-square-down\",\"options\":{\"defaultValue\":\"\",\"multiple\":false,\"disabled\":false,\"clearable\":false,\"placeholder\":\"\",\"required\":false,\"showLabel\":false,\"allowCreate\":false,\"width\":\"100%\",\"options\":[{\"value\":\"下拉框1\"},{\"value\":\"下拉框2\"},{\"value\":\"下拉框3\"}],\"remote\":\"dict\",\"remoteOptions\":[{\"value\":\"P6\",\"label\":\"P6\"},{\"value\":\"P8\",\"label\":\"P8\"},{\"value\":\"P5\",\"label\":\"P5\"},{\"value\":\"P9\",\"label\":\"P9\"},{\"value\":\"P7\",\"label\":\"P7\"},{\"value\":\"P10\",\"label\":\"P10\"}],\"props\":{\"value\":\"value\",\"label\":\"label\"},\"remoteFunc\":\"func_1608433344000_95961\",\"dictType\":\"ac3f1996-bcec-4604-b465-eaf5d1208e79\"},\"key\":\"1608433344000_95961\",\"model\":\"level\",\"rules\":[{\"type\":\"string\",\"message\":\"岗位格式不正确\"}]}]},{\"span\":12,\"list\":[{\"type\":\"date\",\"name\":\"入职时间\",\"labelWidth\":\"\",\"hidden\":false,\"icon\":\"regular/calendar-alt\",\"options\":{\"defaultValue\":false,\"readonly\":false,\"disabled\":false,\"editable\":true,\"clearable\":true,\"placeholder\":\"\",\"startPlaceholder\":\"\",\"endPlaceholder\":\"\",\"type\":\"date\",\"format\":\"yyyy-MM-dd\",\"timestamp\":false,\"required\":false,\"width\":\"100%\",\"remoteFunc\":\"func_1608432345000_20310\"},\"key\":\"1608432345000_20310\",\"model\":\"jobtime\",\"rules\":[{\"type\":\"string\",\"message\":\"入职时间格式不正确\"}]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1575516929000_36539\"},\"key\":\"1575516931000_0.9740509729876656\",\"model\":\"1575516929000_36539\",\"rules\":[]},{\"type\":\"grid\",\"name\":\"栅格布局\",\"icon\":\"th\",\"columns\":[{\"span\":12,\"list\":[{\"type\":\"input\",\"name\":\"薪资\",\"labelWidth\":0,\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_1575516931000_89639\"},\"key\":\"salary\",\"model\":\"salary\",\"rules\":[]}]},{\"span\":12,\"list\":[{\"type\":\"input\",\"name\":\"联系方式\",\"labelWidth\":0,\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_1575516931000_89639\"},\"key\":\"1575516931000_0.7423405755223678\",\"model\":\"mobile\",\"rules\":[{\"type\":\"string\",\"message\":\"单行文本格式不正确\"}]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1575516929000_36539\"},\"key\":\"1575516931000_0.3680056593272678\",\"model\":\"1575516929000_36539\",\"rules\":[]},{\"type\":\"grid\",\"name\":\"栅格布局\",\"icon\":\"th\",\"columns\":[{\"span\":12,\"list\":[{\"type\":\"input\",\"name\":\"专业\",\"labelWidth\":0,\"hidden\":false,\"icon\":\"regular/keyboard\",\"options\":{\"width\":\"100%\",\"defaultValue\":\"\",\"readonly\":false,\"disabled\":false,\"required\":false,\"dataType\":\"string\",\"pattern\":\"\",\"placeholder\":\"\",\"remoteFunc\":\"func_1575516931000_89639\"},\"key\":\"major\",\"model\":\"major\",\"rules\":[]}]},{\"span\":12,\"list\":[{\"type\":\"date\",\"name\":\"出生年月\",\"labelWidth\":\"\",\"hidden\":false,\"icon\":\"regular/calendar-alt\",\"options\":{\"defaultValue\":false,\"readonly\":false,\"disabled\":false,\"editable\":true,\"clearable\":true,\"placeholder\":\"\",\"startPlaceholder\":\"\",\"endPlaceholder\":\"\",\"type\":\"month\",\"format\":\"yyyy-MM\",\"timestamp\":false,\"required\":false,\"width\":\"100%\",\"remoteFunc\":\"func_1608432438000_26217\"},\"key\":\"1608432438000_26217\",\"model\":\"birthdate\",\"rules\":[]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1575516929000_36539\"},\"key\":\"1575516931000_0.22046952760726568\",\"model\":\"1575516929000_36539\",\"rules\":[]},{\"type\":\"grid\",\"name\":\"栅格布局(1列)\",\"icon\":\"th\",\"columns\":[{\"span\":24,\"list\":[{\"type\":\"table\",\"name\":\"工作履历\",\"icon\":\"table\",\"options\":{\"remoteFunc\":\"func_1608432102000_18779\",\"visibleList\":{\"actionColumnBtnEdit\":true,\"actionColumnBtnDetail\":false,\"btnAdd\":true,\"actionColumn\":true,\"tableTitle\":false,\"searchForm\":false,\"actionColumnBtnDel\":true,\"conditionTitle\":false,\"btnExport\":true,\"btnImport\":false},\"tableParams\":\"personid,id\",\"prefill\":\"personid,id\",\"tableTitle\":\"\",\"showPagination\":true,\"isMultiple\":false,\"tableName\":\"resume\",\"tableDesignerName\":\"person_resume\",\"dialogFormDesignerName\":\"person_resume\"},\"key\":\"1608432102000_18779\",\"model\":\"人员履历表\",\"rules\":[]}]}],\"options\":{\"gutter\":0,\"justify\":\"start\",\"align\":\"top\",\"remoteFunc\":\"func_1608432099000_43356\"},\"key\":\"1608432099000_43356\",\"model\":\"1608432099000_43356\",\"rules\":[]}],\"config\":{\"labelWidth\":140,\"labelPosition\":\"right\",\"size\":\"small\",\"isTableClass\":true,\"name\":\"person\"}}', '员工管理', '2020-12-20 12:39:38'); 160 | COMMIT; 161 | 162 | -- ---------------------------- 163 | -- Table structure for person 164 | -- ---------------------------- 165 | DROP TABLE IF EXISTS `person`; 166 | CREATE TABLE `person` ( 167 | `id` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', 168 | `personname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '姓名', 169 | `deptname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '所在部门', 170 | `salary` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '薪资', 171 | `post` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '岗位', 172 | `level` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '职级', 173 | `timestamp` datetime DEFAULT NULL COMMENT '时间戳', 174 | `jobtime` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '入职时间', 175 | `jobno` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '工号', 176 | `education` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文化程度', 177 | `major` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '专业', 178 | `mobile` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '联系方式', 179 | `birthdate` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '出生年月', 180 | `sex` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '性别', 181 | `avatar` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '头像', 182 | PRIMARY KEY (`id`) 183 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; 184 | 185 | -- ---------------------------- 186 | -- Records of person 187 | -- ---------------------------- 188 | BEGIN; 189 | INSERT INTO `person` VALUES ('038aa5c4-4274-11eb-bb0a-ed55e0675fa7', '邬彦皓', '研发部', '10000', '研发岗', 'P6', '2021-01-04 23:22:17', '2018-05-23', '2019548937', '博士', '专业', '15686640133', '2020-06', '男', NULL); 190 | INSERT INTO `person` VALUES ('038ac626-4274-11eb-bb0a-ed55e0675fa7', '路曼书', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-10-27', '2019614945', '本科', '专业', '17639302987', '2020-06', '男', NULL); 191 | INSERT INTO `person` VALUES ('038aeb06-4274-11eb-bb0a-ed55e0675fa7', '萧宏恩', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-12-04', '2019927916', '本科', '专业', '15620493978', '2020-06', '男', NULL); 192 | INSERT INTO `person` VALUES ('038afd1c-4274-11eb-bb0a-ed55e0675fa7', '戴会琦', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-03-02', '2019794742', '本科', '专业', '17623151335', '2020-06', '男', NULL); 193 | INSERT INTO `person` VALUES ('038b0d7a-4274-11eb-bb0a-ed55e0675fa7', '凤虎鹏', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-01-22', '2019689965', '本科', '专业', '17651279640', '2020-06', '男', NULL); 194 | INSERT INTO `person` VALUES ('038b221a-4274-11eb-bb0a-ed55e0675fa7', '乐冬若', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-10-18', '2019565599', '本科', '专业', '17646002851', '2020-06', '男', NULL); 195 | INSERT INTO `person` VALUES ('038b40ba-4274-11eb-bb0a-ed55e0675fa7', '鲁双健', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-10-17', '2019758100', '本科', '专业', '15613393016', '2020-06', '男', NULL); 196 | INSERT INTO `person` VALUES ('038b5d20-4274-11eb-bb0a-ed55e0675fa7', '石越延', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-08-02', '2019593703', '本科', '专业', '13625998336', '2020-06', '男', NULL); 197 | INSERT INTO `person` VALUES ('038b777e-4274-11eb-bb0a-ed55e0675fa7', '施心怡', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-07-20', '2019694217', '本科', '专业', '15675146795', '2020-06', '男', NULL); 198 | INSERT INTO `person` VALUES ('038b9330-4274-11eb-bb0a-ed55e0675fa7', '廉新奎', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-12-28', '2019689978', '本科', '专业', '13665657099', '2020-06', '男', NULL); 199 | INSERT INTO `person` VALUES ('038ba988-4274-11eb-bb0a-ed55e0675fa7', '柳翔伯', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-04-24', '2019867237', '本科', '专业', '13686623977', '2020-06', '男', NULL); 200 | INSERT INTO `person` VALUES ('038bd44e-4274-11eb-bb0a-ed55e0675fa7', '凌帆强', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-07-30', '2019766252', '本科', '专业', '17640824681', '2020-06', '男', NULL); 201 | INSERT INTO `person` VALUES ('038bed76-4274-11eb-bb0a-ed55e0675fa7', '熊一远', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-12-18', '2019729549', '本科', '专业', '15620496363', '2020-06', '男', NULL); 202 | INSERT INTO `person` VALUES ('038c03ec-4274-11eb-bb0a-ed55e0675fa7', '凌紫宗', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-01-28', '2019848988', '本科', '专业', '17637737408', '2020-06', '男', NULL); 203 | INSERT INTO `person` VALUES ('038c1d0a-4274-11eb-bb0a-ed55e0675fa7', '卜航钧', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-06-29', '2019556295', '本科', '专业', '15612689300', '2020-06', '男', NULL); 204 | INSERT INTO `person` VALUES ('038c2d36-4274-11eb-bb0a-ed55e0675fa7', '凌征柏', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-03-27', '2019734513', '本科', '专业', '15609813363', '2020-06', '男', NULL); 205 | INSERT INTO `person` VALUES ('038c3efc-4274-11eb-bb0a-ed55e0675fa7', '卜小双', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-09-13', '2019503680', '本科', '专业', '17688696112', '2020-06', '男', NULL); 206 | INSERT INTO `person` VALUES ('038c4e92-4274-11eb-bb0a-ed55e0675fa7', '强武中', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-10-17', '2019814860', '本科', '专业', '17608396635', '2020-06', '男', NULL); 207 | INSERT INTO `person` VALUES ('038c5f68-4274-11eb-bb0a-ed55e0675fa7', '屈华宇', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-11-11', '2019563259', '本科', '专业', '17690528348', '2020-06', '男', NULL); 208 | INSERT INTO `person` VALUES ('038c6ee0-4274-11eb-bb0a-ed55e0675fa7', '康媛征', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-12-10', '2019871719', '本科', '专业', '15614722132', '2020-06', '男', NULL); 209 | INSERT INTO `person` VALUES ('038c7f52-4274-11eb-bb0a-ed55e0675fa7', '诸忠泉', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-02-13', '2019668816', '本科', '专业', '15610097887', '2020-06', '男', NULL); 210 | INSERT INTO `person` VALUES ('038c8e52-4274-11eb-bb0a-ed55e0675fa7', '柯江瑜', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-10-07', '2019728923', '本科', '专业', '15616047698', '2020-06', '男', NULL); 211 | INSERT INTO `person` VALUES ('038c9eb0-4274-11eb-bb0a-ed55e0675fa7', '姚远博', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-06-22', '2019638168', '本科', '专业', '13622265870', '2020-06', '男', NULL); 212 | INSERT INTO `person` VALUES ('038caf18-4274-11eb-bb0a-ed55e0675fa7', '房良锦', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-01-25', '2019504073', '本科', '专业', '17639644735', '2020-06', '男', NULL); 213 | INSERT INTO `person` VALUES ('038cbea4-4274-11eb-bb0a-ed55e0675fa7', '麻冬圣', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-12-01', '2019605862', '本科', '专业', '17696416506', '2020-06', '男', NULL); 214 | INSERT INTO `person` VALUES ('038ccd68-4274-11eb-bb0a-ed55e0675fa7', '何钧坚', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-05-19', '2019517092', '本科', '专业', '17609460950', '2020-06', '男', NULL); 215 | INSERT INTO `person` VALUES ('038cdd30-4274-11eb-bb0a-ed55e0675fa7', '霍骏斌', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-02-23', '2019767873', '本科', '专业', '17619904819', '2020-06', '男', NULL); 216 | INSERT INTO `person` VALUES ('038cec62-4274-11eb-bb0a-ed55e0675fa7', '管晋芳', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-08-05', '2019788091', '本科', '专业', '13601406042', '2020-06', '男', NULL); 217 | INSERT INTO `person` VALUES ('038cfc52-4274-11eb-bb0a-ed55e0675fa7', '管珍家', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-07-13', '2019636837', '本科', '专业', '17666242878', '2020-06', '男', NULL); 218 | INSERT INTO `person` VALUES ('038d0bd4-4274-11eb-bb0a-ed55e0675fa7', '左彦琪', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-11-16', '2019819912', '本科', '专业', '15697115233', '2020-06', '男', NULL); 219 | INSERT INTO `person` VALUES ('038d1ade-4274-11eb-bb0a-ed55e0675fa7', '昌萌灿', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-10-11', '2019689048', '本科', '专业', '13615195848', '2020-06', '男', NULL); 220 | INSERT INTO `person` VALUES ('038d2be6-4274-11eb-bb0a-ed55e0675fa7', '王勤波', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-04-08', '2019985507', '本科', '专业', '15661602918', '2020-06', '男', NULL); 221 | INSERT INTO `person` VALUES ('038d3b5e-4274-11eb-bb0a-ed55e0675fa7', '高田元', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-01-01', '2019860392', '本科', '专业', '17601798270', '2020-06', '男', NULL); 222 | INSERT INTO `person` VALUES ('038d4bd0-4274-11eb-bb0a-ed55e0675fa7', '谈震方', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-03-14', '2019845437', '本科', '专业', '15632108246', '2020-06', '男', NULL); 223 | INSERT INTO `person` VALUES ('038d5b2a-4274-11eb-bb0a-ed55e0675fa7', '崔伯坤', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-12-30', '2019646011', '本科', '专业', '13644736018', '2020-06', '男', NULL); 224 | INSERT INTO `person` VALUES ('038d6af2-4274-11eb-bb0a-ed55e0675fa7', '章萌生', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-05-22', '2019693743', '本科', '专业', '13632922584', '2020-06', '男', NULL); 225 | INSERT INTO `person` VALUES ('038d7c18-4274-11eb-bb0a-ed55e0675fa7', '诸萌夫', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-12-12', '2019530682', '本科', '专业', '17657299789', '2020-06', '男', NULL); 226 | INSERT INTO `person` VALUES ('038d8d34-4274-11eb-bb0a-ed55e0675fa7', '米征智', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-07-30', '2019572182', '本科', '专业', '15694338276', '2020-06', '男', NULL); 227 | INSERT INTO `person` VALUES ('038d9e00-4274-11eb-bb0a-ed55e0675fa7', '殷广健', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-01-15', '2019768865', '本科', '专业', '13675781251', '2020-06', '男', NULL); 228 | INSERT INTO `person` VALUES ('038daf30-4274-11eb-bb0a-ed55e0675fa7', '汪洲健', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-06-23', '2019627781', '本科', '专业', '15646149452', '2020-06', '男', NULL); 229 | INSERT INTO `person` VALUES ('038dc4e8-4274-11eb-bb0a-ed55e0675fa7', '杜宏伊', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-04-04', '2019832308', '本科', '专业', '13642998592', '2020-06', '男', NULL); 230 | INSERT INTO `person` VALUES ('038de1d0-4274-11eb-bb0a-ed55e0675fa7', '范仲方', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-11-06', '2019778199', '本科', '专业', '15679605781', '2020-06', '男', NULL); 231 | INSERT INTO `person` VALUES ('038df346-4274-11eb-bb0a-ed55e0675fa7', '冯卓宝', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-06-23', '2019894071', '本科', '专业', '15628202263', '2020-06', '男', NULL); 232 | INSERT INTO `person` VALUES ('038e052a-4274-11eb-bb0a-ed55e0675fa7', '包轩化', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-11-01', '2019635757', '本科', '专业', '17645453153', '2020-06', '男', NULL); 233 | INSERT INTO `person` VALUES ('038e1538-4274-11eb-bb0a-ed55e0675fa7', '戴利菲', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-09-30', '2019996573', '本科', '专业', '15625999999', '2020-06', '男', NULL); 234 | INSERT INTO `person` VALUES ('038e2d48-4274-11eb-bb0a-ed55e0675fa7', '施美茜', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-03-27', '2019575594', '本科', '专业', '17698265022', '2020-06', '男', NULL); 235 | INSERT INTO `person` VALUES ('038e3f04-4274-11eb-bb0a-ed55e0675fa7', '郎希志', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-12-05', '2019888253', '本科', '专业', '13670147496', '2020-06', '男', NULL); 236 | INSERT INTO `person` VALUES ('038e4fc6-4274-11eb-bb0a-ed55e0675fa7', '孙志民', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-12-08', '2019714483', '本科', '专业', '15656813156', '2020-06', '男', NULL); 237 | INSERT INTO `person` VALUES ('038e60b0-4274-11eb-bb0a-ed55e0675fa7', '魏勤滨', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-11-22', '2019907656', '本科', '专业', '13682644748', '2020-06', '男', NULL); 238 | INSERT INTO `person` VALUES ('038e7140-4274-11eb-bb0a-ed55e0675fa7', '孙日富', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-08-29', '2019894830', '本科', '专业', '15695997014', '2020-06', '男', NULL); 239 | INSERT INTO `person` VALUES ('038e80a4-4274-11eb-bb0a-ed55e0675fa7', '钮孝来', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-08-14', '2019751184', '本科', '专业', '13685379554', '2020-06', '男', NULL); 240 | INSERT INTO `person` VALUES ('038e90d0-4274-11eb-bb0a-ed55e0675fa7', '王英阳', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-02-12', '2019571430', '本科', '专业', '13650381081', '2020-06', '男', NULL); 241 | INSERT INTO `person` VALUES ('038ea0e8-4274-11eb-bb0a-ed55e0675fa7', '袁淇虎', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-09-24', '2019603598', '本科', '专业', '15678872714', '2020-06', '男', NULL); 242 | INSERT INTO `person` VALUES ('038eb182-4274-11eb-bb0a-ed55e0675fa7', '滕萌若', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-04-18', '2019803699', '本科', '专业', '17607361041', '2020-06', '男', NULL); 243 | INSERT INTO `person` VALUES ('038ec208-4274-11eb-bb0a-ed55e0675fa7', '鲍鹏银', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-04-17', '2019707704', '本科', '专业', '13649590210', '2020-06', '男', NULL); 244 | INSERT INTO `person` VALUES ('038ed23e-4274-11eb-bb0a-ed55e0675fa7', '钟一百', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-07-28', '2019627422', '本科', '专业', '17631495657', '2020-06', '男', NULL); 245 | INSERT INTO `person` VALUES ('038ee328-4274-11eb-bb0a-ed55e0675fa7', '费靖豪', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-12-27', '2019514000', '本科', '专业', '15673191955', '2020-06', '男', NULL); 246 | INSERT INTO `person` VALUES ('038ef336-4274-11eb-bb0a-ed55e0675fa7', '韩大长', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-03-21', '2019687734', '本科', '专业', '15628591111', '2020-06', '男', NULL); 247 | INSERT INTO `person` VALUES ('038f02f4-4274-11eb-bb0a-ed55e0675fa7', '徐坚忠', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-02-20', '2019896670', '本科', '专业', '13689192591', '2020-06', '男', NULL); 248 | INSERT INTO `person` VALUES ('038f130c-4274-11eb-bb0a-ed55e0675fa7', '康宇剑', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-01-13', '2019920147', '本科', '专业', '17685125250', '2020-06', '男', NULL); 249 | INSERT INTO `person` VALUES ('038f2342-4274-11eb-bb0a-ed55e0675fa7', '范真虹', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-10-04', '2019910727', '本科', '专业', '13601525109', '2020-06', '男', NULL); 250 | INSERT INTO `person` VALUES ('038f3224-4274-11eb-bb0a-ed55e0675fa7', '钟洋兰', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-09-05', '2019793195', '本科', '专业', '13671341340', '2020-06', '男', NULL); 251 | INSERT INTO `person` VALUES ('038f40e8-4274-11eb-bb0a-ed55e0675fa7', '梅清铁', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-02-17', '2019733794', '本科', '专业', '17643378904', '2020-06', '男', NULL); 252 | INSERT INTO `person` VALUES ('038f5056-4274-11eb-bb0a-ed55e0675fa7', '鲁仪强', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-08-12', '2019789386', '本科', '专业', '15653795984', '2020-06', '男', NULL); 253 | INSERT INTO `person` VALUES ('038f641a-4274-11eb-bb0a-ed55e0675fa7', '郎庆涛', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-09-01', '2019745548', '本科', '专业', '17620427825', '2020-06', '男', NULL); 254 | INSERT INTO `person` VALUES ('038f7496-4274-11eb-bb0a-ed55e0675fa7', '陈蔚景', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-06-30', '2019859582', '本科', '专业', '17635922320', '2020-06', '男', NULL); 255 | INSERT INTO `person` VALUES ('038f847c-4274-11eb-bb0a-ed55e0675fa7', '曹其道', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-06-27', '2019561268', '本科', '专业', '13697089553', '2020-06', '男', NULL); 256 | INSERT INTO `person` VALUES ('038f94b2-4274-11eb-bb0a-ed55e0675fa7', '黄荣传', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-12-10', '2019727592', '本科', '专业', '15617357000', '2020-06', '男', NULL); 257 | INSERT INTO `person` VALUES ('9842bace-c4d6-4512-8406-9db5f0bac182', '张三', '研发部', '10000', '研发岗', 'P6', '2021-01-05 14:51:24', '2015-06-07', '2019697465', '本科', '专业', '17667768265', '2020-06', '男', NULL); 258 | INSERT INTO `person` VALUES ('fc7cb664-4273-11eb-bb0a-ed55e0675fa7', '毛石媛', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2018-07-06', '2019525695', '本科', '专业', '17664489380', '2020-06', '男', NULL); 259 | INSERT INTO `person` VALUES ('fd75f2ce-4273-11eb-bb0a-ed55e0675fa7', '贺亦思', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2016-04-05', '2019536080', '本科', '专业', '17619264321', '2020-06', '男', NULL); 260 | INSERT INTO `person` VALUES ('fdd8f66c-4273-11eb-bb0a-ed55e0675fa7', '宋星岩', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-10-08', '2019603316', '本科', '专业', '17631510757', '2020-06', '男', NULL); 261 | INSERT INTO `person` VALUES ('fe22aa46-4273-11eb-bb0a-ed55e0675fa7', '金义淇', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2015-01-22', '2019908343', '本科', '专业', '17613155865', '2020-06', '男', NULL); 262 | INSERT INTO `person` VALUES ('fe66142a-4273-11eb-bb0a-ed55e0675fa7', '尹华晖', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2017-12-28', '2019731765', '本科', '专业', '17665919362', '2020-06', '男', NULL); 263 | INSERT INTO `person` VALUES ('fe9ce572-4273-11eb-bb0a-ed55e0675fa7', '雷景双', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-10-11', '2019933797', '本科', '专业', '15681317336', '2020-06', '男', NULL); 264 | INSERT INTO `person` VALUES ('fedeea3a-4273-11eb-bb0a-ed55e0675fa7', '贾政政', '研发部', '10000', '研发岗', 'P6', '2020-12-20 11:30:42', '2019-11-29', '2019973692', '本科', '专业', '15689999903', '2020-06', '男', NULL); 265 | INSERT INTO `person` VALUES ('ff1b847c-4273-11eb-bb0a-ed55e0675fa7', '米儿天', '研发部', '10000', '研发岗', 'P6', '2021-01-04 17:45:58', '2015-03-22', '2019567070', '本科', '专业', '13696110769', '2020-06', '男', NULL); 266 | INSERT INTO `person` VALUES ('ff5d3a66-4273-11eb-bb0a-ed55e0675fa7', '郑士灵', '研发部', '10000', '研发岗', 'P6', '2021-01-04 17:52:28', '2016-05-17', '2019914272', '本科', '专业', '17684736967', '2020-06', '男', NULL); 267 | COMMIT; 268 | 269 | -- ---------------------------- 270 | -- Table structure for person_education 271 | -- ---------------------------- 272 | DROP TABLE IF EXISTS `person_education`; 273 | CREATE TABLE `person_education` ( 274 | `id` char(36) NOT NULL, 275 | `personid` varchar(255) DEFAULT NULL, 276 | `time` varchar(255) DEFAULT NULL COMMENT '起止时间', 277 | `school` varchar(255) DEFAULT NULL COMMENT '学校', 278 | `type` varchar(255) DEFAULT NULL COMMENT '学校类型', 279 | `remark` text COMMENT '备注', 280 | `timestamp` datetime DEFAULT NULL, 281 | PRIMARY KEY (`id`) 282 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 283 | 284 | -- ---------------------------- 285 | -- Records of person_education 286 | -- ---------------------------- 287 | BEGIN; 288 | COMMIT; 289 | 290 | -- ---------------------------- 291 | -- Table structure for person_resume 292 | -- ---------------------------- 293 | DROP TABLE IF EXISTS `person_resume`; 294 | CREATE TABLE `person_resume` ( 295 | `id` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 296 | `personid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, 297 | `time` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '起止时间', 298 | `workunit` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '工作单位', 299 | `workduty` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '职务', 300 | `remark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '备注', 301 | `timestamp` datetime DEFAULT NULL, 302 | PRIMARY KEY (`id`) 303 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; 304 | 305 | -- ---------------------------- 306 | -- Records of person_resume 307 | -- ---------------------------- 308 | BEGIN; 309 | INSERT INTO `person_resume` VALUES ('4d660920-45d6-47d6-b366-5de31fdfa6da', '9842bace-c4d6-4512-8406-9db5f0bac182', '2019-01,2019-08', '江苏省xxx公司', '软件工程师', '

相关备注

', '2020-12-20 11:29:54'); 310 | INSERT INTO `person_resume` VALUES ('e1c2a250-2b94-45cb-a239-d7f9b690459d', '9842bace-c4d6-4512-8406-9db5f0bac182', '2019-10,2020-10', '苏州市某科技有限公司', '某技术组长', '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
123      
123      
123      
 345     
  567567    
', '2020-12-20 11:30:34'); 311 | COMMIT; 312 | 313 | -- ---------------------------- 314 | -- Table structure for role 315 | -- ---------------------------- 316 | DROP TABLE IF EXISTS `role`; 317 | CREATE TABLE `role` ( 318 | `id` char(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, 319 | `roleName` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '角色名', 320 | `roleAuthName` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '权限', 321 | `roleAuthNameDict` longtext CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '权限名称', 322 | `rank` int DEFAULT NULL COMMENT '排序', 323 | `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 324 | PRIMARY KEY (`id`) USING BTREE 325 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 326 | 327 | -- ---------------------------- 328 | -- Records of role 329 | -- ---------------------------- 330 | BEGIN; 331 | INSERT INTO `role` VALUES ('00000000-1000-0000-0000-000000000000', '超级管理员', 'AdminDashboardForAdmin,AdminDashboard,Users,Role,FormDesigner,TableDesigner,Dict,flowClueInfo,BusinessActClueInfo,System,DevTools', '运维桌面,用户管理,角色管理,表单设计,表格设计,字典管理,线索管理', 2, '2020-09-17 10:32:04'); 332 | COMMIT; 333 | 334 | -- ---------------------------- 335 | -- Table structure for users 336 | -- ---------------------------- 337 | DROP TABLE IF EXISTS `users`; 338 | CREATE TABLE `users` ( 339 | `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, 340 | `userName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用户名', 341 | `deptId` varchar(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, 342 | `roleId` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, 343 | `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '密码', 344 | `realName` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '真实姓名', 345 | `rank` int DEFAULT '0' COMMENT '排序码', 346 | `photo` longtext CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '照片', 347 | `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 348 | PRIMARY KEY (`id`) USING BTREE, 349 | KEY `index_id` (`id`) USING BTREE, 350 | KEY `index_username` (`userName`) USING BTREE, 351 | KEY `index_deptid` (`deptId`) 352 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; 353 | 354 | -- ---------------------------- 355 | -- Records of users 356 | -- ---------------------------- 357 | BEGIN; 358 | INSERT INTO `users` VALUES ('00000000-1000-0000-0000-000000000000', 'admin', '2f8447de-5732-4fa4-8286-9a71b41dd1e7', '00000000-1000-0000-0000-000000000000', '123', '超级管理员', 0, 'data:image/jpg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCABkAGQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3aiiigAqhrOs2Og6ZLqGoTCOCP8Sx7KB3Jq/0GTXgHxT8SjW/Ef2O1uFlsLJQqGNsq7kZZsjr6fgaAJPEPxZ1vVJXj0xv7Oteg2YMrD3bt+GPqa4m61O/vWLXd7czsepllZv5mqtFMkckjxtujdlPqpxWzp3jDxDpTqbTV7tQP4HkLp/3y2RWJRQB7d4M+K0WrXMWna3HHbXMhCx3CcRuewIP3T+n0r02vkSvpH4ea4+veD7SaeTfcw5gmJOSSvQn6jH60ho6qiiigYUUUUAFFFFAHL/EW8lsfAWqzQsVcxrHkdg7qp/Qmvmyvpnx3Zm/8DavAoywtzIB/uEP/wCy1478OfDGna1eXWo6zNHHpthtLrI4RXZs4BPpwfrxTEzl9O0TVdWJGn6fc3IBwTFEWA+p6Ctn/hXXi3Zv/sWbH++mfyzmvd7fxFoUVukdnIfs6jCfZrWRowPYquMU4eL/AA7v2PrFpE/92aQRn8mxSCx81X+k6jpUgj1CxuLVj0E0ZXP0z1qnX07e+IfCl1bPBeatpE8DD5o5LiNwfwzXneseB/CGpyGfRdUuLbdzsitZLiL8MDI/M0wseTV2nws1Gey8dWcMbsIroPFKueCNpI/IgfrXQeH/AIZ6DdX4ivPESXMi8mzjTyZCPcMd2PoPxrD+Fdg0/wAQbdsZFpHLI3/fJX+bCgD6DooopDCiiigAooooAzPEglPhfVhBnzvsc2zHXOw4rxzwz4Tjt/iBYWdy63OmyKt1EGORIGjd0yOhxtP5e9e7EAjBGQa8/Phn+zPFlvbR3jLb3EDHT22AtayRNvCf7S4kkGD/AA5HvQB6AOBgdK5jx/p9pqHhG8W4gSSYKBbEj5hKWAUA9eSQPxq/9r16IbH0q1mcf8tIrsqre+CuR9OfqaZDpl/fX8N5rMkAW3bfBZ25JjR/77MQC7DPHAA9M80AYL+EdD0/xrozJpdtFC1vMFAX5WmXYVyD1O3eR9Pau5qlqmmRaraCF5HikRxJDNH96Jx0Yf55BI71Sjn8RWwEc9jZ3uOBPDOYi3uUZTj8GNAGP8S9Ki1DwsZVVVvoZ4RbSjhlZpFXAPXHzfp7Vy3wq0S40vWkuZZQxvdNNwyD+BTIoTJ9ThjXW+JBftol1qGpJDClrGzW1pC5fdMRtQuxA6FhhQOvOTgVo+F/Dv8Awj9gFmnNxePHGkku3aAqLtRFHZQPzJJ70CN2iiigYUUUUAFFFFABWN4lsbi601LmyXdfWMq3Vuv99l6p/wACUsv41s0UAVdN1C31XToL61bdDMu5c9R6g+hB4I9RVquMlmutN8V3S+HrY3kO3ztStQ4VUkOMGMngSEZJXoQAeCat3XxC8OWNuXvLuS3nX71rLCyzA+hXH69PegDqKK4TTfi14Zv5zFM9zZf3XuIxtb8VJx+NX9R8TX2oWE//AAitlJeFUJN4y7Yh/wBc92PMb0A4z1PagCxqTf234ktNJj+a2sHW7vW7bx/qo/rn5iPRR610lY/hiHT49Dhl06Vp458yyTyHMksh+8z/AO1ngjtjHatigAooooAKKKKACuO134meHNEkaH7Q17cLwY7UBgD7tnH6muX+Lni+4tZE8P2ErR74w906nBIPRM9uOT9R7147QK56pf8AxsvXJGn6RbxDs08hkP5DbXNah8TfFeoKU/tH7Mh/htkCf+Pfe/WuQopgen/CrxmbPU5NG1GYtHeyb4pnOSJj2J77sD8frXWeJ/D1n4+1r7NAoiTTw0c+oqMkvjiJR0bBOW9Og5JrwUEqwZSQRyCO1enfDf4iR6UiaLrDhbQsTDcn/lmSckN7Enr2+nQAtwfBqe0iluZb2G9miIeK1CFEmAOSrNnIyMjjoT1rtNT8a6Zo/g0apboqsB5ENmw2sko48tl7bcc+w9xWh4k8W6Z4Z0r7ZczLI8i5ghRgWmPbHt79K+ctb1m613VbjULoqHmcuUQYVeAOB9ABnqcUgLVn4u1/T7ye6tNUniknkaWQA5RmJyTtPH6V09l8YvEdvgXMVldr3LxlG/NSB+lee0UxHtemfGnTZmVNT02e1zwXhcSL9SOD/OvQdJ1rTdctftOmXkVzF32HlfYjqD9a+U60tD1y+8PapFf2EpSRD8y5+WRe6sO4NA7n1TRVLSNSh1nSLTUYOI7iISAH+HPUfgcj8KKQz5u8Z351Lxlq1ySSDcsi/wC6p2j9AKwqt6lFcJfzvcwSws8jNiRCp5Oe9VKZIUUUUAFFFFACli2MknAwM9qSiigAooooAKKKMZOBQB7j8Kddhj8GfZrmTabe5dEH+yQG/mxorzrQP7VtNPZItOvXRpCwKQMQeB6D2opDPoySKOZCkqK6nqrDIrJuvCPh28yZ9EsGY9WECqfzAzRRQMx7j4W+EZ8401oSe8c7j9CSKxtQ+EHhyKB5Y7jUUIHQSoR+q0UUCOC1Twhp9izCKa5OP7zL/wDE1y13apA5CFjj1oopgQRIHfBz+Fb2naBa3ZHmSTDP90j/AAoooA7rRPhdoeojM11qA9lkQf8AsldLB8I/CkJ+eC6n/wCuk5H/AKDiiikBrW3gDwpaf6vRLZv+uuZP/Qia2bXStPsQPslha2+OnlQqv8hRRQMt0UUUAf/Z', '2021-01-05 15:00:15'); 359 | COMMIT; 360 | 361 | -- ---------------------------- 362 | -- Function structure for generatePhone 363 | -- ---------------------------- 364 | DROP FUNCTION IF EXISTS `generatePhone`; 365 | delimiter ;; 366 | CREATE FUNCTION `generatePhone`() 367 | RETURNS char(11) CHARSET utf8mb3 368 | DETERMINISTIC 369 | BEGIN 370 | DECLARE head VARCHAR(100) DEFAULT '000,156,136,176'; 371 | DECLARE content CHAR(10) DEFAULT '0123456789'; 372 | DECLARE phone CHAR(11) DEFAULT substring(head, 1+(FLOOR(1 + (RAND() * 3))*4), 3); 373 | 374 | #SET phone = CONCAT(phone, substring('156,136,123,456,789', 1+(FLOOR(1 + (RAND() * 4))*4), 3)); 375 | 376 | DECLARE i int DEFAULT 1; 377 | DECLARE len int DEFAULT LENGTH(content); 378 | WHILE i<9 DO 379 | SET i=i+1; 380 | SET phone = CONCAT(phone, substring(content, floor(1 + RAND() * len), 1)); 381 | END WHILE; 382 | 383 | RETURN phone; 384 | END 385 | ;; 386 | delimiter ; 387 | 388 | -- ---------------------------- 389 | -- Function structure for generateUserName 390 | -- ---------------------------- 391 | DROP FUNCTION IF EXISTS `generateUserName`; 392 | delimiter ;; 393 | CREATE FUNCTION `generateUserName`() 394 | RETURNS varchar(255) CHARSET utf8mb3 395 | DETERMINISTIC 396 | BEGIN 397 | DECLARE xing varchar(2056) DEFAULT '赵钱孙李周郑王冯陈楮卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐费廉岑薛雷贺倪汤滕殷罗毕郝邬安常乐于时傅皮齐康伍余元卜顾孟平黄和穆萧尹姚邵湛汪祁毛禹狄米贝明臧计伏成戴谈宋茅庞熊纪舒屈项祝董梁杜阮蓝闽席季麻强贾路娄危江童颜郭梅盛林刁锺徐丘骆高夏蔡田樊胡凌霍虞万支柯昝管卢莫经裘缪干解应宗丁宣贲邓郁单杭洪包诸左石崔吉钮龚程嵇邢滑裴陆荣翁'; 398 | 399 | DECLARE ming varchar(2056) DEFAULT '嘉懿煜城懿轩烨伟苑博伟泽熠彤鸿煊博涛烨霖烨华煜祺智宸正豪昊然明杰诚立轩立辉峻熙弘文熠彤鸿煊烨霖哲瀚鑫鹏致远俊驰雨泽烨磊晟睿天佑文昊修洁黎昕远航旭尧鸿涛伟祺轩越泽浩宇瑾瑜皓轩擎苍擎宇志泽睿渊楷瑞轩弘文哲瀚雨泽鑫磊梦琪忆之桃慕青问兰尔岚元香初夏沛菡傲珊曼文乐菱痴珊恨玉惜文香寒新柔语蓉海安夜蓉涵柏水桃醉蓝春儿语琴从彤傲晴语兰又菱碧彤元霜怜梦紫寒妙彤曼易南莲紫翠雨寒易烟如萱若南寻真晓亦向珊慕灵以蕊寻雁映易雪柳孤岚笑霜海云凝天沛珊寒云冰旋宛儿绿真盼儿晓霜碧凡夏菡曼香若烟半梦雅绿冰蓝灵槐平安书翠翠风香巧代云梦曼幼翠友巧听寒梦柏醉易访旋亦玉凌萱访卉怀亦笑蓝春翠靖柏夜蕾冰夏梦松书雪乐枫念薇靖雁寻春恨山从寒忆香觅波静曼凡旋以亦念露芷蕾千兰新波代真新蕾雁玉冷卉紫山千琴恨天傲芙盼山怀蝶冰兰山柏翠萱乐丹翠柔谷山之瑶冰露尔珍谷雪乐萱涵菡海莲傲蕾青槐冬儿易梦惜雪宛海之柔夏青亦瑶妙菡春竹修杰伟诚建辉晋鹏天磊绍辉泽洋明轩健柏煊昊强伟宸博超君浩子骞明辉鹏涛炎彬鹤轩越彬风华靖琪明诚高格光华国源宇晗昱涵润翰飞翰海昊乾浩博和安弘博鸿朗华奥华灿嘉慕坚秉建明金鑫锦程瑾瑜鹏经赋景同靖琪君昊俊明季同开济凯安康成乐语力勤良哲理群茂彦敏博明达朋义彭泽鹏举濮存溥心璞瑜浦泽奇邃祥荣轩'; 400 | 401 | DECLARE I_xing int DEFAULT LENGTH(xing) / 3; 402 | DECLARE I_ming int DEFAULT LENGTH(ming) / 3; 403 | DECLARE return_str varchar(2056) DEFAULT ''; 404 | 405 | SET return_str = CONCAT(return_str, substring(xing, floor(1 + RAND() * I_xing), 1)); 406 | SET return_str = CONCAT(return_str, substring(ming, floor(1 + RAND() * I_ming), 1)); 407 | 408 | IF RAND() > 0.400 THEN 409 | SET return_str = CONCAT(return_str, substring(ming, floor(1 + RAND() * I_ming), 1)); 410 | END IF; 411 | 412 | RETURN return_str; 413 | END 414 | ;; 415 | delimiter ; 416 | 417 | SET FOREIGN_KEY_CHECKS = 1; 418 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nestjs-api-server", 3 | "version": "0.0.1", 4 | "description": "一套基于NestJS-API-Server", 5 | "author": "BoBo", 6 | "private": true, 7 | "license": "MIT", 8 | "scripts": { 9 | "prebuild": "rimraf dist", 10 | "build": "nest build", 11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", 12 | "start": "cross-env NODE_ENV=development && nest start --watch", 13 | "start:debug": "cross-env NODE_ENV=development && nest start --debug --watch", 14 | "start:prod": "cross-env NODE_ENV=production && PORT=3000 node dist/main", 15 | "start:test": "cross-env NODE_ENV=test && cross-env NODE_ENV=test && node dist/main", 16 | "pm2": "pm2 start --name admin dist/main.js --env production", 17 | "db": "rm -rf src/entities & npx typeorm-model-generator -h localhost -d nest -p 3306 -u root -x root -e mysql -o src/entities --noConfig true --ce pascal --cp camel", 18 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", 19 | "test": "jest", 20 | "test:watch": "jest --watch", 21 | "test:cov": "jest --coverage", 22 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", 23 | "test:e2e": "jest --config ./test/jest-e2e.json" 24 | }, 25 | "dependencies": { 26 | "@nestjs/common": "10.2.8", 27 | "@nestjs/config": "^3.1.1", 28 | "@nestjs/core": "10.2.8", 29 | "@nestjs/jwt": "^10.2.0", 30 | "@nestjs/platform-express": "10.2.8", 31 | "@nestjs/testing": "10.2.8", 32 | "@nestjs/passport": "^10.0.2", 33 | "@nestjs/platform-socket.io": "^10.2.8", 34 | "@nestjs/platform-ws": "^10.2.8", 35 | "@nestjs/swagger": "^7.1.15", 36 | "@nestjs/typeorm": "^10.0.0", 37 | "@nestjs/websockets": "^10.2.8", 38 | "@nestjs/serve-static": "^4.0.0", 39 | "compression": "^1.7.4", 40 | "dayjs": "^1.8.35", 41 | "helmet": "^4.0.0", 42 | "log4js": "^6.3.0", 43 | "moment": "^2.27.0", 44 | "mysql2": "^3.6.3", 45 | "passport": "^0.4.1", 46 | "passport-jwt": "^4.0.0", 47 | "passport-local": "^1.0.0", 48 | "path": "^0.12.7", 49 | "reflect-metadata": "^0.1.13", 50 | "rimraf": "^3.0.2", 51 | "rxjs": "7.5.5", 52 | "stacktrace-js": "^2.0.2", 53 | "swagger-ui-express": "^4.1.4", 54 | "typeorm": "^0.3.17", 55 | "uuid": "^8.3.0" 56 | }, 57 | "devDependencies": { 58 | "@nestjs/cli": "^10.2.1", 59 | "@nestjs/schematics": "^10.0.3", 60 | "@nestjs/testing": "^10.2.8", 61 | "@types/express": "^4.17.3", 62 | "@types/helmet": "^0.0.47", 63 | "@types/jest": "25.2.3", 64 | "@types/node": "^13.9.1", 65 | "@types/passport-local": "^1.0.33", 66 | "@types/supertest": "^2.0.8", 67 | "@typescript-eslint/eslint-plugin": "6.11.0", 68 | "@typescript-eslint/parser": "6.11.0", 69 | "cross-env": "^7.0.3", 70 | "eslint": "8.53.0", 71 | "eslint-config-prettier": "^9.0.0", 72 | "eslint-plugin-import": "^2.29.0", 73 | "eslint-plugin-prettier": "^5.0.1", 74 | "husky": "^4.3.0", 75 | "jest": "26.0.1", 76 | "lint-staged": "^10.5.1", 77 | "prettier": "^3.1.0", 78 | "start-server-webpack-plugin": "^2.2.5", 79 | "supertest": "^4.0.2", 80 | "ts-jest": "26.1.0", 81 | "ts-node": "^8.6.2", 82 | "tsconfig-paths": "^4.2.0", 83 | "typescript": "5.2.2", 84 | "webpack-node-externals": "^2.5.1", 85 | "tsconfig-paths-webpack-plugin": "^4.1.0" 86 | }, 87 | "husky": { 88 | "hooks": { 89 | "pre-commit": "lint-staged" 90 | } 91 | }, 92 | "lint-staged": { 93 | "src/**/*.{js,ts}": [ 94 | "prettier --write", 95 | "eslint --fix", 96 | "git add" 97 | ] 98 | }, 99 | "jest": { 100 | "moduleFileExtensions": [ 101 | "js", 102 | "json", 103 | "ts" 104 | ], 105 | "rootDir": "src", 106 | "testRegex": ".spec.ts$", 107 | "transform": { 108 | "^.+\\.(t|j)s$": "ts-jest" 109 | }, 110 | "coverageDirectory": "../coverage", 111 | "testEnvironment": "node" 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Nest-Api-Server 5 | 6 | 7 | 8 | 9 |
如果对你有帮助的话,帮忙点点star! ^_^
10 |
swagger地址
11 |
前端演示地址
12 |
前端git地址
13 |
打开console查看socket信息
14 | 15 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Redirect } from '@nestjs/common' 2 | import { AppService } from './app.service' 3 | import { NoAuth } from './guards/customize' 4 | 5 | @Controller() 6 | export class AppController { 7 | constructor(private readonly appService: AppService) {} 8 | 9 | @NoAuth() 10 | @Get() 11 | @Redirect('/public', 301) 12 | root(): string { 13 | return '' 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { EducationModule } from './module/person/education/education.module' 2 | import { ResumeModule } from './module/person/resume/resume.module' 3 | import { PersonModule } from './module/person/person.module' 4 | import { DynamictablesModule } from './module/dynamictables/dynamictables.module' 5 | import { FormModule } from './module/form/form.module' 6 | import { AdCodelistModule } from './module/ad-codelist/ad-codelist.module' 7 | import { RoleModule } from './module/role/role.module' 8 | import { Module } from '@nestjs/common' 9 | import { AppController } from './app.controller' 10 | import { AppService } from './app.service' 11 | import { UsersModule } from './module/users/users.module' 12 | import { AuthModule } from './module/auth/auth.module' 13 | import { Connection } from 'typeorm' 14 | import { APP_GUARD } from '@nestjs/core' 15 | import { RoleAuthGuard } from './guards/auth-guards' 16 | import { ServeStaticModule } from '@nestjs/serve-static' 17 | import { join } from 'path' 18 | import { TypeOrmModule } from '@nestjs/typeorm' 19 | import { UploadModule } from './module/upload/upload.module' 20 | import { EventsModule } from './events/events.module' 21 | import { ConfigModule, ConfigService } from '@nestjs/config' 22 | import customConfig from './config' 23 | import { AdCodelistTypeModule } from './module/ad-codelist-type/ad-codelist-type.module' 24 | 25 | @Module({ 26 | imports: [ 27 | ConfigModule.forRoot({ 28 | isGlobal: true, // 作用于全局 29 | load: [customConfig] // 加载自定义配置项 30 | }), 31 | TypeOrmModule.forRootAsync({ 32 | imports: [ConfigModule], // 数据库配置项依赖于ConfigModule,需在此引入 33 | useFactory: (configService: ConfigService) => 34 | configService.get('DATABASE_CONFIG'), 35 | inject: [ConfigService] // 记得注入服务,不然useFactory函数中获取不到ConfigService 36 | }), 37 | ServeStaticModule.forRoot({ 38 | rootPath: join(__dirname, '..', 'public'), 39 | exclude: ['/api*'] 40 | }), 41 | EventsModule, 42 | AuthModule, 43 | UsersModule, 44 | UploadModule, 45 | RoleModule, 46 | PersonModule, 47 | AdCodelistModule, 48 | AdCodelistTypeModule, 49 | FormModule, 50 | DynamictablesModule, 51 | ResumeModule, 52 | EducationModule 53 | ], 54 | controllers: [AppController], 55 | providers: [ 56 | AppService, 57 | { 58 | provide: APP_GUARD, 59 | useClass: RoleAuthGuard 60 | } 61 | ] 62 | }) 63 | export class AppModule { 64 | constructor(private readonly connection: Connection) {} 65 | } 66 | -------------------------------------------------------------------------------- /src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common' 2 | 3 | @Injectable() 4 | export class AppService {} 5 | -------------------------------------------------------------------------------- /src/config/constants.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: 设置jwt相关参数 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月06 16:10:49 6 | */ 7 | export const jwtConstants = { 8 | secret: 'shinobi7414', // 秘钥 9 | time: '24h' 10 | } 11 | -------------------------------------------------------------------------------- /src/config/env/development.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: 数据库配置文件 https://www.bookstack.cn/read/TypeORM-0.2.20-zh/connection-options.md 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年09月15 14:16:42 6 | */ 7 | import { join } from 'path' 8 | 9 | export default { 10 | // 端口 11 | port: parseInt(process.env.PORT, 10) || 3000, 12 | // 是否开启swagger 13 | enableSwagger: true, 14 | // 数据库配置 15 | DATABASE_CONFIG: { 16 | type: 'mysql', 17 | host: 'localhost', 18 | port: 3306, 19 | username: 'root', 20 | password: 'root', 21 | database: 'nest', 22 | charset: 'utf8mb4', 23 | entities: [join(__dirname, '..', '..', '/entities/*{.ts,.js}')], 24 | synchronize: true, // 是否在每次应用程序启动时自动创建数据库架构 25 | logging: false, 26 | dateStrings: true, // 强制日期类型(TIMESTAMP,DATETIME,DATE)作为字符串返回,而不是转换为 JavaScript Date 对象 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /src/config/env/production.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: 数据库配置文件 https://www.bookstack.cn/read/TypeORM-0.2.20-zh/connection-options.md 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年09月15 14:16:42 6 | */ 7 | import { join } from 'path' 8 | 9 | export default { 10 | // 端口 11 | port: parseInt(process.env.PORT, 10) || 3000, 12 | // 是否开启swagger 13 | enableSwagger: true, 14 | // 数据库配置 15 | DATABASE_CONFIG: { 16 | type: 'mysql', 17 | host: 'localhost', 18 | port: 3306, 19 | username: 'root', 20 | password: '', 21 | database: 'nest', 22 | charset: 'utf8mb4', 23 | entities: [join(__dirname, '..', '..', '/entities/*{.ts,.js}')], 24 | synchronize: false, // 是否在每次应用程序启动时自动创建数据库架构 25 | logging: true, 26 | dateStrings: true // 强制日期类型(TIMESTAMP,DATETIME,DATE)作为字符串返回,而不是转换为 JavaScript Date 对象 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/config/env/test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: 数据库配置文件 https://www.bookstack.cn/read/TypeORM-0.2.20-zh/connection-options.md 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年09月15 14:16:42 6 | */ 7 | import { join } from 'path' 8 | 9 | export default { 10 | // 端口 11 | port: parseInt(process.env.PORT, 10) || 3000, 12 | // 是否开启swagger 13 | enableSwagger: true, 14 | // 数据库配置 15 | DATABASE_CONFIG: { 16 | type: 'mysql', 17 | host: 'localhost', 18 | port: 3306, 19 | username: 'root', 20 | password: '', 21 | database: 'nest', 22 | charset: 'utf8mb4', 23 | entities: [join(__dirname, '..', '..', '/entities/*{.ts,.js}')], 24 | synchronize: true, 25 | logging: true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/config/index.ts: -------------------------------------------------------------------------------- 1 | import developmentConfig from './env/development' 2 | import testConfig from './env/test' 3 | import productionConfig from './env/production' 4 | 5 | const configs = { 6 | development: developmentConfig, 7 | test: testConfig, 8 | production: productionConfig 9 | } 10 | const env = process.env.NODE_ENV || 'development' 11 | 12 | export default () => configs[env] 13 | -------------------------------------------------------------------------------- /src/config/log4js.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: log4j 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月06 16:14:34 6 | */ 7 | 8 | import * as path from 'path' 9 | const baseLogPath = path.resolve(__dirname, '../../logs') // 日志要写入哪个目录 10 | 11 | const log4jsConfig = { 12 | appenders: { 13 | console: { 14 | type: 'console' // 会打印到控制台 15 | }, 16 | access: { 17 | type: 'dateFile', // 会写入文件,并按照日期分类 18 | filename: `${baseLogPath}/access/access.log`, // 日志文件名,会命名为:access.20200320.log 19 | alwaysIncludePattern: true, 20 | pattern: 'yyyyMMdd', 21 | daysToKeep: 60, 22 | numBackups: 3, 23 | category: 'http', 24 | keepFileExt: true // 是否保留文件后缀 25 | }, 26 | app: { 27 | type: 'dateFile', 28 | filename: `${baseLogPath}/app-out/app.log`, 29 | alwaysIncludePattern: true, 30 | layout: { 31 | type: 'pattern', 32 | pattern: 33 | '{"date":"%d","level":"%p","category":"%c","host":"%h","pid":"%z","data":\'%m\'}' 34 | }, 35 | // 日志文件按日期(天)切割 36 | pattern: 'yyyyMMdd', 37 | daysToKeep: 60, 38 | // maxLogSize: 10485760, 39 | numBackups: 3, 40 | keepFileExt: true 41 | }, 42 | errorFile: { 43 | type: 'dateFile', 44 | filename: `${baseLogPath}/errors/error.log`, 45 | alwaysIncludePattern: true, 46 | layout: { 47 | type: 'pattern', 48 | pattern: 49 | '{"date":"%d","level":"%p","category":"%c","host":"%h","pid":"%z","data":\'%m\'}' 50 | }, 51 | // 日志文件按日期(天)切割 52 | pattern: 'yyyyMMdd', 53 | daysToKeep: 60, 54 | // maxLogSize: 10485760, 55 | numBackups: 3, 56 | keepFileExt: true 57 | }, 58 | errors: { 59 | type: 'logLevelFilter', 60 | level: 'ERROR', 61 | appender: 'errorFile' 62 | } 63 | }, 64 | categories: { 65 | default: { 66 | appenders: ['console', 'app', 'errors'], 67 | level: 'DEBUG' 68 | }, 69 | info: { appenders: ['console', 'app', 'errors'], level: 'info' }, 70 | access: { appenders: ['console', 'app', 'errors'], level: 'info' }, 71 | http: { appenders: ['access'], level: 'DEBUG' } 72 | }, 73 | pm2: true, // 使用 pm2 来管理项目时,打开 74 | pm2InstanceVar: 'INSTANCE_ID' // 会根据 pm2 分配的 id 进行区分,以免各进程在写日志时造成冲突 75 | } 76 | 77 | export default log4jsConfig 78 | -------------------------------------------------------------------------------- /src/core/code.enum.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: 状态码枚举 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月10 15:48:38 6 | */ 7 | export enum StatusCode { 8 | TIMEOUT = -1, // 系统繁忙 9 | SUCCESS = 200, // 成功 10 | BUSINESS_FAIL = 400, // 业务类错误 11 | USER_ID_INVALID = 10001 // 用户id无效 12 | } 13 | -------------------------------------------------------------------------------- /src/core/resultBean.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: ResultBean 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月10 15:56:42 6 | */ 7 | 8 | import { StatusCode } from './code.enum' 9 | 10 | export interface ResultBean { 11 | code: number 12 | message: string 13 | data: any 14 | } 15 | 16 | export class ResultGenerator { 17 | static success(data: any = {}, message = 'success'): ResultBean { 18 | const result: ResultBean = { 19 | code: StatusCode.SUCCESS, 20 | message, 21 | data 22 | } 23 | return result 24 | } 25 | 26 | static fail(code: number, message: string) { 27 | const result: ResultBean = { 28 | code, 29 | message, 30 | data: undefined 31 | } 32 | return result 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/core/transform.ts: -------------------------------------------------------------------------------- 1 | import { ValueTransformer } from 'typeorm' 2 | 3 | /* 4 | * @file: typeorm bit(1) => 转换为 true false 5 | https://github.com/typeorm/typeorm/issues/3875 6 | * @copyright: BoBo 7 | * @author: BoBo 8 | * @Date: 2020年09月07 10:59:00 9 | */ 10 | export class BoolBitTransformer implements ValueTransformer { 11 | // To db from typeorm 12 | to(value: boolean | null): Buffer | null { 13 | if (value === null) { 14 | return null 15 | } 16 | const res = new Buffer(1) 17 | res[0] = value ? 1 : 0 18 | return res 19 | } 20 | // From db to typeorm 21 | from(value: Buffer): boolean | null { 22 | if (value === null) { 23 | return null 24 | } 25 | return value[0] === 1 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/entities/AdCodelist.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity } from 'typeorm' 2 | 3 | @Entity('ad_codelist', { schema: 'nest' }) 4 | export class AdCodelist { 5 | @Column('varchar', { primary: true, name: 'id', comment: 'ID', length: 50 }) 6 | id: string 7 | 8 | @Column('text', { name: 'codeValue', nullable: true, comment: '字典值' }) 9 | codeValue: string | null 10 | 11 | @Column('varchar', { 12 | name: 'codeName', 13 | nullable: true, 14 | comment: '字典值描述', 15 | length: 100 16 | }) 17 | codeName: string | null 18 | 19 | @Column('varchar', { 20 | name: 'codeType', 21 | nullable: true, 22 | comment: '字典类型', 23 | length: 50 24 | }) 25 | codeType: string | null 26 | 27 | @Column('decimal', { 28 | name: 'codeOrder', 29 | nullable: true, 30 | comment: '排序', 31 | precision: 8, 32 | scale: 0 33 | }) 34 | codeOrder: string | null 35 | 36 | @Column('varchar', { 37 | name: 'remark', 38 | nullable: true, 39 | comment: '备注', 40 | length: 255 41 | }) 42 | remark: string | null 43 | 44 | @Column('timestamp', { 45 | name: 'timestamp', 46 | comment: '创建时间', 47 | default: () => 'CURRENT_TIMESTAMP' 48 | }) 49 | timestamp: Date 50 | } 51 | -------------------------------------------------------------------------------- /src/entities/AdCodelistType.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity } from 'typeorm' 2 | 3 | @Entity('ad_codelist_type', { schema: 'nest' }) 4 | export class AdCodelistType { 5 | @Column('varchar', { primary: true, name: 'id', comment: 'ID', length: 36 }) 6 | id: string 7 | 8 | @Column('varchar', { 9 | name: 'typeName', 10 | nullable: true, 11 | comment: '字典类型名称', 12 | length: 100, 13 | }) 14 | typeName: string | null 15 | 16 | @Column('decimal', { 17 | name: 'order', 18 | nullable: true, 19 | comment: '排序', 20 | precision: 8, 21 | scale: 0, 22 | }) 23 | order: string | null 24 | 25 | @Column('varchar', { 26 | name: 'remark', 27 | nullable: true, 28 | comment: '备注', 29 | length: 255, 30 | }) 31 | remark: string | null 32 | 33 | @Column('varchar', { 34 | name: 'parentId', 35 | nullable: true, 36 | comment: '父级ID', 37 | length: 36, 38 | }) 39 | parentId: string | null 40 | 41 | @Column('timestamp', { 42 | name: 'timestamp', 43 | comment: '创建时间', 44 | default: () => 'CURRENT_TIMESTAMP', 45 | }) 46 | timestamp: Date 47 | } 48 | -------------------------------------------------------------------------------- /src/entities/Dept.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity, Index } from 'typeorm' 2 | 3 | @Index('index_id', ['id'], { unique: true }) 4 | @Entity('dept', { schema: 'nest' }) 5 | export class Dept { 6 | @Column('varchar', { primary: true, name: 'id', length: 36 }) 7 | id: string 8 | 9 | @Column('varchar', { 10 | name: 'name', 11 | nullable: true, 12 | comment: '部门名称', 13 | length: 255 14 | }) 15 | name: string | null 16 | 17 | @Column('int', { name: 'rank', nullable: true, comment: '排序码' }) 18 | rank: number | null 19 | 20 | @Column('varchar', { 21 | name: 'parentId', 22 | nullable: true, 23 | comment: '上级ID', 24 | length: 36 25 | }) 26 | parentId: string | null 27 | 28 | @Column('timestamp', { 29 | name: 'timestamp', 30 | comment: '创建时间', 31 | default: () => 'CURRENT_TIMESTAMP' 32 | }) 33 | timestamp: Date 34 | } 35 | -------------------------------------------------------------------------------- /src/entities/Dynamictables.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity } from 'typeorm' 2 | 3 | @Entity('dynamictables', { schema: 'nest' }) 4 | export class Dynamictables { 5 | @Column('char', { primary: true, name: 'id', length: 36 }) 6 | id: string 7 | 8 | @Column('varchar', { 9 | name: 'tableName', 10 | nullable: true, 11 | comment: '表名', 12 | length: 255 13 | }) 14 | tableName: string | null 15 | 16 | @Column('text', { name: 'formJson', nullable: true, comment: '数据' }) 17 | formJson: string | null 18 | 19 | @Column('text', { name: 'position', nullable: true, comment: '使用位置' }) 20 | position: string | null 21 | 22 | @Column('timestamp', { 23 | name: 'timestamp', 24 | comment: '创建时间', 25 | default: () => 'CURRENT_TIMESTAMP' 26 | }) 27 | timestamp: Date 28 | } 29 | -------------------------------------------------------------------------------- /src/entities/Form.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity } from 'typeorm' 2 | 3 | @Entity('form', { schema: 'nest' }) 4 | export class Form { 5 | @Column('char', { primary: true, name: 'id', length: 36 }) 6 | id: string 7 | 8 | @Column('varchar', { 9 | name: 'tableName', 10 | nullable: true, 11 | comment: '表名', 12 | length: 255 13 | }) 14 | tableName: string | null 15 | 16 | @Column('longtext', { name: 'formJson', nullable: true, comment: '数据' }) 17 | formJson: string | null 18 | 19 | @Column('text', { name: 'position', nullable: true, comment: '使用位置' }) 20 | position: string | null 21 | 22 | @Column('timestamp', { 23 | name: 'timestamp', 24 | comment: '创建时间', 25 | default: () => 'CURRENT_TIMESTAMP' 26 | }) 27 | timestamp: Date 28 | } 29 | -------------------------------------------------------------------------------- /src/entities/Person.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity } from 'typeorm' 2 | 3 | @Entity('person', { schema: 'nest' }) 4 | export class Person { 5 | @Column('char', { primary: true, name: 'id', comment: '主键', length: 36 }) 6 | id: string 7 | 8 | @Column('varchar', { 9 | name: 'personname', 10 | nullable: true, 11 | comment: '姓名', 12 | length: 255 13 | }) 14 | personname: string | null 15 | 16 | @Column('varchar', { 17 | name: 'deptname', 18 | nullable: true, 19 | comment: '所在部门', 20 | length: 255 21 | }) 22 | deptname: string | null 23 | 24 | @Column('varchar', { 25 | name: 'salary', 26 | nullable: true, 27 | comment: '薪资', 28 | length: 255 29 | }) 30 | salary: string | null 31 | 32 | @Column('varchar', { 33 | name: 'post', 34 | nullable: true, 35 | comment: '岗位', 36 | length: 255 37 | }) 38 | post: string | null 39 | 40 | @Column('varchar', { 41 | name: 'level', 42 | nullable: true, 43 | comment: '职级', 44 | length: 255 45 | }) 46 | level: string | null 47 | 48 | @Column('datetime', { name: 'timestamp', nullable: true, comment: '时间戳' }) 49 | timestamp: Date | null 50 | 51 | @Column('varchar', { 52 | name: 'jobtime', 53 | nullable: true, 54 | comment: '入职时间', 55 | length: 255 56 | }) 57 | jobtime: string | null 58 | 59 | @Column('varchar', { 60 | name: 'jobno', 61 | nullable: true, 62 | comment: '工号', 63 | length: 255 64 | }) 65 | jobno: string | null 66 | 67 | @Column('varchar', { 68 | name: 'education', 69 | nullable: true, 70 | comment: '文化程度', 71 | length: 255 72 | }) 73 | education: string | null 74 | 75 | @Column('varchar', { 76 | name: 'major', 77 | nullable: true, 78 | comment: '专业', 79 | length: 255 80 | }) 81 | major: string | null 82 | 83 | @Column('varchar', { 84 | name: 'mobile', 85 | nullable: true, 86 | comment: '联系方式', 87 | length: 100 88 | }) 89 | mobile: string | null 90 | 91 | @Column('varchar', { 92 | name: 'birthdate', 93 | nullable: true, 94 | comment: '出生年月', 95 | length: 100 96 | }) 97 | birthdate: string | null 98 | 99 | @Column('varchar', { 100 | name: 'sex', 101 | nullable: true, 102 | comment: '性别', 103 | length: 10 104 | }) 105 | sex: string | null 106 | 107 | @Column('varchar', { 108 | name: 'avatar', 109 | nullable: true, 110 | comment: '头像', 111 | length: 255 112 | }) 113 | avatar: string | null 114 | } 115 | -------------------------------------------------------------------------------- /src/entities/PersonEducation.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity } from 'typeorm' 2 | 3 | @Entity('person_education', { schema: 'nest' }) 4 | export class PersonEducation { 5 | @Column('char', { primary: true, name: 'id', length: 36 }) 6 | id: string 7 | 8 | @Column('varchar', { name: 'personid', nullable: true, length: 255 }) 9 | personid: string | null 10 | 11 | @Column('varchar', { 12 | name: 'time', 13 | nullable: true, 14 | comment: '起止时间', 15 | length: 255 16 | }) 17 | time: string | null 18 | 19 | @Column('varchar', { 20 | name: 'school', 21 | nullable: true, 22 | comment: '学校', 23 | length: 255 24 | }) 25 | school: string | null 26 | 27 | @Column('varchar', { 28 | name: 'type', 29 | nullable: true, 30 | comment: '学校类型', 31 | length: 255 32 | }) 33 | type: string | null 34 | 35 | @Column('text', { name: 'remark', nullable: true, comment: '备注' }) 36 | remark: string | null 37 | 38 | @Column('datetime', { name: 'timestamp', nullable: true }) 39 | timestamp: Date | null 40 | } 41 | -------------------------------------------------------------------------------- /src/entities/PersonResume.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity } from 'typeorm' 2 | 3 | @Entity('person_resume', { schema: 'nest' }) 4 | export class PersonResume { 5 | @Column('char', { primary: true, name: 'id', length: 36 }) 6 | id: string 7 | 8 | @Column('varchar', { name: 'personid', nullable: true, length: 255 }) 9 | personid: string | null 10 | 11 | @Column('varchar', { 12 | name: 'time', 13 | nullable: true, 14 | comment: '起止时间', 15 | length: 255 16 | }) 17 | time: string | null 18 | 19 | @Column('varchar', { 20 | name: 'workunit', 21 | nullable: true, 22 | comment: '工作单位', 23 | length: 255 24 | }) 25 | workunit: string | null 26 | 27 | @Column('varchar', { 28 | name: 'workduty', 29 | nullable: true, 30 | comment: '职务', 31 | length: 255 32 | }) 33 | workduty: string | null 34 | 35 | @Column('text', { name: 'remark', nullable: true, comment: '备注' }) 36 | remark: string | null 37 | 38 | @Column('datetime', { name: 'timestamp', nullable: true }) 39 | timestamp: Date | null 40 | } 41 | -------------------------------------------------------------------------------- /src/entities/Role.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity } from 'typeorm' 2 | 3 | @Entity('role', { schema: 'nest' }) 4 | export class Role { 5 | @Column('char', { primary: true, name: 'id', length: 36 }) 6 | id: string 7 | 8 | @Column('text', { name: 'roleName', nullable: true, comment: '角色名' }) 9 | roleName: string | null 10 | 11 | @Column('text', { name: 'roleAuthName', nullable: true, comment: '权限' }) 12 | roleAuthName: string | null 13 | 14 | @Column('longtext', { 15 | name: 'roleAuthNameDict', 16 | nullable: true, 17 | comment: '权限名称' 18 | }) 19 | roleAuthNameDict: string | null 20 | 21 | @Column('int', { name: 'rank', nullable: true, comment: '排序' }) 22 | rank: number | null 23 | 24 | @Column('timestamp', { 25 | name: 'timestamp', 26 | comment: '创建时间', 27 | default: () => 'CURRENT_TIMESTAMP' 28 | }) 29 | timestamp: Date 30 | } 31 | -------------------------------------------------------------------------------- /src/entities/Users.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity, Index } from 'typeorm' 2 | 3 | @Index('index_id', ['id'], {}) 4 | @Index('index_username', ['userName'], {}) 5 | @Index('index_deptid', ['deptId'], {}) 6 | @Entity('users', { schema: 'nest' }) 7 | export class Users { 8 | @Column('varchar', { primary: true, name: 'id', length: 36 }) 9 | id: string 10 | 11 | @Column('varchar', { 12 | name: 'userName', 13 | nullable: true, 14 | comment: '用户名', 15 | length: 50, 16 | }) 17 | userName: string | null 18 | 19 | @Column('varchar', { name: 'deptId', nullable: true, length: 36 }) 20 | deptId: string | null 21 | 22 | @Column('varchar', { name: 'roleId', nullable: true, length: 36 }) 23 | roleId: string | null 24 | 25 | @Column('varchar', { 26 | name: 'password', 27 | nullable: true, 28 | comment: '密码', 29 | length: 50, 30 | }) 31 | password: string | null 32 | 33 | @Column('varchar', { 34 | name: 'realName', 35 | nullable: true, 36 | comment: '真实姓名', 37 | length: 20, 38 | }) 39 | realName: string | null 40 | 41 | @Column('int', { 42 | name: 'rank', 43 | nullable: true, 44 | comment: '排序码', 45 | default: () => "'0'", 46 | }) 47 | rank: number | null 48 | 49 | @Column('longtext', { name: 'photo', nullable: true, comment: '照片' }) 50 | photo: string | null 51 | 52 | @Column('timestamp', { 53 | name: 'timestamp', 54 | comment: '创建时间', 55 | default: () => 'CURRENT_TIMESTAMP', 56 | }) 57 | timestamp: Date 58 | } 59 | -------------------------------------------------------------------------------- /src/events/events.gateway.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: webSocket https://docs.nestjs.cn/6/websockets?id=websocket 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月13 16:48:08 6 | */ 7 | import { 8 | SubscribeMessage, 9 | WebSocketGateway, 10 | WsResponse, 11 | WebSocketServer, 12 | OnGatewayConnection, 13 | OnGatewayInit, 14 | OnGatewayDisconnect 15 | } from '@nestjs/websockets' 16 | import { Observable, of } from 'rxjs' 17 | 18 | let num = 0 19 | 20 | @WebSocketGateway(8080) 21 | export class EventsGateway 22 | implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect { 23 | @WebSocketServer() server 24 | 25 | // 初始化 26 | afterInit() {} 27 | 28 | // 连接 29 | handleConnection() {} 30 | 31 | // 断开连接 32 | handleDisconnect() {} 33 | 34 | // 订阅消息事件 35 | @SubscribeMessage('message') 36 | handleEvent(client: any): Observable> { 37 | // 通知当前client message 38 | this.server.emit('message', new Date().toLocaleString()) 39 | num++ 40 | console.log(`有一位用户链接!> ${num}`) 41 | client.on('disconnect', () => { 42 | num-- 43 | console.log(`有人离开了...> ${num}`) 44 | }) 45 | 46 | return of({ event: 'message', data: '233' }) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/events/events.module.ts: -------------------------------------------------------------------------------- 1 | import { Module, Global } from '@nestjs/common' 2 | import { EventsGateway } from './events.gateway' 3 | @Global() 4 | @Module({ 5 | providers: [EventsGateway], 6 | exports: [EventsGateway] 7 | }) 8 | export class EventsModule {} 9 | -------------------------------------------------------------------------------- /src/filter/any-exception.filter.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: 全局异常拦截 http exception -> any exception 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月06 16:57:04 6 | */ 7 | 8 | import { 9 | ExceptionFilter, 10 | Catch, 11 | ArgumentsHost, 12 | HttpException, 13 | HttpStatus 14 | } from '@nestjs/common' 15 | import { Logger } from '../utils/log4js' 16 | 17 | @Catch() 18 | export class AllExceptionsFilter implements ExceptionFilter { 19 | catch(exception: unknown, host: ArgumentsHost) { 20 | const ctx = host.switchToHttp() 21 | const response = ctx.getResponse() 22 | const request = ctx.getRequest() 23 | 24 | const status = 25 | exception instanceof HttpException 26 | ? exception.getStatus() 27 | : HttpStatus.INTERNAL_SERVER_ERROR 28 | 29 | const logFormat = ` <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 30 | Request original url: ${request.originalUrl} 31 | Method: ${request.method} 32 | IP: ${request.ip} 33 | Status code: ${status} 34 | Response: ${exception} \n <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 35 | ` 36 | Logger.error(logFormat) 37 | response.status(status).json({ 38 | code: status, 39 | message: `Service Error: ${exception}`, 40 | data: null 41 | }) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/filter/api-exception.filter.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: api异常拦截 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月10 15:55:37 6 | */ 7 | import { StatusCode } from './../core/code.enum' 8 | import { HttpException, HttpStatus } from '@nestjs/common' 9 | 10 | export class ApiException extends HttpException { 11 | private errorMessage: string 12 | private errorCode: StatusCode 13 | 14 | constructor( 15 | errorMessage: string, 16 | errorCode: StatusCode, 17 | statusCode: HttpStatus 18 | ) { 19 | super(errorMessage, statusCode) 20 | this.errorMessage = errorMessage 21 | this.errorCode = errorCode 22 | } 23 | 24 | getErrorCode(): StatusCode { 25 | return this.errorCode 26 | } 27 | 28 | getErrorMessage(): string { 29 | return this.errorMessage 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/filter/http-exception.filter.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: 全局http异常拦截 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月10 15:51:14 6 | */ 7 | import { 8 | ExceptionFilter, 9 | ArgumentsHost, 10 | Catch, 11 | HttpException 12 | } from '@nestjs/common' 13 | import { ApiException } from './api-exception.filter' 14 | 15 | @Catch(HttpException) 16 | export class HttpExceptionFilter implements ExceptionFilter { 17 | catch(exception, host: ArgumentsHost) { 18 | const ctx = host.switchToHttp() 19 | const response = ctx.getResponse() 20 | const status = exception.getStatus() 21 | if (exception instanceof ApiException) { 22 | response.status(status).json({ 23 | code: exception.getErrorCode(), 24 | message: exception.getErrorMessage(), 25 | data: null 26 | }) 27 | } else { 28 | response.status(status).json({ 29 | code: status, 30 | data: new Date().toLocaleDateString(), 31 | message: exception.message 32 | }) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/guards/auth-guards.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: 全局jwt guard 3 | 接口上添加@NoAuth() 则跳过校验 4 | * @copyright: BoBo 5 | * @author: BoBo 6 | * @Date: 2020年08月07 14:53:52 7 | */ 8 | import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common' 9 | import { Observable } from 'rxjs' 10 | import { Reflector } from '@nestjs/core' 11 | import { AuthGuard, IAuthGuard } from '@nestjs/passport' 12 | 13 | @Injectable() 14 | export class RoleAuthGuard implements CanActivate { 15 | constructor(private readonly reflector: Reflector) {} 16 | canActivate( 17 | context: ExecutionContext 18 | ): boolean | Promise | Observable { 19 | // 在这里取metadata中的no-auth,得到的会是一个bool 20 | const noAuth = this.reflector.get('no-auth', context.getHandler()) 21 | const guard = RoleAuthGuard.getAuthGuard(noAuth) 22 | return typeof guard === 'boolean' ? guard : guard.canActivate(context) //执行所选策略Guard的canActivate方法 23 | } 24 | 25 | // @NoAuth() 则表示直接放行不校验token 26 | private static getAuthGuard(noAuth: boolean): IAuthGuard | boolean { 27 | if (noAuth) { 28 | return true 29 | } else { 30 | return new (AuthGuard('jwt'))() 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/guards/customize.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common' 2 | 3 | export const NoAuth = () => SetMetadata('no-auth', true) 4 | -------------------------------------------------------------------------------- /src/guards/jwt-auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common' 2 | import { AuthGuard } from '@nestjs/passport' 3 | 4 | @Injectable() 5 | export class JwtAuthGuard extends AuthGuard('jwt') {} 6 | -------------------------------------------------------------------------------- /src/guards/jwt.strategy.ts: -------------------------------------------------------------------------------- 1 | // src/logical/auth/jwt.strategy.ts 2 | import { ExtractJwt, Strategy } from 'passport-jwt' 3 | import { PassportStrategy } from '@nestjs/passport' 4 | import { Injectable } from '@nestjs/common' 5 | import { jwtConstants } from '../config/constants' 6 | 7 | @Injectable() 8 | export class JwtStrategy extends PassportStrategy(Strategy) { 9 | constructor() { 10 | super({ 11 | jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), 12 | ignoreExpiration: false, 13 | secretOrKey: jwtConstants.secret 14 | }) 15 | } 16 | 17 | // JWT验证 - Step 4: 被守卫调用 18 | async validate(payload: any) { 19 | console.log(`JWT验证 - Step 4: 被守卫调用`) 20 | return { 21 | userId: payload.userID, 22 | userName: payload.userName, 23 | realName: payload.realName, 24 | roleID: payload.roleID, 25 | deptID: payload.deptID 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/interceptor/transform.interceptor.ts: -------------------------------------------------------------------------------- 1 | // src/interceptor/transform.interceptor.ts 2 | import { 3 | CallHandler, 4 | ExecutionContext, 5 | Injectable, 6 | NestInterceptor 7 | } from '@nestjs/common' 8 | import { Observable } from 'rxjs' 9 | import { map } from 'rxjs/operators' 10 | import { Logger } from '../utils/log4js' 11 | 12 | @Injectable() 13 | export class TransformInterceptor implements NestInterceptor { 14 | intercept(context: ExecutionContext, next: CallHandler): Observable { 15 | const req = context.getArgByIndex(1).req 16 | return next.handle().pipe( 17 | map(data => { 18 | const logFormat = ` <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 19 | Request original url: ${req.originalUrl} 20 | Method: ${req.method} 21 | IP: ${req.ip} 22 | User: ${JSON.stringify(req.user)} 23 | Response data:\n ${JSON.stringify(data.data)} 24 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<` 25 | Logger.info(logFormat) 26 | Logger.access(logFormat) 27 | return data 28 | }) 29 | ) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: main.ts 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月06 16:10:49 6 | */ 7 | import { NestFactory } from '@nestjs/core' 8 | import { NestExpressApplication } from '@nestjs/platform-express' 9 | import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger' 10 | import { AppModule } from './app.module' 11 | import { logger } from './middleware/logger.middleware' 12 | import * as express from 'express' 13 | import { TransformInterceptor } from './interceptor/transform.interceptor' 14 | import { AllExceptionsFilter } from './filter/any-exception.filter' 15 | import * as compression from 'compression' 16 | import { HttpExceptionFilter } from './filter/http-exception.filter' 17 | import { join } from 'path' 18 | 19 | async function bootstrap() { 20 | const app = await NestFactory.create(AppModule, { 21 | cors: true, 22 | }) 23 | app.enableCors({ 24 | origin: true, 25 | }) 26 | // helmet安全 27 | // app.use(helmet()); 28 | const options = new DocumentBuilder() 29 | .setTitle('Nestjs Swagger') 30 | .setDescription('API description') 31 | .setVersion('1.0') 32 | .addTag('cats') 33 | .build() 34 | const document = SwaggerModule.createDocument(app, options) 35 | SwaggerModule.setup('api', app, document) 36 | app.use(express.json()) // For parsing application/json 37 | app.use(express.urlencoded({ extended: true })) // For parsing application/x-www-form-urlencoded 38 | // 监听所有的请求路由,并打印日志 39 | app.use(logger) 40 | // 使用全局拦截器打印出参 41 | app.useGlobalInterceptors(new TransformInterceptor()) 42 | // 全局异常 43 | app.useGlobalFilters(new AllExceptionsFilter()) 44 | // 开启gzip 45 | app.use(compression()) 46 | 47 | app.useGlobalFilters(new HttpExceptionFilter()) 48 | 49 | // 配置静态资源 50 | app.useStaticAssets(join(__dirname, '../public', '/'), { 51 | prefix: '/', 52 | setHeaders: (res) => { 53 | res.set('Cache-Control', 'max-age=2592000') 54 | }, 55 | }) 56 | 57 | await app.listen(process.env.PORT || 7788) 58 | } 59 | bootstrap() 60 | -------------------------------------------------------------------------------- /src/middleware/logger.middleware.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: log中间件 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月06 16:17:03 6 | */ 7 | import { Injectable, NestMiddleware } from '@nestjs/common' 8 | import { Request, Response } from 'express' 9 | import { Logger } from '../utils/log4js' 10 | 11 | @Injectable() 12 | export class LoggerMiddleware implements NestMiddleware { 13 | use(req: Request, res: Response, next: () => void) { 14 | const code = res.statusCode // 响应状态码 15 | // 组装日志信息 16 | const logFormat = `Method: ${req.method} \n Request original url: ${req.originalUrl} \n IP: ${req.ip} \n Status code: ${code} \n` 17 | // 根据状态码,进行日志类型区分 18 | if (code >= 500) { 19 | Logger.error(logFormat) 20 | } else if (code >= 400) { 21 | Logger.warn(logFormat) 22 | } else { 23 | Logger.access(logFormat) 24 | Logger.log(logFormat) 25 | } 26 | next() 27 | } 28 | } 29 | 30 | // 函数式中间件 31 | export function logger(req: Request, res: Response, next: () => any) { 32 | const code = res.statusCode // 响应状态码 33 | next() 34 | // 组装日志信息 35 | const logFormat = ` >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 36 | Request original url: ${req.originalUrl} 37 | Method: ${req.method} 38 | IP: ${req.ip} 39 | Status code: ${code} 40 | Parmas: ${JSON.stringify(req.params)} 41 | Query: ${JSON.stringify(req.query)} 42 | Body: ${JSON.stringify( 43 | req.body 44 | )} \n >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 45 | ` 46 | // 根据状态码,进行日志类型区分 47 | if (code >= 500) { 48 | Logger.error(logFormat) 49 | } else if (code >= 400) { 50 | Logger.warn(logFormat) 51 | } else { 52 | Logger.access(logFormat) 53 | Logger.log(logFormat) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/module/ad-codelist-type/ad-codelist-type.controller.ts: -------------------------------------------------------------------------------- 1 | import { AdCodelistTypeService } from './ad-codelist-type.service' 2 | import { Controller } from '@nestjs/common' 3 | import { ApiHeader } from '@nestjs/swagger' 4 | import { AdCodelistType } from '@/entities/AdCodelistType' 5 | import { BaseController } from 'src/module/base/base.controller' 6 | 7 | @ApiHeader({ 8 | name: '字典类型设置', 9 | description: '字典类型设置', 10 | }) 11 | @Controller('ad_codelist_type') 12 | export class AdCodelistController extends BaseController { 13 | constructor(private adCodelistTypeService: AdCodelistTypeService) { 14 | super(adCodelistTypeService) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/module/ad-codelist-type/ad-codelist-type.module.ts: -------------------------------------------------------------------------------- 1 | import { AdCodelistController } from './ad-codelist-type.controller' 2 | import { AdCodelistTypeService } from './ad-codelist-type.service' 3 | import { Module } from '@nestjs/common' 4 | import { TypeOrmModule } from '@nestjs/typeorm' 5 | import { AdCodelistType } from '@/entities/AdCodelistType' 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([AdCodelistType])], 9 | providers: [AdCodelistTypeService], 10 | controllers: [AdCodelistController], 11 | exports: [AdCodelistTypeService], 12 | }) 13 | export class AdCodelistTypeModule {} 14 | -------------------------------------------------------------------------------- /src/module/ad-codelist-type/ad-codelist-type.service.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from 'src/module/base/base.service' 2 | import { Injectable } from '@nestjs/common' 3 | import { InjectRepository } from '@nestjs/typeorm' 4 | import { Repository } from 'typeorm' 5 | import { AdCodelistType } from '@/entities/AdCodelistType' 6 | 7 | @Injectable() 8 | export class AdCodelistTypeService extends BaseService { 9 | adCodelistTypeRepository: Repository 10 | constructor( 11 | @InjectRepository(AdCodelistType) 12 | adCodelistTypeRepository: Repository, 13 | ) { 14 | super(adCodelistTypeRepository) 15 | this.adCodelistTypeRepository = adCodelistTypeRepository 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/module/ad-codelist/ad-codelist.controller.ts: -------------------------------------------------------------------------------- 1 | import { ResultGenerator } from './../../core/resultBean' 2 | import { AdCodelistService } from './ad-codelist.service' 3 | import { Controller, Post, Body } from '@nestjs/common' 4 | import { ApiHeader } from '@nestjs/swagger' 5 | import { AdCodelist } from '@/entities/AdCodelist' 6 | import { BaseController } from 'src/module/base/base.controller' 7 | import { NoAuth } from 'src/guards/customize' 8 | 9 | @ApiHeader({ 10 | name: '字典设置', 11 | description: '字典设置', 12 | }) 13 | @Controller('ad_codelist') 14 | export class AdCodelistController extends BaseController { 15 | constructor(private adCodelistService: AdCodelistService) { 16 | super(adCodelistService) 17 | } 18 | 19 | @NoAuth() 20 | @Post('list') 21 | public async list(@Body() body) { 22 | // const code = await this.adCodelistService.repository 23 | // .createQueryBuilder('code') 24 | // .leftJoinAndSelect(AdCodelistType, 'type', 'type.id = code.codeType') 25 | // .select('code.*') 26 | // .addSelect('type.codeName', 'typeName') 27 | // .getRawMany(); 28 | // const code = await this.adCodelistService.repository.query('select t.*,c.codeName as typeName from ad_codelist t join ad_codelist_type c on (t.codeType = c.id)') 29 | return ResultGenerator.success(await this.adCodelistService.find(body)) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/module/ad-codelist/ad-codelist.module.ts: -------------------------------------------------------------------------------- 1 | import { AdCodelistController } from './ad-codelist.controller' 2 | import { AdCodelistService } from './ad-codelist.service' 3 | import { Module } from '@nestjs/common' 4 | import { TypeOrmModule } from '@nestjs/typeorm' 5 | import { AdCodelist } from '@/entities/AdCodelist' 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([AdCodelist])], 9 | providers: [AdCodelistService], 10 | controllers: [AdCodelistController], 11 | exports: [AdCodelistService], 12 | }) 13 | export class AdCodelistModule {} 14 | -------------------------------------------------------------------------------- /src/module/ad-codelist/ad-codelist.service.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from 'src/module/base/base.service' 2 | import { Injectable } from '@nestjs/common' 3 | import { InjectRepository } from '@nestjs/typeorm' 4 | import { Repository } from 'typeorm' 5 | import { AdCodelist } from '@/entities/AdCodelist' 6 | 7 | @Injectable() 8 | export class AdCodelistService extends BaseService { 9 | adCodelistRepository: Repository 10 | constructor( 11 | @InjectRepository(AdCodelist) adCodelistRepository: Repository, 12 | ) { 13 | super(adCodelistRepository) 14 | this.adCodelistRepository = adCodelistRepository 15 | } 16 | 17 | async find(body) { 18 | const qb = this.adCodelistRepository 19 | .createQueryBuilder('code') 20 | .innerJoin('ad_codelist_type', 'type', 'type.id = code.codeType') 21 | this.splitSql(qb, body) 22 | qb.select('code.*') 23 | .addSelect('type.typeName', 'typeName') 24 | .addOrderBy('code.codeOrder', 'ASC') // 此处返回字段为 type_typeName 25 | 26 | const list = await qb.getRawMany() 27 | const total = await qb.getCount() 28 | return { 29 | list, 30 | total, 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/module/auth/auth.module.ts: -------------------------------------------------------------------------------- 1 | import { RoleModule } from './../role/role.module' 2 | import { JwtStrategy } from './../../guards/jwt.strategy' 3 | import { UsersModule } from '../users/users.module' 4 | import { Module, Global } from '@nestjs/common' 5 | import { AuthService } from './auth.service' 6 | import { PassportModule } from '@nestjs/passport' 7 | import { JwtModule } from '@nestjs/jwt' 8 | import { jwtConstants } from 'src/config/constants' 9 | import { DeptModule } from '../dept/dept.module' 10 | 11 | @Global() 12 | @Module({ 13 | imports: [ 14 | PassportModule.register({ defaultStrategy: 'jwt' }), 15 | JwtModule.register({ 16 | secret: jwtConstants.secret, 17 | signOptions: { expiresIn: jwtConstants.time } // token 过期时效 18 | }), 19 | UsersModule, 20 | DeptModule, 21 | RoleModule 22 | ], 23 | providers: [AuthService, JwtStrategy], 24 | exports: [AuthService] 25 | }) 26 | export class AuthModule {} 27 | -------------------------------------------------------------------------------- /src/module/auth/auth.service.ts: -------------------------------------------------------------------------------- 1 | import { DeptService } from './../dept/dept.service' 2 | import { RoleService } from './../role/role.service' 3 | import { Users } from './../../entities/Users' 4 | import { UsersService } from '../users/users.service' 5 | import { Injectable } from '@nestjs/common' 6 | import { JwtService } from '@nestjs/jwt' 7 | 8 | @Injectable() 9 | export class AuthService { 10 | user 11 | constructor( 12 | private readonly usersService: UsersService, 13 | private readonly roleService: RoleService, 14 | private readonly deptService: DeptService, 15 | private readonly jwtService: JwtService 16 | ) {} 17 | 18 | // 校验用户信息 19 | async validateUser(username: string, password: string): Promise { 20 | const user = await this.usersService.findByUserName(username) 21 | if (user) { 22 | if (password === user.password) { 23 | // 密码正确 24 | return { 25 | code: 200, 26 | user 27 | } 28 | } else { 29 | // 密码错误 30 | return { 31 | code: 800, 32 | user: null 33 | } 34 | } 35 | } 36 | // 查无此人 37 | return { 38 | code: 801, 39 | user: null 40 | } 41 | } 42 | 43 | // 签发jwt 44 | async certificate(user: Users) { 45 | // 查找当前用户角色/部门 46 | const role = await this.roleService.findById(user.roleId) 47 | const dept = await this.deptService.findById(user.deptId) 48 | 49 | const payload = { 50 | userName: user.userName, 51 | userID: user.id, 52 | deptID: user.deptId, 53 | realName: user.realName, 54 | roleID: user.roleId, 55 | roleName: role.roleName, 56 | deptName: dept.name, 57 | roleAuthName: role.roleAuthName, 58 | photo: '' 59 | } 60 | const token = this.jwtService.sign(payload) 61 | this.user = { 62 | ...payload, 63 | photo: user.photo 64 | } 65 | return token 66 | } 67 | 68 | getUser() { 69 | return this.user 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/module/base/base.controller.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: BaseController 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月10 11:45:59 6 | */ 7 | import { BaseService } from './base.service' 8 | import { Body, Controller, Post, Query } from '@nestjs/common' 9 | import { ResultGenerator } from './../../core/resultBean' 10 | 11 | @Controller() 12 | export abstract class BaseController { 13 | protected constructor(protected service: BaseService) {} 14 | 15 | @Post('list') 16 | public async list(@Body() body) { 17 | return ResultGenerator.success(await this.service.find(body)) 18 | } 19 | 20 | @Post('add') 21 | public async add(@Body() data: T) { 22 | return ResultGenerator.success(await this.service.add(data), '新增成功') 23 | } 24 | 25 | @Post('update') 26 | public async update(@Body() data: T) { 27 | return ResultGenerator.success(await this.service.update(data), '更新成功') 28 | } 29 | 30 | @Post('detail') 31 | public async detail(@Query() id: string) { 32 | return ResultGenerator.success(await this.service.findById(id)) 33 | } 34 | 35 | @Post('delete') 36 | public async delete(@Query() id: string) { 37 | return ResultGenerator.success(await this.service.delete(id), '删除成功') 38 | } 39 | 40 | /** 41 | * 批量删除接口 42 | * @param id 43 | */ 44 | @Post('deleteByIds') 45 | public async deleteByIds(@Body() id: string[]) { 46 | return ResultGenerator.success( 47 | await this.service.deleteByIds(id), 48 | '删除成功' 49 | ) 50 | } 51 | 52 | /** 53 | * tree 接口 54 | */ 55 | @Post('tree') 56 | public async tree() { 57 | return ResultGenerator.success(await this.service.tree()) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/module/base/base.service.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: BaseService 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月10 10:44:35 6 | */ 7 | import { Injectable } from '@nestjs/common' 8 | import * as jwt from 'jsonwebtoken' 9 | import { jwtConstants } from '../../config/constants' 10 | 11 | const guid = require('uuid') 12 | const dayjs = require('dayjs') 13 | 14 | import { BaseEntity, Repository, SelectQueryBuilder } from 'typeorm' 15 | import { InjectRepository } from '@nestjs/typeorm' 16 | 17 | interface searchType { 18 | field: string 19 | operator: string 20 | value: any 21 | } 22 | 23 | interface SearchCondition { 24 | orderCondition: string 25 | searchCondition: searchType[] 26 | pageIndex: number 27 | pageSize: number 28 | } 29 | 30 | @Injectable() 31 | export abstract class BaseService { 32 | public repository: Repository 33 | constructor(@InjectRepository(BaseEntity) repository: Repository) { 34 | this.repository = repository 35 | } 36 | 37 | /** 38 | * 获取当前token携带信息 39 | * jwt token 40 | * @param authorization 41 | */ 42 | getUserInfoFromToken(authorization) { 43 | if (!authorization) return null 44 | 45 | const token = authorization.split(' ')[1] 46 | const user = jwt.verify(token, jwtConstants.secret) 47 | return user 48 | } 49 | 50 | // 新增接口 51 | async add(entity: T) { 52 | const obj = JSON.parse(JSON.stringify(entity as any)) 53 | 54 | // id为null则自动生成guid 55 | if (!obj.id) { 56 | obj.id = guid.v4() 57 | } 58 | obj.timestamp = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss') 59 | 60 | await this.repository.insert(obj) 61 | return entity 62 | } 63 | // 更新接口 64 | async update(entity: T) { 65 | const obj = JSON.parse(JSON.stringify(entity as any)) 66 | 67 | // 此处大坑,如果有更好的方案欢迎PR! 68 | // 更新的时候去除伪列 (此处由于ts的类型检查不带入运行时,不会自动映射属性,否则数据库没有这个字段会报错) 69 | Object.keys(obj).forEach((k) => { 70 | // 去除伪列, 伪列格式默认为 表名_字段名 例如保存users表 (dept_name) 详见/users/list方法 71 | if (k.includes('_')) { 72 | delete obj[k] 73 | } 74 | }) 75 | // 更新时间戳 76 | obj.timestamp = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss') 77 | 78 | await this.repository.update(obj.id, obj) 79 | return (entity as any).id 80 | } 81 | 82 | // 删除接口 83 | async delete(id: string) { 84 | await this.repository.delete(id) 85 | return id 86 | } 87 | 88 | // 批量删除接口 89 | async deleteByIds(ids: string[]) { 90 | await this.repository.delete(ids) 91 | return ids 92 | } 93 | 94 | // 查询ById接口 95 | async findById(id: string) { 96 | // ts bug https://github.com/typeorm/typeorm/issues/8939 97 | const result = await this.repository.findOneBy({ 98 | id, 99 | } as any) 100 | return result 101 | } 102 | 103 | // tree接口 104 | async tree() { 105 | const result = await this.repository.find() 106 | // 此处默认顶层parentId 为 0 , 自行修改 107 | return toTree(result, '0') 108 | } 109 | 110 | async find(args: SearchCondition) { 111 | const qb = this.repository.createQueryBuilder() 112 | 113 | // 拼接sql 114 | this.splitSql(qb, args) 115 | 116 | const [list, total] = await qb.getManyAndCount() 117 | 118 | return { 119 | list, 120 | total, 121 | } 122 | } 123 | 124 | splitSql(qb: SelectQueryBuilder, args: SearchCondition) { 125 | const { pageIndex, pageSize, searchCondition, orderCondition } = args 126 | if (Array.isArray(searchCondition) && searchCondition.length > 0) { 127 | // 拼接高级查询条件 128 | this.getSearchCondition(searchCondition, qb) 129 | } 130 | // 拼接order条件 131 | if (orderCondition && orderCondition.includes(' ')) { 132 | const [field, order] = orderCondition.split(' ') 133 | qb.orderBy(field, order.toUpperCase() as any) 134 | } 135 | // 拼接分页条件 136 | // 若pageIndex,pageSize = 0,0 137 | // 则默认查询全部 138 | if (pageIndex && pageSize && pageIndex + pageSize > 1) { 139 | qb.skip((pageIndex - 1) * pageSize) 140 | qb.take(pageSize) 141 | } 142 | } 143 | 144 | getSearchCondition(searchCondition: searchType[], qb: SelectQueryBuilder) { 145 | // 一键搜 查询方式为orlike拼接 146 | const orLike = searchCondition.find((item) => item.operator === 'orlike') 147 | if (orLike) { 148 | const fields = orLike.field.split(',') 149 | fields.forEach((field) => { 150 | qb.orWhere(`${field} LIKE :value`, { value: `%${orLike.value}%` }) 151 | }) 152 | } else { 153 | // ... 154 | qb.where('1 = 1') 155 | searchCondition.forEach((obj) => { 156 | const { value, operator, field } = obj 157 | switch (operator) { 158 | case 'eq': 159 | qb.where(`${field} = :value`, { value }) 160 | break 161 | case 'neq': 162 | qb.where(`${field} <> :value`, { value }) 163 | break 164 | case 'notNull': 165 | qb.where(`${field} is not null`) 166 | break 167 | case 'isNull': 168 | qb.where(`${field} is null`) 169 | break 170 | case 'gt': 171 | qb.where(`${field} > :value`, { value }) 172 | break 173 | case 'lt': 174 | qb.where(`${field} < :value`, { value }) 175 | break 176 | case 'egt': 177 | qb.where(`${field} >= :value`, { value }) 178 | break 179 | case 'elt': 180 | qb.where(`${field} <= :value`, { value }) 181 | break 182 | case 'like': 183 | qb.where(`${field} LIKE :value`, { value: `%${value}%` }) 184 | break 185 | default: 186 | break 187 | } 188 | }) 189 | } 190 | } 191 | } 192 | 193 | /** 194 | * 递归遍历list,返回tree结构 195 | */ 196 | function toTree(list, parId) { 197 | const len = list.length 198 | function loop(parId) { 199 | const res = [] 200 | for (let i = 0; i < len; i++) { 201 | const item = list[i] 202 | if (item.parentId === parId) { 203 | item.children = loop(item.id) 204 | res.push(item) 205 | } 206 | } 207 | return res 208 | } 209 | return loop(parId) 210 | } 211 | -------------------------------------------------------------------------------- /src/module/dept/dept.controller.ts: -------------------------------------------------------------------------------- 1 | import { DeptService } from './dept.service' 2 | import { Controller } from '@nestjs/common' 3 | import { ApiHeader } from '@nestjs/swagger' 4 | import { BaseController } from '../base/base.controller' 5 | import { Dept } from '@/entities/Dept' 6 | 7 | @ApiHeader({ 8 | name: 'dept Module', 9 | description: '部门设置', 10 | }) 11 | @Controller('dept') 12 | export class DeptController extends BaseController { 13 | constructor(private deptService: DeptService) { 14 | super(deptService) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/module/dept/dept.module.ts: -------------------------------------------------------------------------------- 1 | import { DeptController } from './dept.controller' 2 | import { DeptService } from './dept.service' 3 | import { Module } from '@nestjs/common' 4 | import { TypeOrmModule } from '@nestjs/typeorm' 5 | import { Dept } from '@/entities/Dept' 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Dept])], 9 | providers: [DeptService], 10 | controllers: [DeptController], 11 | exports: [DeptService], 12 | }) 13 | export class DeptModule {} 14 | -------------------------------------------------------------------------------- /src/module/dept/dept.service.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from 'src/module/base/base.service' 2 | import { Injectable } from '@nestjs/common' 3 | import { InjectRepository } from '@nestjs/typeorm' 4 | import { Repository } from 'typeorm' 5 | import { Dept } from '@/entities/Dept' 6 | 7 | @Injectable() 8 | export class DeptService extends BaseService { 9 | deptRepository: Repository 10 | constructor(@InjectRepository(Dept) deptRepository: Repository) { 11 | super(deptRepository) 12 | this.deptRepository = deptRepository 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/module/dynamictables/dynamictables.controller.ts: -------------------------------------------------------------------------------- 1 | import { DynamictablesService } from './dynamictables.service' 2 | import { Controller, Post, Query } from '@nestjs/common' 3 | import { ApiHeader } from '@nestjs/swagger' 4 | import { Dynamictables } from '@/entities/Dynamictables' 5 | import { BaseController } from 'src/module/base/base.controller' 6 | import { ResultGenerator } from 'src/core/resultBean' 7 | 8 | @ApiHeader({ 9 | name: '表格管理', 10 | description: '表单管理', 11 | }) 12 | @Controller('dynamictables') 13 | export class DynamictablesController extends BaseController { 14 | constructor(private dynamictablesService: DynamictablesService) { 15 | super(dynamictablesService) 16 | } 17 | @Post('detail') 18 | async getFormJson(@Query() query) { 19 | const table = await this.dynamictablesService.repository.findOne({ 20 | where: { 21 | tableName: query.tablename, 22 | }, 23 | }) 24 | return ResultGenerator.success(table) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/module/dynamictables/dynamictables.module.ts: -------------------------------------------------------------------------------- 1 | import { DynamictablesController } from './dynamictables.controller' 2 | import { DynamictablesService } from './dynamictables.service' 3 | import { Module } from '@nestjs/common' 4 | import { TypeOrmModule } from '@nestjs/typeorm' 5 | import { Dynamictables } from '@/entities/Dynamictables' 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Dynamictables])], 9 | providers: [DynamictablesService], 10 | controllers: [DynamictablesController], 11 | exports: [DynamictablesService], 12 | }) 13 | export class DynamictablesModule {} 14 | -------------------------------------------------------------------------------- /src/module/dynamictables/dynamictables.service.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from 'src/module/base/base.service' 2 | import { Injectable } from '@nestjs/common' 3 | import { InjectRepository } from '@nestjs/typeorm' 4 | import { Repository } from 'typeorm' 5 | import { Dynamictables } from '@/entities/Dynamictables' 6 | 7 | @Injectable() 8 | export class DynamictablesService extends BaseService { 9 | DynamictablesRepository: Repository 10 | constructor( 11 | @InjectRepository(Dynamictables) 12 | DynamictablesRepository: Repository, 13 | ) { 14 | super(DynamictablesRepository) 15 | this.DynamictablesRepository = DynamictablesRepository 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/module/form/form.controller.ts: -------------------------------------------------------------------------------- 1 | import { ResultGenerator } from './../../core/resultBean' 2 | import { FormService } from './form.service' 3 | import { Controller, Post, Query } from '@nestjs/common' 4 | import { ApiHeader } from '@nestjs/swagger' 5 | import { Form } from '@/entities/Form' 6 | import { BaseController } from 'src/module/base/base.controller' 7 | 8 | @ApiHeader({ 9 | name: '表单管理', 10 | description: '表单管理', 11 | }) 12 | @Controller('form') 13 | export class FormController extends BaseController
{ 14 | constructor(private formService: FormService) { 15 | super(formService) 16 | } 17 | 18 | @Post('detail') 19 | async getFormJson(@Query() query) { 20 | const form = await this.formService.repository.findOne({ 21 | where: { 22 | tableName: query.tablename, 23 | }, 24 | }) 25 | return ResultGenerator.success(form) 26 | } 27 | 28 | /** 29 | * 获取数据库中所有表名 30 | */ 31 | @Post('getTables') 32 | async getTables() { 33 | const tables = await this.formService.repository.query( 34 | 'select table_name from information_schema.TABLES where TABLE_SCHEMA="nest"', 35 | ) 36 | return ResultGenerator.success(tables) 37 | } 38 | 39 | /** 40 | * 获取某个表中所有字段,不包括带id的,以及isdeleted timestamp字段 41 | * @param query 42 | */ 43 | @Post('getKey') 44 | async getFormKey(@Query() query) { 45 | const sql = 46 | 'select COLUMN_NAME,DATA_TYPE,COLUMN_COMMENT from information_schema.COLUMNS where table_name = "' + 47 | query.tablename + 48 | '"' + 49 | 'and table_schema = "nest" and COLUMN_NAME not like "%id%" and COLUMN_NAME not like "%isdeleted%" and COLUMN_NAME not like "%timestamp%"' 50 | const keys = await this.formService.repository.query(sql) 51 | return ResultGenerator.success(keys) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/module/form/form.module.ts: -------------------------------------------------------------------------------- 1 | import { FormController } from './form.controller' 2 | import { FormService } from './form.service' 3 | import { Module } from '@nestjs/common' 4 | import { TypeOrmModule } from '@nestjs/typeorm' 5 | import { Form } from '@/entities/Form' 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Form])], 9 | providers: [FormService], 10 | controllers: [FormController], 11 | exports: [FormService], 12 | }) 13 | export class FormModule {} 14 | -------------------------------------------------------------------------------- /src/module/form/form.service.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from 'src/module/base/base.service' 2 | import { Injectable } from '@nestjs/common' 3 | import { InjectRepository } from '@nestjs/typeorm' 4 | import { Repository } from 'typeorm' 5 | import { Form } from '@/entities/Form' 6 | 7 | @Injectable() 8 | export class FormService extends BaseService { 9 | FormRepository: Repository 10 | constructor(@InjectRepository(Form) FormRepository: Repository) { 11 | super(FormRepository) 12 | this.FormRepository = FormRepository 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/module/person/education/education.controller.ts: -------------------------------------------------------------------------------- 1 | import { EducationService } from './education.service' 2 | import { Controller } from '@nestjs/common' 3 | import { ApiHeader } from '@nestjs/swagger' 4 | import { BaseController } from '../../base/base.controller' 5 | import { PersonEducation } from '@/entities/PersonEducation' 6 | 7 | @ApiHeader({ 8 | name: 'Education Module', 9 | description: '教育经历模块', 10 | }) 11 | @Controller('Education') 12 | export class EducationController extends BaseController { 13 | constructor(private educationService: EducationService) { 14 | super(educationService) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/module/person/education/education.module.ts: -------------------------------------------------------------------------------- 1 | import { EducationController } from './education.controller' 2 | import { EducationService } from './education.service' 3 | import { Module } from '@nestjs/common' 4 | import { TypeOrmModule } from '@nestjs/typeorm' 5 | import { PersonEducation } from '@/entities/PersonEducation' 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([PersonEducation])], 9 | providers: [EducationService], 10 | controllers: [EducationController], 11 | exports: [EducationService], 12 | }) 13 | export class EducationModule {} 14 | -------------------------------------------------------------------------------- /src/module/person/education/education.service.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from '../../base/base.service' 2 | import { Injectable } from '@nestjs/common' 3 | import { InjectRepository } from '@nestjs/typeorm' 4 | import { Repository } from 'typeorm' 5 | import { PersonEducation } from '@/entities/PersonEducation' 6 | 7 | @Injectable() 8 | export class EducationService extends BaseService { 9 | EducationRepository: Repository 10 | constructor( 11 | @InjectRepository(PersonEducation) 12 | EducationRepository: Repository, 13 | ) { 14 | super(EducationRepository) 15 | this.EducationRepository = EducationRepository 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/module/person/person.controller.ts: -------------------------------------------------------------------------------- 1 | import { PersonService } from './person.service' 2 | import { Controller } from '@nestjs/common' 3 | import { ApiHeader } from '@nestjs/swagger' 4 | import { BaseController } from '../base/base.controller' 5 | import { Person } from '@/entities/Person' 6 | 7 | @ApiHeader({ 8 | name: 'Person Module', 9 | description: '员工管理', 10 | }) 11 | @Controller('Person') 12 | export class PersonController extends BaseController { 13 | constructor(private personService: PersonService) { 14 | super(personService) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/module/person/person.module.ts: -------------------------------------------------------------------------------- 1 | import { PersonController } from './person.controller' 2 | import { PersonService } from './person.service' 3 | import { Module } from '@nestjs/common' 4 | import { TypeOrmModule } from '@nestjs/typeorm' 5 | import { Person } from '@/entities/Person' 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Person])], 9 | providers: [PersonService], 10 | controllers: [PersonController], 11 | exports: [PersonService], 12 | }) 13 | export class PersonModule {} 14 | -------------------------------------------------------------------------------- /src/module/person/person.service.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from 'src/module/base/base.service' 2 | import { Injectable } from '@nestjs/common' 3 | import { InjectRepository } from '@nestjs/typeorm' 4 | import { Repository } from 'typeorm' 5 | import { Person } from '@/entities/Person' 6 | 7 | @Injectable() 8 | export class PersonService extends BaseService { 9 | PersonRepository: Repository 10 | constructor(@InjectRepository(Person) PersonRepository: Repository) { 11 | super(PersonRepository) 12 | this.PersonRepository = PersonRepository 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/module/person/resume/resume.controller.ts: -------------------------------------------------------------------------------- 1 | import { ResumeService } from './resume.service' 2 | import { Controller } from '@nestjs/common' 3 | import { ApiHeader } from '@nestjs/swagger' 4 | import { BaseController } from '../../base/base.controller' 5 | import { PersonResume } from '@/entities/PersonResume' 6 | 7 | @ApiHeader({ 8 | name: 'Resume Module', 9 | description: '员工工作履历', 10 | }) 11 | @Controller('Resume') 12 | export class ResumeController extends BaseController { 13 | constructor(private resumeService: ResumeService) { 14 | super(resumeService) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/module/person/resume/resume.module.ts: -------------------------------------------------------------------------------- 1 | import { ResumeController } from './resume.controller' 2 | import { ResumeService } from './resume.service' 3 | import { Module } from '@nestjs/common' 4 | import { TypeOrmModule } from '@nestjs/typeorm' 5 | import { PersonResume } from '@/entities/PersonResume' 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([PersonResume])], 9 | providers: [ResumeService], 10 | controllers: [ResumeController], 11 | exports: [ResumeService], 12 | }) 13 | export class ResumeModule {} 14 | -------------------------------------------------------------------------------- /src/module/person/resume/resume.service.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from 'src/module/base/base.service' 2 | import { Injectable } from '@nestjs/common' 3 | import { InjectRepository } from '@nestjs/typeorm' 4 | import { Repository } from 'typeorm' 5 | import { PersonResume } from '@/entities/PersonResume' 6 | 7 | @Injectable() 8 | export class ResumeService extends BaseService { 9 | ResumeRepository: Repository 10 | constructor( 11 | @InjectRepository(PersonResume) ResumeRepository: Repository, 12 | ) { 13 | super(ResumeRepository) 14 | this.ResumeRepository = ResumeRepository 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/module/role/role.controller.ts: -------------------------------------------------------------------------------- 1 | import { RoleService } from './role.service' 2 | import { Controller } from '@nestjs/common' 3 | import { ApiHeader } from '@nestjs/swagger' 4 | import { BaseController } from '../base/base.controller' 5 | import { Role } from '@/entities/Role' 6 | 7 | @ApiHeader({ 8 | name: 'role Module', 9 | description: '角色设置', 10 | }) 11 | @Controller('role') 12 | export class RoleController extends BaseController { 13 | constructor(private roleService: RoleService) { 14 | super(roleService) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/module/role/role.module.ts: -------------------------------------------------------------------------------- 1 | import { RoleController } from './role.controller' 2 | import { RoleService } from './role.service' 3 | import { Module } from '@nestjs/common' 4 | import { TypeOrmModule } from '@nestjs/typeorm' 5 | import { Role } from '@/entities/Role' 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Role])], 9 | providers: [RoleService], 10 | controllers: [RoleController], 11 | exports: [RoleService], 12 | }) 13 | export class RoleModule {} 14 | -------------------------------------------------------------------------------- /src/module/role/role.service.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from 'src/module/base/base.service' 2 | import { Injectable } from '@nestjs/common' 3 | import { InjectRepository } from '@nestjs/typeorm' 4 | import { Repository } from 'typeorm' 5 | import { Role } from '@/entities/Role' 6 | 7 | @Injectable() 8 | export class RoleService extends BaseService { 9 | roleRepository: Repository 10 | constructor(@InjectRepository(Role) roleRepository: Repository) { 11 | super(roleRepository) 12 | this.roleRepository = roleRepository 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/module/upload/upload.controller.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: 文件上传模块 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月10 15:47:05 6 | */ 7 | import { Post, Controller, UploadedFile, UseInterceptors } from '@nestjs/common' 8 | import { FileInterceptor } from '@nestjs/platform-express' 9 | import { ResultGenerator } from 'src/core/resultBean' 10 | import { ResultBean } from './../../core/resultBean' 11 | 12 | @Controller('file') 13 | @UseInterceptors(FileInterceptor('file')) 14 | export class UploadController { 15 | constructor() {} 16 | @Post('/upload') 17 | uploadFile(@UploadedFile() file): ResultBean { 18 | return ResultGenerator.success('/affix/' + file.filename, '上传成功') 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/module/upload/upload.module.ts: -------------------------------------------------------------------------------- 1 | import { UploadController } from './upload.controller' 2 | import { Module } from '@nestjs/common' 3 | import { UploadService } from './upload.service' 4 | import { MulterModule } from '@nestjs/platform-express' 5 | // import dayjs = require('dayjs') 6 | import { diskStorage } from 'multer' 7 | const guid = require('uuid') 8 | const path = require('path') 9 | @Module({ 10 | imports: [ 11 | // 此处为上传模块全局配置 12 | // 参考 https://www.jianshu.com/p/28f8dd9a732e 13 | MulterModule.register({ 14 | storage: diskStorage({ 15 | //自定义路径,此处默认保存在项目根目录下的upload文件夹 16 | destination: path.join(__dirname, '../../../public/affix', '/'), 17 | filename: (req, file, cb) => { 18 | // 自定义文件名 19 | const filename = `${guid.v4()}.${file.mimetype.split('/')[1]}` 20 | return cb(null, filename) 21 | // 原始文件名 22 | // return cb(null, file.originalname); 23 | }, 24 | }), 25 | limits: { 26 | fieldSize: 1024 * 1024, 27 | fileSize: 1024 * 1024, 28 | }, 29 | }), 30 | ], 31 | providers: [UploadService], 32 | controllers: [UploadController], 33 | }) 34 | export class UploadModule {} 35 | -------------------------------------------------------------------------------- /src/module/upload/upload.service.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: 文件上传 service 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月10 15:47:19 6 | */ 7 | import { Injectable, HttpStatus } from '@nestjs/common' 8 | import { join, resolve } from 'path' 9 | import { createWriteStream } from 'fs' 10 | import { ApiException } from './../../filter/api-exception.filter' 11 | import { StatusCode } from './../../core/code.enum' 12 | import { ResultGenerator, ResultBean } from './../../core/resultBean' 13 | import { dirExists } from 'src/utils/file' 14 | const uploadBasePath: string = join(__dirname, '../../../', 'public/uploads') 15 | 16 | @Injectable() 17 | export class UploadService { 18 | /** 19 | * 单个文件传输 20 | * @param file 21 | */ 22 | public async uploadFile(file): Promise { 23 | try { 24 | await dirExists(uploadBasePath) 25 | const { originalname, buffer } = file 26 | const fullName = new Date().toDateString() + '-' + originalname 27 | const filePath = resolve(uploadBasePath, fullName) 28 | const writeStream = createWriteStream(filePath) 29 | writeStream.write(buffer) 30 | return ResultGenerator.success('上传成功') 31 | } catch (err) { 32 | throw new ApiException( 33 | '文件上传错误', 34 | StatusCode.BUSINESS_FAIL, 35 | HttpStatus.FORBIDDEN 36 | ) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/module/users/users.controller.ts: -------------------------------------------------------------------------------- 1 | import { EventsGateway } from './../../events/events.gateway' 2 | import { NoAuth } from 'src/guards/customize' 3 | import { AuthService } from '../auth/auth.service' 4 | import { UsersService } from './users.service' 5 | import { 6 | Controller, 7 | Post, 8 | Body, 9 | Get, 10 | Query, 11 | Req, 12 | UploadedFile, 13 | UseInterceptors, 14 | } from '@nestjs/common' 15 | import { ApiHeader } from '@nestjs/swagger' 16 | import { BaseController } from '../base/base.controller' 17 | import { Users } from '@/entities/Users' 18 | import { ResultGenerator } from 'src/core/resultBean' 19 | import { FileInterceptor } from '@nestjs/platform-express' 20 | 21 | @ApiHeader({ 22 | name: 'users Module', 23 | description: '用户设置', 24 | }) 25 | @Controller('users') 26 | export class UsersController extends BaseController { 27 | constructor( 28 | private usersService: UsersService, 29 | private readonly authService: AuthService, 30 | private readonly eventsGateway: EventsGateway, 31 | ) { 32 | super(usersService) 33 | } 34 | 35 | @NoAuth() 36 | @Post('login') 37 | async login(@Body() loginParmas: { username: string, password: string }) { 38 | const authResult = await this.authService.validateUser( 39 | loginParmas.username, 40 | loginParmas.password, 41 | ) 42 | switch (authResult.code) { 43 | case 200: 44 | const token = await this.authService.certificate(authResult.user) 45 | return ResultGenerator.success({ token }, '登录成功') 46 | case 800: 47 | return ResultGenerator.fail(800, '密码错误') 48 | case 801: 49 | return ResultGenerator.fail(801, '用户名不存在') 50 | } 51 | } 52 | 53 | /** 54 | * 获取用户身份信息 55 | */ 56 | @Post('userinfo') 57 | async userInfo(@Req() req) { 58 | // decoded token 信息 59 | const user = this.usersService.getUserInfoFromToken( 60 | req.headers.authorization, 61 | ) 62 | return ResultGenerator.success(user) 63 | } 64 | 65 | /** 66 | * socket.io 向客户端发送消息 67 | */ 68 | @NoAuth() 69 | @Get('emit') 70 | async emit(@Query() params) { 71 | this.eventsGateway.server.emit('message', JSON.stringify(params)) 72 | return 'emit' 73 | } 74 | 75 | /** 76 | * 头像上传 77 | * @param body 78 | */ 79 | @Post('uploadImage') 80 | @UseInterceptors(FileInterceptor('file')) // 此处file对应 field name 81 | async uploadImage(@Body() body, @UploadedFile() file) { 82 | const { userid } = body 83 | const base64str = Buffer.from(file.buffer, 'binary').toString('base64') // base64编码 84 | const user = await this.usersService.findById(userid) 85 | if (user) { 86 | user.photo = `data:image/jpg;base64,${base64str}` 87 | this.usersService.update(user) 88 | return ResultGenerator.success('', '上传成功') 89 | } else { 90 | return ResultGenerator.fail(400, '用户不存在') 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/module/users/users.module.ts: -------------------------------------------------------------------------------- 1 | import { UsersController } from './users.controller' 2 | import { UsersService } from './users.service' 3 | import { Module } from '@nestjs/common' 4 | import { TypeOrmModule } from '@nestjs/typeorm' 5 | import { Users } from '@/entities/Users' 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Users])], 9 | providers: [UsersService], 10 | controllers: [UsersController], 11 | exports: [UsersService], 12 | }) 13 | export class UsersModule {} 14 | -------------------------------------------------------------------------------- /src/module/users/users.service.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from 'src/module/base/base.service' 2 | import { Injectable } from '@nestjs/common' 3 | import { InjectRepository } from '@nestjs/typeorm' 4 | import { Repository } from 'typeorm' 5 | import { Users } from '@/entities/Users' 6 | 7 | @Injectable() 8 | export class UsersService extends BaseService { 9 | usersRepository: Repository 10 | constructor(@InjectRepository(Users) usersRepository: Repository) { 11 | super(usersRepository) 12 | this.usersRepository = usersRepository 13 | } 14 | 15 | /** 16 | * 用户名查询是否存在该用户 17 | * @param userName 用户名 18 | */ 19 | findByUserName(userName: string) { 20 | return this.usersRepository.findOneBy({ 21 | userName, 22 | }) 23 | } 24 | 25 | /** 26 | * 用户名查询是否存在该用户 27 | * @param userName 用户名 28 | */ 29 | async getUserInfo(userName: string) { 30 | const user = await this.usersRepository 31 | .createQueryBuilder('users') 32 | .innerJoin('users.deptid', 'dept') 33 | .where('users.userName = :userName', { userName }) 34 | .getOne() 35 | return user 36 | } 37 | 38 | async find(body) { 39 | const qb = this.usersRepository 40 | .createQueryBuilder('users') 41 | .innerJoin('dept', 'dept', 'dept.id = users.deptid') 42 | .innerJoin('role', 'role', 'role.id = users.roleid') 43 | this.splitSql(qb, body) 44 | qb.select('users.*') 45 | .addSelect('dept.name', 'deptName') // 此处不定义alias 返回字段为 -> dept_name 46 | .addSelect('role.roleName', 'roleName') // 同理返回-> role_roleName 47 | 48 | const list = await qb.getRawMany() 49 | const total = await qb.getCount() 50 | return { 51 | list, 52 | total, 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/utils/file.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import path from 'path' 3 | /** 4 | * 读取路径信息 5 | * @param {string} path 路径 6 | */ 7 | function getStat(path) { 8 | return new Promise(resolve => { 9 | fs.stat(path, (err, stats) => { 10 | if (err) { 11 | resolve(false) 12 | } else { 13 | resolve(stats) 14 | } 15 | }) 16 | }) 17 | } 18 | 19 | /** 20 | * 创建路径 21 | * @param {string} dir 路径 22 | */ 23 | function mkdir(dir) { 24 | return new Promise(resolve => { 25 | fs.mkdir(dir, err => { 26 | if (err) { 27 | resolve(false) 28 | } else { 29 | resolve(true) 30 | } 31 | }) 32 | }) 33 | } 34 | 35 | /** 36 | * 路径是否存在,不存在则创建 37 | * @param {string} dir 路径 38 | */ 39 | export async function dirExists(dir) { 40 | console.log(dir) 41 | 42 | const isExists: any = await getStat(dir) 43 | console.log(isExists) 44 | 45 | //如果该路径且不是文件,返回true 46 | if (isExists && isExists.isDirectory()) { 47 | return true 48 | } else if (isExists) { 49 | //如果该路径存在但是文件,返回false 50 | return false 51 | } 52 | //如果该路径不存在 53 | const tempDir = path.parse(dir).dir //拿到上级路径 54 | //递归判断,如果上级目录也不存在,则会代码会在此处继续循环执行,直到目录存在 55 | const status = await dirExists(tempDir) 56 | let mkdirStatus 57 | if (status) { 58 | mkdirStatus = await mkdir(dir) 59 | } 60 | return mkdirStatus 61 | } 62 | -------------------------------------------------------------------------------- /src/utils/log4js.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @file: log4js util 3 | * @copyright: BoBo 4 | * @author: BoBo 5 | * @Date: 2020年08月06 16:15:32 6 | */ 7 | import * as Path from 'path' 8 | import * as Log4js from 'log4js' 9 | import * as Util from 'util' 10 | import * as Moment from 'moment' // 处理时间的工具 11 | import * as StackTrace from 'stacktrace-js' 12 | import Chalk from 'chalk' 13 | import config from '../config/log4js' 14 | 15 | // 日志级别 16 | export enum LoggerLevel { 17 | ALL = 'ALL', 18 | MARK = 'MARK', 19 | TRACE = 'TRACE', 20 | DEBUG = 'DEBUG', 21 | INFO = 'INFO', 22 | WARN = 'WARN', 23 | ERROR = 'ERROR', 24 | FATAL = 'FATAL', 25 | OFF = 'OFF' 26 | } 27 | 28 | // 内容跟踪类 29 | export class ContextTrace { 30 | constructor( 31 | public readonly context: string, 32 | public readonly path?: string, 33 | public readonly lineNumber?: number, 34 | public readonly columnNumber?: number 35 | ) {} 36 | } 37 | 38 | Log4js.addLayout('Awesome-nest', (logConfig: any) => { 39 | return (logEvent: Log4js.LoggingEvent): string => { 40 | let moduleName = '' 41 | let position = '' 42 | 43 | // 日志组装 44 | const messageList: string[] = [] 45 | logEvent.data.forEach((value: any) => { 46 | if (value instanceof ContextTrace) { 47 | moduleName = value.context 48 | // 显示触发日志的坐标(行,列) 49 | if (value.lineNumber && value.columnNumber) { 50 | position = `${value.lineNumber}, ${value.columnNumber}` 51 | } 52 | return 53 | } 54 | 55 | if (typeof value !== 'string') { 56 | value = Util.inspect(value, false, 3, true) 57 | } 58 | 59 | messageList.push(value) 60 | }) 61 | 62 | // 日志组成部分 63 | const messageOutput: string = messageList.join(' ') 64 | const positionOutput: string = position ? ` [${position}]` : '' 65 | const typeOutput = `[${logConfig.type}] ${logEvent.pid.toString()} - ` 66 | const dateOutput = `${Moment(logEvent.startTime).format( 67 | 'YYYY-MM-DD HH:mm:ss' 68 | )}` 69 | const moduleOutput: string = moduleName 70 | ? `[${moduleName}] ` 71 | : '[LoggerService] ' 72 | let levelOutput = `[${logEvent.level}] ${messageOutput}` 73 | 74 | // 根据日志级别,用不同颜色区分 75 | switch (logEvent.level.toString()) { 76 | case LoggerLevel.DEBUG: 77 | levelOutput = Chalk.green(levelOutput) 78 | break 79 | case LoggerLevel.INFO: 80 | levelOutput = Chalk.cyan(levelOutput) 81 | break 82 | case LoggerLevel.WARN: 83 | levelOutput = Chalk.yellow(levelOutput) 84 | break 85 | case LoggerLevel.ERROR: 86 | levelOutput = Chalk.red(levelOutput) 87 | break 88 | case LoggerLevel.FATAL: 89 | levelOutput = Chalk.hex('#DD4C35')(levelOutput) 90 | break 91 | default: 92 | levelOutput = Chalk.grey(levelOutput) 93 | break 94 | } 95 | 96 | return `${Chalk.green(typeOutput)}${dateOutput} ${Chalk.yellow( 97 | moduleOutput 98 | )}${levelOutput}${positionOutput}` 99 | } 100 | }) 101 | 102 | // 注入配置 103 | Log4js.configure(config) 104 | 105 | // 实例化 106 | const logger = Log4js.getLogger() 107 | logger.level = LoggerLevel.TRACE 108 | 109 | export class Logger { 110 | static trace(...args) { 111 | logger.trace(Logger.getStackTrace(), ...args) 112 | } 113 | 114 | static debug(...args) { 115 | logger.debug(Logger.getStackTrace(), ...args) 116 | } 117 | 118 | static log(...args) { 119 | logger.info(Logger.getStackTrace(), ...args) 120 | } 121 | 122 | static info(...args) { 123 | logger.info(Logger.getStackTrace(), ...args) 124 | } 125 | 126 | static warn(...args) { 127 | logger.warn(Logger.getStackTrace(), ...args) 128 | } 129 | 130 | static warning(...args) { 131 | logger.warn(Logger.getStackTrace(), ...args) 132 | } 133 | 134 | static error(...args) { 135 | logger.error(Logger.getStackTrace(), ...args) 136 | } 137 | 138 | static fatal(...args) { 139 | logger.fatal(Logger.getStackTrace(), ...args) 140 | } 141 | 142 | static access(...args) { 143 | const loggerCustom = Log4js.getLogger('http') 144 | loggerCustom.info(Logger.getStackTrace(), ...args) 145 | } 146 | 147 | // 日志追踪,可以追溯到哪个文件、第几行第几列 148 | static getStackTrace(deep = 2): string { 149 | const stackList: StackTrace.StackFrame[] = StackTrace.getSync() 150 | const stackInfo: StackTrace.StackFrame = stackList[deep] 151 | 152 | const lineNumber: number = stackInfo.lineNumber 153 | const columnNumber: number = stackInfo.columnNumber 154 | const fileName: string = stackInfo.fileName 155 | const basename: string = Path.basename(fileName) 156 | return `${basename}(line: ${lineNumber}, column: ${columnNumber}): \n` 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing' 2 | import { INestApplication } from '@nestjs/common' 3 | import * as request from 'supertest' 4 | import { AppModule } from './../src/app.module' 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication 8 | 9 | beforeEach(async () => { 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule] 12 | }).compile() 13 | 14 | app = moduleFixture.createNestApplication() 15 | await app.init() 16 | }) 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!') 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "es2017", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true, 14 | "skipLibCheck": true, 15 | "paths": { 16 | "@/*": ["src/*"] 17 | }, 18 | }, 19 | "exclude": ["node_modules"] 20 | } 21 | --------------------------------------------------------------------------------