From 74432bdadd7ac9f89aafdcaa00cf3376feb61acb Mon Sep 17 00:00:00 2001 From: COOL Date: Thu, 9 Jan 2025 17:14:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 8196 bytes .dockerignore | 18 - .editorconfig | 11 - .eslintrc.json | 30 - .gitattributes | 4 - .gitignore | 20 - .hintrc | 9 - .prettierrc.js | 3 - .vscode/config.code-snippets | 28 - .vscode/controller.code-snippets | 19 - .vscode/entity.code-snippets | 20 - .vscode/event.code-snippets | 21 - .vscode/middleware.code-snippets | 29 - .vscode/queue.code-snippets | 21 - .vscode/service.code-snippets | 33 - Dockerfile | 33 - LICENSE | 21 - README.md | 191 ---- bootstrap.js | 2 - cool/obfuscate.js | 70 -- docker-compose.yml | 40 - jest.config.js | 6 - package.json | 80 -- public/css/welcome.css | 89 -- public/favicon.ico | Bin 5837 -> 0 bytes public/js/welcome.js | 14 - public/uploads/说明.md | 1 - src/comm/utils.ts | 138 --- src/config/config.default.ts | 66 -- src/config/config.local.ts | 40 - src/config/config.prod.ts | 34 - src/configuration.ts | 60 -- src/interface.ts | 6 - src/modules/base/config.ts | 35 - src/modules/base/controller/admin/comm.ts | 99 -- src/modules/base/controller/admin/open.ts | 99 -- .../base/controller/admin/sys/department.ts | 27 - src/modules/base/controller/admin/sys/log.ts | 64 -- src/modules/base/controller/admin/sys/menu.ts | 46 - .../base/controller/admin/sys/param.ts | 34 - src/modules/base/controller/admin/sys/role.ts | 38 - src/modules/base/controller/admin/sys/user.ts | 30 - src/modules/base/controller/app/README.md | 1 - src/modules/base/controller/app/comm.ts | 72 -- src/modules/base/db.json | 103 --- src/modules/base/dto/login.ts | 21 - src/modules/base/entity/sys/conf.ts | 15 - src/modules/base/entity/sys/department.ts | 19 - src/modules/base/entity/sys/log.ts | 23 - src/modules/base/entity/sys/menu.ts | 47 - src/modules/base/entity/sys/param.ts | 27 - src/modules/base/entity/sys/role.ts | 31 - .../base/entity/sys/role_department.ts | 14 - src/modules/base/entity/sys/role_menu.ts | 14 - src/modules/base/entity/sys/user.ts | 54 -- src/modules/base/entity/sys/user_role.ts | 14 - src/modules/base/event/app.ts | 102 -- src/modules/base/event/menu.ts | 40 - src/modules/base/job/log.ts | 25 - src/modules/base/menu.json | 875 ------------------ src/modules/base/middleware/authority.ts | 185 ---- src/modules/base/middleware/log.ts | 26 - src/modules/base/service/sys/conf.ts | 39 - src/modules/base/service/sys/data.ts | 10 - src/modules/base/service/sys/department.ts | 124 --- src/modules/base/service/sys/log.ts | 62 -- src/modules/base/service/sys/login.ts | 251 ----- src/modules/base/service/sys/menu.ts | 463 --------- src/modules/base/service/sys/param.ts | 91 -- src/modules/base/service/sys/perms.ts | 90 -- src/modules/base/service/sys/role.ts | 136 --- src/modules/base/service/sys/user.ts | 235 ----- src/modules/demo/config.ts | 19 - src/modules/demo/controller/admin/goods.ts | 11 - src/modules/demo/controller/open/cache.ts | 37 - src/modules/demo/controller/open/event.ts | 27 - src/modules/demo/controller/open/goods.ts | 32 - src/modules/demo/controller/open/plugin.ts | 29 - src/modules/demo/controller/open/queue.ts | 49 - src/modules/demo/controller/open/rpc.ts | 29 - src/modules/demo/controller/open/sse.ts | 49 - .../demo/controller/open/transaction.ts | 14 - src/modules/demo/entity/goods.ts | 32 - src/modules/demo/event/comm.ts | 27 - src/modules/demo/queue/comm.ts | 20 - src/modules/demo/queue/getter.ts | 7 - src/modules/demo/queue/single.ts | 20 - src/modules/demo/service/cache.ts | 18 - src/modules/demo/service/goods.ts | 40 - src/modules/demo/service/rpc.ts | 70 -- src/modules/demo/service/transaction.ts | 23 - src/modules/dict/config.ts | 19 - src/modules/dict/controller/admin/info.ts | 30 - src/modules/dict/controller/admin/type.ts | 18 - src/modules/dict/controller/app/info.ts | 26 - src/modules/dict/db.json | 88 -- src/modules/dict/entity/info.ts | 26 - src/modules/dict/entity/type.ts | 14 - src/modules/dict/service/info.ts | 137 --- src/modules/dict/service/type.ts | 25 - src/modules/plugin/config.ts | 27 - src/modules/plugin/controller/admin/info.ts | 56 -- src/modules/plugin/entity/info.ts | 44 - src/modules/plugin/event/app.ts | 44 - src/modules/plugin/event/init.ts | 36 - src/modules/plugin/hooks/base.ts | 26 - src/modules/plugin/hooks/upload/index.ts | 122 --- src/modules/plugin/hooks/upload/interface.ts | 56 -- src/modules/plugin/interface.ts | 25 - src/modules/plugin/service/center.ts | 200 ---- src/modules/plugin/service/info.ts | 445 --------- src/modules/plugin/service/types.ts | 257 ----- src/modules/recycle/config.ts | 19 - src/modules/recycle/controller/admin/data.ts | 35 - src/modules/recycle/entity/data.ts | 32 - src/modules/recycle/event/data.ts | 21 - src/modules/recycle/schedule/data.ts | 32 - src/modules/recycle/service/data.ts | 84 -- src/modules/space/config.ts | 24 - src/modules/space/controller/admin/info.ts | 18 - src/modules/space/controller/admin/type.ts | 15 - src/modules/space/controller/说明.md | 1 - src/modules/space/entity/info.ts | 33 - src/modules/space/entity/type.ts | 14 - src/modules/space/service/info.ts | 30 - src/modules/space/service/type.ts | 28 - src/modules/task/config.ts | 18 - src/modules/task/controller/admin/info.ts | 67 -- src/modules/task/controller/说明.md | 1 - src/modules/task/db.json | 40 - src/modules/task/entity/info.ts | 56 -- src/modules/task/entity/log.ts | 18 - src/modules/task/event/app.ts | 17 - src/modules/task/middleware/task.ts | 31 - src/modules/task/queue/task.ts | 30 - src/modules/task/service/demo.ts | 19 - src/modules/task/service/info.ts | 361 -------- src/modules/user/config.ts | 34 - src/modules/user/controller/admin/address.ts | 13 - src/modules/user/controller/admin/info.ts | 15 - src/modules/user/controller/app/address.ts | 39 - src/modules/user/controller/app/comm.ts | 25 - src/modules/user/controller/app/info.ts | 65 -- src/modules/user/controller/app/login.ts | 107 --- src/modules/user/entity/address.ts | 34 - src/modules/user/entity/info.ts | 34 - src/modules/user/entity/wx.ts | 40 - src/modules/user/event/app.ts | 56 -- src/modules/user/middleware/app.ts | 96 -- src/modules/user/service/address.ts | 63 -- src/modules/user/service/info.ts | 124 --- src/modules/user/service/login.ts | 307 ------ src/modules/user/service/sms.ts | 85 -- src/modules/user/service/wx.ts | 281 ------ src/welcome.ts | 19 - test/README.md | 12 - tsconfig.json | 30 - typings/plugin.d.ts | 8 - typings/upload.d.ts | 56 -- view/welcome.html | 28 - 160 files changed, 9727 deletions(-) create mode 100644 .DS_Store delete mode 100644 .dockerignore delete mode 100644 .editorconfig delete mode 100644 .eslintrc.json delete mode 100644 .gitattributes delete mode 100644 .gitignore delete mode 100644 .hintrc delete mode 100644 .prettierrc.js delete mode 100644 .vscode/config.code-snippets delete mode 100644 .vscode/controller.code-snippets delete mode 100644 .vscode/entity.code-snippets delete mode 100644 .vscode/event.code-snippets delete mode 100644 .vscode/middleware.code-snippets delete mode 100644 .vscode/queue.code-snippets delete mode 100644 .vscode/service.code-snippets delete mode 100644 Dockerfile delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 bootstrap.js delete mode 100644 cool/obfuscate.js delete mode 100644 docker-compose.yml delete mode 100644 jest.config.js delete mode 100644 package.json delete mode 100644 public/css/welcome.css delete mode 100644 public/favicon.ico delete mode 100644 public/js/welcome.js delete mode 100644 public/uploads/说明.md delete mode 100644 src/comm/utils.ts delete mode 100644 src/config/config.default.ts delete mode 100644 src/config/config.local.ts delete mode 100644 src/config/config.prod.ts delete mode 100644 src/configuration.ts delete mode 100644 src/interface.ts delete mode 100644 src/modules/base/config.ts delete mode 100644 src/modules/base/controller/admin/comm.ts delete mode 100644 src/modules/base/controller/admin/open.ts delete mode 100644 src/modules/base/controller/admin/sys/department.ts delete mode 100644 src/modules/base/controller/admin/sys/log.ts delete mode 100644 src/modules/base/controller/admin/sys/menu.ts delete mode 100644 src/modules/base/controller/admin/sys/param.ts delete mode 100644 src/modules/base/controller/admin/sys/role.ts delete mode 100644 src/modules/base/controller/admin/sys/user.ts delete mode 100644 src/modules/base/controller/app/README.md delete mode 100644 src/modules/base/controller/app/comm.ts delete mode 100644 src/modules/base/db.json delete mode 100644 src/modules/base/dto/login.ts delete mode 100644 src/modules/base/entity/sys/conf.ts delete mode 100644 src/modules/base/entity/sys/department.ts delete mode 100644 src/modules/base/entity/sys/log.ts delete mode 100644 src/modules/base/entity/sys/menu.ts delete mode 100644 src/modules/base/entity/sys/param.ts delete mode 100644 src/modules/base/entity/sys/role.ts delete mode 100644 src/modules/base/entity/sys/role_department.ts delete mode 100644 src/modules/base/entity/sys/role_menu.ts delete mode 100644 src/modules/base/entity/sys/user.ts delete mode 100644 src/modules/base/entity/sys/user_role.ts delete mode 100644 src/modules/base/event/app.ts delete mode 100644 src/modules/base/event/menu.ts delete mode 100644 src/modules/base/job/log.ts delete mode 100644 src/modules/base/menu.json delete mode 100644 src/modules/base/middleware/authority.ts delete mode 100644 src/modules/base/middleware/log.ts delete mode 100644 src/modules/base/service/sys/conf.ts delete mode 100644 src/modules/base/service/sys/data.ts delete mode 100644 src/modules/base/service/sys/department.ts delete mode 100644 src/modules/base/service/sys/log.ts delete mode 100644 src/modules/base/service/sys/login.ts delete mode 100644 src/modules/base/service/sys/menu.ts delete mode 100644 src/modules/base/service/sys/param.ts delete mode 100644 src/modules/base/service/sys/perms.ts delete mode 100644 src/modules/base/service/sys/role.ts delete mode 100644 src/modules/base/service/sys/user.ts delete mode 100644 src/modules/demo/config.ts delete mode 100644 src/modules/demo/controller/admin/goods.ts delete mode 100644 src/modules/demo/controller/open/cache.ts delete mode 100644 src/modules/demo/controller/open/event.ts delete mode 100644 src/modules/demo/controller/open/goods.ts delete mode 100644 src/modules/demo/controller/open/plugin.ts delete mode 100644 src/modules/demo/controller/open/queue.ts delete mode 100644 src/modules/demo/controller/open/rpc.ts delete mode 100644 src/modules/demo/controller/open/sse.ts delete mode 100644 src/modules/demo/controller/open/transaction.ts delete mode 100644 src/modules/demo/entity/goods.ts delete mode 100644 src/modules/demo/event/comm.ts delete mode 100644 src/modules/demo/queue/comm.ts delete mode 100644 src/modules/demo/queue/getter.ts delete mode 100644 src/modules/demo/queue/single.ts delete mode 100644 src/modules/demo/service/cache.ts delete mode 100644 src/modules/demo/service/goods.ts delete mode 100644 src/modules/demo/service/rpc.ts delete mode 100644 src/modules/demo/service/transaction.ts delete mode 100644 src/modules/dict/config.ts delete mode 100644 src/modules/dict/controller/admin/info.ts delete mode 100644 src/modules/dict/controller/admin/type.ts delete mode 100644 src/modules/dict/controller/app/info.ts delete mode 100644 src/modules/dict/db.json delete mode 100644 src/modules/dict/entity/info.ts delete mode 100644 src/modules/dict/entity/type.ts delete mode 100644 src/modules/dict/service/info.ts delete mode 100644 src/modules/dict/service/type.ts delete mode 100644 src/modules/plugin/config.ts delete mode 100644 src/modules/plugin/controller/admin/info.ts delete mode 100644 src/modules/plugin/entity/info.ts delete mode 100644 src/modules/plugin/event/app.ts delete mode 100644 src/modules/plugin/event/init.ts delete mode 100644 src/modules/plugin/hooks/base.ts delete mode 100644 src/modules/plugin/hooks/upload/index.ts delete mode 100644 src/modules/plugin/hooks/upload/interface.ts delete mode 100644 src/modules/plugin/interface.ts delete mode 100644 src/modules/plugin/service/center.ts delete mode 100644 src/modules/plugin/service/info.ts delete mode 100644 src/modules/plugin/service/types.ts delete mode 100644 src/modules/recycle/config.ts delete mode 100644 src/modules/recycle/controller/admin/data.ts delete mode 100644 src/modules/recycle/entity/data.ts delete mode 100644 src/modules/recycle/event/data.ts delete mode 100644 src/modules/recycle/schedule/data.ts delete mode 100644 src/modules/recycle/service/data.ts delete mode 100644 src/modules/space/config.ts delete mode 100644 src/modules/space/controller/admin/info.ts delete mode 100644 src/modules/space/controller/admin/type.ts delete mode 100644 src/modules/space/controller/说明.md delete mode 100644 src/modules/space/entity/info.ts delete mode 100644 src/modules/space/entity/type.ts delete mode 100644 src/modules/space/service/info.ts delete mode 100644 src/modules/space/service/type.ts delete mode 100644 src/modules/task/config.ts delete mode 100644 src/modules/task/controller/admin/info.ts delete mode 100644 src/modules/task/controller/说明.md delete mode 100644 src/modules/task/db.json delete mode 100644 src/modules/task/entity/info.ts delete mode 100644 src/modules/task/entity/log.ts delete mode 100644 src/modules/task/event/app.ts delete mode 100644 src/modules/task/middleware/task.ts delete mode 100644 src/modules/task/queue/task.ts delete mode 100644 src/modules/task/service/demo.ts delete mode 100644 src/modules/task/service/info.ts delete mode 100644 src/modules/user/config.ts delete mode 100644 src/modules/user/controller/admin/address.ts delete mode 100644 src/modules/user/controller/admin/info.ts delete mode 100644 src/modules/user/controller/app/address.ts delete mode 100644 src/modules/user/controller/app/comm.ts delete mode 100644 src/modules/user/controller/app/info.ts delete mode 100644 src/modules/user/controller/app/login.ts delete mode 100644 src/modules/user/entity/address.ts delete mode 100644 src/modules/user/entity/info.ts delete mode 100644 src/modules/user/entity/wx.ts delete mode 100644 src/modules/user/event/app.ts delete mode 100644 src/modules/user/middleware/app.ts delete mode 100644 src/modules/user/service/address.ts delete mode 100644 src/modules/user/service/info.ts delete mode 100644 src/modules/user/service/login.ts delete mode 100644 src/modules/user/service/sms.ts delete mode 100644 src/modules/user/service/wx.ts delete mode 100644 src/welcome.ts delete mode 100644 test/README.md delete mode 100644 tsconfig.json delete mode 100644 typings/plugin.d.ts delete mode 100644 typings/upload.d.ts delete mode 100644 view/welcome.html diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..46a8e3909a72f0c17552b389279dff25aebddeb9 GIT binary patch literal 8196 zcmeHM-A)rh6h6}~bjx3e(S(>7H}MuLB|tIWlmZtd>IF4=p$1#Jl$B+N^oNEJOz+iK z@D+@=zK6bxSNNUTrS442jU-CKOfz$~yXV_8^UXPDd$vR*D&0nrXpV?nbe6M|7)CU{ z&V8t5k~8-p1@J@%0HlM{s^J)QfWml*EGM!bO9jO}UW7s-rox4ZatKB zXmMbzp%>0o!%>X%feokwd<%DwsQmZ%4S<3CY9MD|)2B9t(2am*Y=Pe64DO&~1(MP_ei+(3 zyCddU%`H%GP6jOK*zCH2WlP84iurDg+@&w6U7EtGB|aS>n1vebDz0@a#Cw#+jp6<^ z^nKHU+L5%Tqh=y0toPbSiNAcWAB91?v#{_}WU|iKc+SnalkVHi$&Vxr!ws#J~!$^L@I?+V(D1ra$?K8d(R&-o# zMWKv%uUX$w-VPph?y}!-E$ySXw1|4B_&Egc5_{l-{S!K*P``&@A5614K^xG&h)RyC z(A){-gK5kRVu<6a0~@Jm9JSxdBh%O%J*6#Lr%ifJRoc{Nr+hH2?O-+%@nuAkbKhWM z3ae%>I>6XeYabouh+Z+1^4f9Wy6{}i5WD(Zc-5M2p0+XTHSqNevH)%y1_IHiA+q2I z(WYzh8b@jUcduS9t-`BUipr}OSK-yArP5z`b+YOqpH>;s^l8ra;zMdjrd0+R@+x?N zk+C_GXviFpC)iKU^+O)R*+kQJklQ#P_VnEm>>=s-z|m~G0t49?JID3^=H>7IuVBGK zEd!Q;>&}31HmVyH%<|#~kvU(npvrMbRgOar{xHO`2UW(D6WNa? a&Y=DC7XjzWtbP8cf79CMzjBJ3H2emjw^fP& literal 0 HcmV?d00001 diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index abe7af5..0000000 --- a/.dockerignore +++ /dev/null @@ -1,18 +0,0 @@ -logs/ -npm-debug.log -yarn-error.log -node_modules/ -package-lock.json -yarn.lock -coverage/ -dist/ -.idea/ -run/ -.DS_Store -*.sw* -*.un~ -.tsbuildinfo -.tsbuildinfo.* -.audit -public/uploads/ -cache/ diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 4c7f8a8..0000000 --- a/.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -# 🎨 editorconfig.org - -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_style = space -indent_size = 2 -trim_trailing_whitespace = true -insert_final_newline = true \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 7dab201..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "extends": "./node_modules/mwts/", - "ignorePatterns": [ - "node_modules", - "dist", - "test", - "jest.config.js", - "typings", - "public/**/**", - "view/**/**", - "packages" - ], - "env": { - "jest": true - }, - "rules": { - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/ban-ts-comment": "off", - "node/no-extraneous-import": "off", - "no-empty": "off", - "node/no-extraneous-require": "off", - "node/no-unpublished-import": "off", - "eqeqeq": "off", - "node/no-unsupported-features/node-builtins": "off", - "@typescript-eslint/ban-types": "off", - "no-control-regex": "off", - "prefer-const": "off" - } -} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 0b909d8..0000000 --- a/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -*.js text eol=lf -*.json text eol=lf -*.ts text eol=lf -*.code-snippets text eol=lf \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 4cafa26..0000000 --- a/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -logs/ -cache/ -npm-debug.log -yarn-error.log -node_modules/ -package-lock.json -yarn.lock -coverage/ -dist/ -.idea/ -run/ -.DS_Store -launch.json -*.sw* -*.un~ -.tsbuildinfo -.tsbuildinfo.* -data/* -pnpm-lock.yaml -public/uploads/* diff --git a/.hintrc b/.hintrc deleted file mode 100644 index 82cba57..0000000 --- a/.hintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": [ - "development" - ], - "hints": { - "typescript-config/consistent-casing": "off", - "typescript-config/strict": "off" - } -} \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js deleted file mode 100644 index b964930..0000000 --- a/.prettierrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - ...require('mwts/.prettierrc.json') -} diff --git a/.vscode/config.code-snippets b/.vscode/config.code-snippets deleted file mode 100644 index 2abbf4f..0000000 --- a/.vscode/config.code-snippets +++ /dev/null @@ -1,28 +0,0 @@ -{ - "config": { - "prefix": "config", - "body": [ - "import { ModuleConfig } from '@cool-midway/core';", - "", - "/**", - " * 模块配置", - " */", - "export default () => {", - " return {", - " // 模块名称", - " name: 'xxx',", - " // 模块描述", - " description: 'xxx',", - " // 中间件,只对本模块有效", - " middlewares: [],", - " // 中间件,全局有效", - " globalMiddlewares: [],", - " // 模块加载顺序,默认为0,值越大越优先加载", - " order: 0,", - " } as ModuleConfig;", - "};", - "" - ], - "description": "cool-admin config代码片段" - } -} diff --git a/.vscode/controller.code-snippets b/.vscode/controller.code-snippets deleted file mode 100644 index 5bd7095..0000000 --- a/.vscode/controller.code-snippets +++ /dev/null @@ -1,19 +0,0 @@ -{ - "controller": { - "prefix": "controller", - "body": [ - "import { CoolController, BaseController } from '@cool-midway/core';", - "", - "/**", - " * 描述", - " */", - "@CoolController({", - " api: ['add', 'delete', 'update', 'info', 'list', 'page'],", - " entity: 实体,", - "})", - "export class XxxController extends BaseController {}", - "" - ], - "description": "cool-admin controller代码片段" - } -} diff --git a/.vscode/entity.code-snippets b/.vscode/entity.code-snippets deleted file mode 100644 index 992a066..0000000 --- a/.vscode/entity.code-snippets +++ /dev/null @@ -1,20 +0,0 @@ -{ - "entity": { - "prefix": "entity", - "body": [ - "import { BaseEntity } from '@cool-midway/core';", - "import { Column, Entity } from 'typeorm';", - "", - "/**", - " * 描述", - " */", - "@Entity('xxx_xxx_xxx')", - "export class XxxEntity extends BaseEntity {", - " @Column({ comment: '描述' })", - " xxx: string;", - "}", - "" - ], - "description": "cool-admin entity代码片段" - } -} diff --git a/.vscode/event.code-snippets b/.vscode/event.code-snippets deleted file mode 100644 index dae6473..0000000 --- a/.vscode/event.code-snippets +++ /dev/null @@ -1,21 +0,0 @@ -{ - "event": { - "prefix": "event", - "body": [ - "import { CoolEvent, Event } from '@cool-midway/core';", - "", - "/**", - " * 接收事件", - " */", - "@CoolEvent()", - "export class xxxEvent {", - " @Event('updateUser')", - " async updateUser(msg, a) {", - " console.log('ImEvent', 'updateUser', msg, a);", - " }", - "}", - "" - ], - "description": "cool-admin event代码片段" - } -} diff --git a/.vscode/middleware.code-snippets b/.vscode/middleware.code-snippets deleted file mode 100644 index 367be90..0000000 --- a/.vscode/middleware.code-snippets +++ /dev/null @@ -1,29 +0,0 @@ -{ - "middleware": { - "prefix": "middleware", - "body": [ - "import { Middleware } from '@midwayjs/decorator';", - "import { NextFunction, Context } from '@midwayjs/koa';", - "import { IMiddleware } from '@midwayjs/core';", - "", - "/**", - " * 描述", - " */", - "@Middleware()", - "export class XxxMiddleware implements IMiddleware {", - " resolve() {", - " return async (ctx: Context, next: NextFunction) => {", - " // 控制器前执行的逻辑", - " const startTime = Date.now();", - " // 执行下一个 Web 中间件,最后执行到控制器", - " await next();", - " // 控制器之后执行的逻辑", - " console.log(Date.now() - startTime);", - " };", - " }", - "}", - "" - ], - "description": "cool-admin middleware代码片段" - } -} diff --git a/.vscode/queue.code-snippets b/.vscode/queue.code-snippets deleted file mode 100644 index 3518633..0000000 --- a/.vscode/queue.code-snippets +++ /dev/null @@ -1,21 +0,0 @@ -{ - "queue": { - "prefix": "queue", - "body": [ - "import { BaseCoolQueue, CoolQueue } from '@cool-midway/task';", - "", - "/**", - " * 队列", - " */", - "@CoolQueue()", - "export abstract class xxxQueue extends BaseCoolQueue {", - " async data(job: any, done: any) {", - " console.log('收到的数据', job.data);", - " done();", - " }", - "}", - "" - ], - "description": "cool-admin service代码片段" - } -} diff --git a/.vscode/service.code-snippets b/.vscode/service.code-snippets deleted file mode 100644 index 4870279..0000000 --- a/.vscode/service.code-snippets +++ /dev/null @@ -1,33 +0,0 @@ -{ - "service": { - "prefix": "service", - "body": [ - "import { Init, Provide } from '@midwayjs/decorator';", - "import { BaseService } from '@cool-midway/core';", - "import { InjectEntityModel } from '@midwayjs/typeorm';", - "import { Repository } from 'typeorm';", - "", - "/**", - " * 描述", - " */", - "@Provide()", - "export class XxxService extends BaseService {", - " @InjectEntityModel(实体)", - " xxxEntity: Repository<实体>;", - "" - " @Init()" - " async init() {", - " await super.init();", - " this.setEntity(this.xxxEntity);", - " }", - "", - " /**", - " * 描述", - " */", - " async xxx() {}", - "}", - "" - ], - "description": "cool-admin service代码片段" - } -} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index b68ce7a..0000000 --- a/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ - -FROM node:lts-alpine - -WORKDIR /app - -# 配置alpine国内镜像加速 -RUN sed -i "s@http://dl-cdn.alpinelinux.org/@https://repo.huaweicloud.com/@g" /etc/apk/repositories - -# 安装tzdata,默认的alpine基础镜像不包含时区组件,安装后可通过TZ环境变量配置时区 -RUN apk add --no-cache tzdata - -# 设置时区为中国东八区,这里的配置可以被docker-compose.yml或docker run时指定的时区覆盖 -ENV TZ="Asia/Shanghai" - -# 如果各公司有自己的私有源,可以替换registry地址,如使用官方源注释下一行 -RUN npm config set registry https://registry.npmmirror.com - -# 复制package.json -COPY package.json ./package.json -# 安装依赖 -RUN npm install -# 构建项目 -COPY . . -RUN npm run build -# 删除开发期依赖 -RUN rm -rf node_modules && rm package-lock.json -# 安装生产环境依赖 -RUN npm install - -# 如果端口更换,这边可以更新一下 -EXPOSE 8001 - -CMD ["npm", "run", "start"] \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 5a6831d..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 cool-team-official - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index a970153..0000000 --- a/README.md +++ /dev/null @@ -1,191 +0,0 @@ -

- Midway Logo -

- -

cool-admin(midway版)一个很酷的后台权限管理系统,开源免费,模块化、插件化、极速开发CRUD,方便快速构建迭代后台管理系统,支持serverless、docker、普通服务器等多种方式部署 -到 官网 进一步了解。 -

- GitHub license - GitHub tag - GitHub tag -

- -## 特性 - -Ai时代,很多老旧的框架已经无法满足现代化的开发需求,Cool-Admin开发了一系列的功能,让开发变得更简单、更快速、更高效。 - -- **Ai编码**:通过微调大模型学习框架特有写法,实现简单功能从Api接口到前端页面的一键生成 -- **流程编排**:通过拖拽编排方式,即可实现类似像智能客服这样的功能 -- **模块化**:代码是模块化的,清晰明了,方便维护 -- **插件化**:插件化的设计,可以通过安装插件的方式扩展如:支付、短信、邮件等功能 - -![](https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/flow.png) - -## 技术栈 - -- 后端:**`node.js` `midway.js` `koa.js` `typescript`** -- 前端:**`vue.js` `element-plus` `jsx` `pinia` `vue-router`** -- 数据库:**`mysql` `postgresql` `sqlite`** - -如果你是前端,后端的这些技术选型对你是特别友好的,前端开发者可以较快速地上手。 -如果你是后端,Typescript 的语法又跟 java、php 等特别类似,一切看起来也是那么得熟悉。 - -如果你想使用 java 版本后端,请移步[cool-admin-java](https://cool-js.com/admin/java/introduce.html) - -#### 官网 - -[https://cool-js.com](https://cool-js.com) - -## 视频教程 - -[官方 B 站视频教程](https://www.bilibili.com/video/BV1j1421R7aB) - - - -## 演示 - -[AI 极速编码](https://cool-js.com/ai/introduce.html) - -[https://show.cool-admin.com](https://show.cool-admin.com) - -- 账户:admin -- 密码:123456 - -Admin Home - -#### 项目前端 - -[https://github.com/cool-team-official/cool-admin-vue](https://github.com/cool-team-official/cool-admin-vue) - -或 - -[https://gitee.com/cool-team-official/cool-admin-vue](https://gitee.com/cool-team-official/cool-admin-vue) - -或 - -[https://gitcode.com/cool_team/cool-admin-vue](https://gitcode.com/cool_team/cool-admin-vue) - -## 微信群 - -Admin Wechat - -## 运行 - -#### 修改数据库配置,配置文件位于`src/config/config.local.ts` - -以 Mysql 为例,其他数据库请参考[数据库配置文档](https://cool-js.com/admin/node/quick.html#%E6%95%B0%E6%8D%AE%E5%BA%93%E9%85%8D%E7%BD%AE) - -Mysql(`>=5.7版本`),建议 8.0,node 版本(`>=16.x`),建议 18.x,首次启动会自动初始化并导入数据 - -```ts -// mysql,驱动已经内置,无需安装 -typeorm: { - dataSource: { - default: { - type: 'mysql', - host: '127.0.0.1', - port: 3306, - username: 'root', - password: '123456', - database: 'cool', - // 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失 - synchronize: true, - // 打印日志 - logging: false, - // 字符集 - charset: 'utf8mb4', - // 是否开启缓存 - cache: true, - // 实体路径 - entities: ['**/modules/*/entity'], - }, - }, - }, -``` - -#### 安装依赖并运行 - -```bash -$ npm i -$ npm run dev -$ open http://localhost:8001/ -``` - -注: `npm i`如果安装失败可以尝试使用[cnpm](https://developer.aliyun.com/mirror/NPM?from=tnpm),或者切换您的镜像源,推荐使用[pnpm](https://pnpm.io/) - -## CURD(快速增删改查) - -大部分的后台管理系统,或者 API 服务都是对数据进行管理,所以可以看到大量的 CRUD 场景(增删改查),cool-admin 对此进行了大量地封装,让这块的编码量变得极其地少。 - -#### 新建一个数据表 - -`src/modules/demo/entity/goods.ts`,项目启动数据库会自动创建该表,无需手动创建 - -```ts -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity, Index } from 'typeorm'; - -/** - * 商品 - */ -@Entity('demo_app_goods') -export class DemoAppGoodsEntity extends BaseEntity { - @Column({ comment: '标题' }) - title: string; - - @Column({ comment: '图片' }) - pic: string; - - @Column({ comment: '价格', type: 'decimal', precision: 5, scale: 2 }) - price: number; -} -``` - -#### 编写 api 接口 - -`src/modules/demo/controller/app/goods.ts`,快速编写 6 个 api 接口 - -```ts -import { CoolController, BaseController } from '@cool-midway/core'; -import { DemoAppGoodsEntity } from '../../entity/goods'; - -/** - * 商品 - */ -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: DemoAppGoodsEntity, -}) -export class DemoAppGoodsController extends BaseController { - /** - * 其他接口 - */ - @Get('/other') - async other() { - return this.ok('hello, cool-admin!!!'); - } -} -``` - -这样我们就完成了 6 个接口的编写,对应的接口如下: - -- `POST /app/demo/goods/add` 新增 -- `POST /app/demo/goods/delete` 删除 -- `POST /app/demo/goods/update` 更新 -- `GET /app/demo/goods/info` 单个信息 -- `POST /app/demo/goods/list` 列表信息 -- `POST /app/demo/goods/page` 分页查询(包含模糊查询、字段全匹配等) - -### 部署 - -[部署教程](https://cool-js.com/admin/deploy.html) - -### 内置指令 - -- 使用 `npm run lint` 来做代码风格检查。 - -[midway]: https://midwayjs.org - -### 低价服务器 - -[阿里云、腾讯云、华为云低价云服务器,不限新老](https://cool-js.com/service/cloud) diff --git a/bootstrap.js b/bootstrap.js deleted file mode 100644 index 9c096c2..0000000 --- a/bootstrap.js +++ /dev/null @@ -1,2 +0,0 @@ -const { Bootstrap } = require('@midwayjs/bootstrap'); -Bootstrap.run(); diff --git a/cool/obfuscate.js b/cool/obfuscate.js deleted file mode 100644 index b7d5530..0000000 --- a/cool/obfuscate.js +++ /dev/null @@ -1,70 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const JavaScriptObfuscator = require('javascript-obfuscator'); - -// 混淆配置 -const obfuscatorOptions = { - compact: true, - controlFlowFlattening: true, - controlFlowFlatteningThreshold: 0.7, - deadCodeInjection: true, - deadCodeInjectionThreshold: 0.4, - debugProtection: false, - debugProtectionInterval: 0, - disableConsoleOutput: true, - identifierNamesGenerator: 'hexadecimal', - log: false, - numbersToExpressions: true, - renameGlobals: false, - rotateStringArray: true, - selfDefending: true, - shuffleStringArray: true, - splitStrings: true, - splitStringsChunkLength: 10, - stringArray: true, - stringArrayEncoding: ['base64'], - stringArrayThreshold: 0.75, - transformObjectKeys: true, - unicodeEscapeSequence: false, -}; - -// 处理单个文件的函数 -function obfuscateFile(filePath) { - try { - const code = fs.readFileSync(filePath, 'utf8'); - const obfuscationResult = JavaScriptObfuscator.obfuscate( - code, - obfuscatorOptions - ); - fs.writeFileSync(filePath, obfuscationResult.getObfuscatedCode()); - console.log(`成功混淆文件: ${filePath}`); - } catch (error) { - console.error(`处理文件 ${filePath} 时出错:`, error); - } -} - -// 递归处理目录的函数 -function processDirectory(directory) { - const files = fs.readdirSync(directory); - - files.forEach(file => { - const fullPath = path.join(directory, file); - const stat = fs.statSync(fullPath); - - if (stat.isDirectory()) { - processDirectory(fullPath); - } else if (path.extname(file) === '.js') { - obfuscateFile(fullPath); - } - }); -} - -// 开始处理 -const distPath = path.join(process.cwd(), 'dist'); -if (fs.existsSync(distPath)) { - console.log('开始混淆 dist 目录下的 JS 文件...'); - processDirectory(distPath); - console.log('混淆完成!'); -} else { - console.error('错误: dist 目录不存在!'); -} diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index a296994..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,40 +0,0 @@ -# 本地数据库环境 -# 数据存放在当前目录下的 data里 -# 推荐使用安装了docker扩展的vscode打开目录 在本文件上右键可以快速启动,停止 -# 如不需要相关容器开机自启动,可注释掉 restart: always -# 如遇端口冲突 可调整ports下 :前面的端口号 -version: "3.1" - -services: - coolDB: - image: mysql - command: - --default-authentication-plugin=mysql_native_password - --sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION - --group_concat_max_len=102400 - restart: always - volumes: - - ./data/mysql/:/var/lib/mysql/ - environment: - TZ: Asia/Shanghai # 指定时区 - MYSQL_ROOT_PASSWORD: "123456" # 配置root用户密码 - MYSQL_DATABASE: "cool" # 业务库名 - MYSQL_USER: "root" # 业务库用户名 - MYSQL_PASSWORD: "123456" # 业务库密码 - networks: - - cool - ports: - - 3306:3306 - - coolRedis: - image: redis - #command: --requirepass "12345678" # redis库密码,不需要密码注释本行 - restart: always - environment: - TZ: Asia/Shanghai # 指定时区 - volumes: - - ./data/redis/:/data/ - networks: - - cool - ports: - - 6379:6379 diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index c5bd388..0000000 --- a/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', - testPathIgnorePatterns: ['/test/fixtures'], - coveragePathIgnorePatterns: ['/test/'], -}; \ No newline at end of file diff --git a/package.json b/package.json deleted file mode 100644 index 02bdeb6..0000000 --- a/package.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "name": "cool-admin", - "version": "7.1.2", - "description": "一个项目用COOL就够了", - "private": true, - "dependencies": { - "@cool-midway/core": "^7.1.25", - "@cool-midway/rpc": "^7.0.0", - "@cool-midway/task": "^7.0.0", - "@midwayjs/bootstrap": "^3.16.0", - "@midwayjs/cache-manager": "^3.16.0", - "@midwayjs/core": "^3.16.0", - "@midwayjs/cron": "^3.16.0", - "@midwayjs/cross-domain": "^3.16.1", - "@midwayjs/decorator": "^3.16.0", - "@midwayjs/info": "^3.16.1", - "@midwayjs/koa": "^3.16.1", - "@midwayjs/logger": "^3.4.0", - "@midwayjs/static-file": "^3.16.1", - "@midwayjs/typeorm": "^3.16.0", - "@midwayjs/upload": "^3.16.1", - "@midwayjs/validate": "^3.16.1", - "@midwayjs/view-ejs": "^3.16.1", - "axios": "^1.6.8", - "cache-manager-ioredis-yet": "^2.0.4", - "decompress": "^4.2.1", - "download": "^8.0.0", - "ipip-ipdb": "^0.6.0", - "jsonwebtoken": "^9.0.2", - "lodash": "^4.17.21", - "md5": "^2.3.0", - "mini-svg-data-uri": "^1.4.4", - "moment": "^2.30.1", - "mysql2": "^3.9.7", - "svg-captcha": "^1.4.0", - "svg2png-wasm": "^1.4.1", - "typeorm": "^0.3.20", - "uuid": "^9.0.1", - "ws": "^8.17.0" - }, - "devDependencies": { - "@midwayjs/mock": "^3.16.0", - "@types/jest": "^29.5.12", - "@types/koa": "^2.15.0", - "@types/node": "20", - "cross-env": "^7.0.3", - "javascript-obfuscator": "^4.1.1", - "jest": "^29.7.0", - "mwts": "^1.3.0", - "mwtsc": "^1.10.1", - "prettier": "^3.2.5", - "ts-jest": "^29.1.2", - "typescript": "~5.4.5" - }, - "engines": { - "node": ">=12.0.0" - }, - "scripts": { - "start": "NODE_ENV=production node ./bootstrap.js", - "dev": "cross-env NODE_ENV=local mwtsc --watch --run @midwayjs/mock/app.js --keepalive", - "cov": "jest --coverage", - "lint": "mwts check", - "lint:fix": "mwts fix", - "ci": "npm run cov", - "build": "mwtsc --cleanOutDir", - "build:obfuscate": "mwtsc --cleanOutDir && node cool/obfuscate.js", - "pm2:start": "pm2 start ./bootstrap.js -i max --name cool-admin", - "pm2:stop": "pm2 stop cool-admin & pm2 delete cool-admin" - }, - "midway-bin-clean": [ - ".vscode/.tsbuildinfo", - "dist" - ], - "repository": { - "type": "git", - "url": "https://cool-js.com" - }, - "author": "COOL", - "license": "MIT" -} diff --git a/public/css/welcome.css b/public/css/welcome.css deleted file mode 100644 index c838986..0000000 --- a/public/css/welcome.css +++ /dev/null @@ -1,89 +0,0 @@ -body { - display: flex; - height: 100vh; - justify-content: center; - align-items: center; - text-align: center; - background: #222; -} - -@keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -.footer-bar { - position: fixed; - bottom: 0; - left: 0; - right: 0; - color: #6ee1f5; - padding: 10px 0 20px 0; - text-align: center; - opacity: 0; /* 开始时隐藏 */ - animation: fadeIn 5s forwards; /* 应用动画 */ -} - -.link { - color: #6ee1f5; -} - -.reveal { - position: relative; - display: flex; - color: #6ee1f5; - font-size: 2em; - font-family: Raleway, sans-serif; - letter-spacing: 3px; - text-transform: uppercase; - white-space: pre; -} -.reveal span { - opacity: 0; - transform: scale(0); - animation: fadeIn 2.4s forwards; -} -.reveal::before, .reveal::after { - position: absolute; - content: ""; - top: 0; - bottom: 0; - width: 2px; - height: 100%; - background: white; - opacity: 0; - transform: scale(0); -} -.reveal::before { - left: 50%; - animation: slideLeft 1.5s cubic-bezier(0.7, -0.6, 0.3, 1.5) forwards; -} -.reveal::after { - right: 50%; - animation: slideRight 1.5s cubic-bezier(0.7, -0.6, 0.3, 1.5) forwards; -} - -@keyframes fadeIn { - to { - opacity: 1; - transform: scale(1); - } -} -@keyframes slideLeft { - to { - left: -6%; - opacity: 1; - transform: scale(0.9); - } -} -@keyframes slideRight { - to { - right: -6%; - opacity: 1; - transform: scale(0.9); - } -} diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index a0c3086ab00181b2809e1851a71268aeb354d9c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5837 zcmXX~2|QHY`@b`~Xl9I*LH6D$41Md=N?#Lm%Swps@>uFT948wGCd&h*S(4xB|>I>vPHG(HQfAZX6S-;7cT5wR=&cfOx#Sa9w-?V!^jauQb!)*$^g#*w_YTt2>;9DS{WbK zqHUH!DigA@q}5cn=0t<@M5*RU?72$ihrxb;}>nSpuFYKrE7!- z!qDef%bHs0E1s|(t4?zp7<;nG30N)G$DP>W-ED2yasfPQg!8wUCG3bCN)QnUxDE#6 z@YEAqAq&)GaH(p8|LxZk1YEGxw2XiV6_r6h@fM^Hc`{v>Dgl*F+f@}HEnqrOaKr<) zQKg6Xf`#WBQWkiSvOY-@%e$Y|M)BvbWZXiU5- zUGuu7Vkdr*7JC*wH)D9gedGyX$ zW$@U7l`TlnH=pp?8%!!Y9IRoyV0+(4l*!uQzZG&^4Dro-!Dg8Ve0UbC8pbUAras4x zxYGz!w%ck=(+CL#TzX|fI-QM7tfAwxOfA@Jny9FX2s96J`8`PMy?PjL~`mj z_%S~F#qRVSUT_*F0?S(m`<4u_jvh5rU8kG@N3U`%(da^=%bSR6Qb<`h%#x6xx`xak zyMbbZVHQGT=Y$Eu&+O{S$`A`*E|>e8v#gv~G}2T$lWkoLI58?Z|R&QMb0v$EtH zqJ%I^_b;C1J}rRp?M-mqKLSq;9eK-RG2%L6EMl;~mbw^9y}i}dMbnvm2~>92{;1r8 z9YH==CA)lx_+8!u`fKSMDG%*q0N9az=9@YWgW3L?$|43YyBz$Fbri6jA9M7)0##i_ znEyI?yB%!eGp!GlXr6Te7sI-{;&g86A!X0T2upTkS`W^g%UFw&+jfnq&rd>d5+q*q zHQge`Hond#yH;>qkq!ALNidViOhi%%y7u~%&xN7g+|~8%RLVzq!p9f{nmgt&My{f* z>$U3zTLWg6?Y&k$d`^Vc`LT}@WXC1O^W5`K*E2xQ*f~U!hc9d~=NTtgvl<`*Dn9UQ z!jkV;VAH=OaM8uX>m6L70oX||mAS`@9g#@EaVidOMJa7J7k_T5f#Oqk5?qZzFC7w_ zh!b6&vcoj38|yUMFZgW0>(vTma`u?kTNM^1XgUt;Ca#k6)BBsR!0K0C(~Rp&V#yba zIHOfH(4_7tYyUmh+-vraF|xP2&qnP6A_jXw!pvi;FG89RJCeR{F~5kjo&4km*$J4K ze@gllNHL34(< zBDVc;Z{&rW`et;NEmVoVX_93lxaD=a`>N{v zmgH+7>7AMFR3xFbGvUyagNT6F7q|4|RjD5gA71ByV)yUuL(lXP0Uw95pN(D>F}NY8 zK>Qx2Hg(*}(Cq*bsQ9hEN9N4!dmIVK32_h4c*XV~5;~L&iWCEQyyvPKBGEr8-Xbyk z%3MB9ug=DK{UKDg} zdt@F;Zj^p1yox5Y(7R`)(cUn!%6r5|#9$b0O>cVDbDV{092%F^d(T4z&LK(O1*65J z*hk+Dlk70ujk4Npv@7ubEB4MjN}E9Y7PV_BeYqhm6;JMeISK6z{RTC|On%Mx#k$i9 z?JFARbh_YwJ2{q}r_;A}KfcVT>0X=nh15xvIt;H+;lYkv5)5>GF8ih9O1%lK zJDkFb9)|1cM>gY*)c}z}F|;e;mZXJlT>Ez1stD6Hn%9+dTxq2VToD)Fid#^}j zc+VUT<;|UwDCwRU=)*9r!%gZPA$~1clJ9U?ZA!fXkY($8Qs)It>z!xh!qM|{65bfL zN7R{yC(VGT60v?50~Ha&&|e`>5uB2%(e{5d+`o}O&(N+>AdA-bY&p)SnALHj(PL~nw;wL{jP$|H4pMhFJ3@YSxdJt9 zS;$?3YQ^H$v?s0I5`Rk4&mVGKIq_o&BfV45`TkBAazp~d zzE-&a&k{Oats^$^f?iR;ZX4=nIBkxEtRJ830he^bO%i5Fu@nRAu}a+nlJDn;PEBQy zj_Jb@OPcM707WV5Lhh*HEs&s|!f}Rbo_(po!XgS;*6%i-fM{&555-Lq+LwUyq!ALrn~Ko?JPD!4E0 z5aNL+Cg>7WS+Eqr70IHffaUfg(@PZ!J)&DZ=`#i~^{dD#+gpXYEsXD|>&cDZwHo!2 z>z#g`p9c?>UHYdD5{J)|;b{R+Xbn4qnYyn;m}@C^bcM!c&X<};w1%mrl92|-@{ zhbYr}dEL%_J}ZT+#mh1;`iQ_IqkA;)V7sy3Cj)S$qPp=T-2Zwa?HjQb>-Tv-7$}Wp z0G3<%OnJrvvsP{S?|08&!4+w_MnD=7em}Yt zGO4H7B7$5<3u|#FYu-m0i!%Ac-yGnB_C8*XWd*x&pG)d#`s*>N9|_?wUCE8FI6~{_ zoK2qX$aB(y)sc++2k@B+(%u(6X?(6P^E7m3R~9?r3Zr@m5zZm$zz@>4gk6e>2y-?H zow^oS2C=O#eHr(UK4R*k7g@W1?wBz1JR+_o#Y}SOFOcG&(FD)J94=Q6hnd#1_D+|v zNFZgYbaZwg0O<;Naj<(&@Fn{1@?C+N46{3JH}!K4c=@IxsXX#K$V1EU4fB+A7AbZM zenLL0P$Sppaqs#if0yhtD%4X5-Uv)`f5S83xwn6*f&No-vU|6v(EeU~TH$18Eq(Cp zcyh#KySX<^w}iwbuMn|;$+Ydz)21-p{ckGdFSGc+=tR%;7S++V+lO3}k3EA@QfA{c z+ZR$?yS-ewQ+xwoSmZogy1b@YZrw}xz#ea5)S9gH=FLr}Nm<;98S$SKKHNZ>c;kw+ zC^JXaQj{j-i@SWOtJ86mbQphC?#cZ_ExFZB=Hr>j;+*Ibco{WW7_~~qo!mqd_&tpy zl(dy^EO`mo(N$#zN7rkBuA9daI?h18iYZ=Vv*ja5f7y%Pcg#s3oLjjYqe z{q7-wlE1s==TRk#pL};P%t^z(1*q<7Q{xI}{?7r_;J4kx1$5+k8)9w7^2^F4Sr#CjvAPcDzfHXj22pGO89xBR3b6<2>gW$D4`X)5{6j& zu1CQZl9^xNT4z})4BA=2WConK4Qs86|9l8NcJZngHlih|*9AZdqh`dr(JiVLFLvcJ z9?p6sy{I>3MQ(Q{!#A#RhQ>&-&tjCJl7l!}h{#B6-RAG2W1n-W9Qj7BF^a!;-kz#Jf0l!GHKK5{!Y9n*LqZ-y&Q4QcK{RjBFrV){J>4v; ztmOor3VCVcNKB0V?${t3Z;{w)&ZiV*CM!jGU$e0SSMFr6BwZXM4 z4CQ_e4=bd?H`-PjjO?Qi-C>;&v*);p{Key^)c#GdvspC>t`MK$VsU4{NDL;St-Hhf zM5*1YwE67-k`t;Te~K&Pe`HRK^+~f|NZ&E#%klz}WLT+um$gs(g@`B9KtYML>(XFh z7;^U!Ln#QB*lOndNf33P2T9Tjy6Q1q)Qj=Pa0jZE8;ew^+Ab~#cQ7&DZLd^>U7cck zP|`4b<3i;Ts5(N~2=%uHi2+wC<{bBjIM6?9ZzU~`3txd*d^>6iKxn5wdmPumhqI*G{7?m+r0`bh@mJWKMY zruZ3HP;7VoOy3*07}_;fI>JL9s>60nbxdslZ2jEj3hHu?Ipm`QS_#AUGTDF=)34#7 zLz2Qi=l_t74+@?$#by07zM?7d6xc~1h-(X@N_+o+J)DbmkYH&drb4nh;92jDPiJ5V z(l<-FGmjn?km6QcFa|QxCW_B*%@Tl*wl_BfYNMaive$6UfLr_VELdEhGtgFOUYz|I z*|3FShnNn)XJEm)`-2^rp)+rxioy*smD4gReFVe2#Sg3GG5&v~x$yGf6%2cOvlqd6 z>vH5duW^wwb)p9xvaw0BChYzeaC~43h%SY`afV0|g_hsZP)C-2BEA%Ou$*Gz1UW@@ zb&;k^cqtCtTQ|p1Kj|v&VDbZU3!G4dW6Fz^&`}d6-p9 z;psl+u^GW^&!11YdJC*P`!=nCrdQ+Qr(j$k{=1>iEj#}J^Q??f_pEb$w4_d8eqMme zqqiHUks5Kkpz)Cl=*a>vCGE6)x8yL#yy!MrJN6>#B2dM3{wx43T<}@+)gGCnK3wx1 zaq+gwK2}7}lfLnT!7%Q>RE+MN#((gWHibOlVxKC*!7r^2?onQnU`icNcq{f|cYqk5 zUKl~~UPzN_2S+z^H#OlI@bhMysP4@j%*j(4(Z|stoD{O#@{pvmgo%G_-m85dJ#1K;kn6;AU_MIa=Xj6-*(^?cTA%RntF>aXB_yb#F|f95>*h$3^@9CeZ$4_#ofnlOVA@uLziswQuBK z){|!ffev6+HKaB|H12`ES-d=X^%fKR5b}& zy~gpK;X9}Ts|J26QJe0$-!A^&*q|xS?cb`@Cf_9$$a?NoSmIl=zxsI`Xt*BndWlU# zxwvt&!w!%idZO`C96N$?`=1$ul4do9Zp)Yc2}I^O^ln5ws&DsM3lRC#RSDpp$6e%qdHgN+S~O{{Yd%gj@gs diff --git a/public/js/welcome.js b/public/js/welcome.js deleted file mode 100644 index 05054e8..0000000 --- a/public/js/welcome.js +++ /dev/null @@ -1,14 +0,0 @@ -const duration = 0.8; -const delay = 0.3; -// eslint-disable-next-line no-undef -const revealText = document.querySelector('.reveal'); -const letters = revealText.textContent.split(''); -revealText.textContent = ''; -const middle = letters.filter(e => e !== ' ').length / 2; -letters.forEach((letter, i) => { - // eslint-disable-next-line no-undef - const span = document.createElement('span'); - span.textContent = letter; - span.style.animationDelay = `${delay + Math.abs(i - middle) * 0.1}s`; - revealText.append(span); -}); diff --git a/public/uploads/说明.md b/public/uploads/说明.md deleted file mode 100644 index 22a298f..0000000 --- a/public/uploads/说明.md +++ /dev/null @@ -1 +0,0 @@ -文件上传目录 \ No newline at end of file diff --git a/src/comm/utils.ts b/src/comm/utils.ts deleted file mode 100644 index f9ba60c..0000000 --- a/src/comm/utils.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { Inject, Provide } from '@midwayjs/decorator'; -import { Context } from '@midwayjs/koa'; -import * as ipdb from 'ipip-ipdb'; -import * as _ from 'lodash'; -import * as moment from 'moment'; - -/** - * 帮助类 - */ -@Provide() -export class Utils { - @Inject() - baseDir; - - /** - * 获得请求IP - */ - async getReqIP(ctx: Context) { - const req = ctx.req; - return ( - req.headers['x-forwarded-for'] || - req.socket.remoteAddress.replace('::ffff:', '') - ); - } - - /** - * 去除对象的空值属性 - * @param obj - */ - async removeEmptyP(obj) { - Object.keys(obj).forEach(key => { - if (obj[key] === null || obj[key] === '' || obj[key] === 'undefined') { - delete obj[key]; - } - }); - } - - /** - * 线程阻塞毫秒数 - * @param ms - */ - sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); - } - - /** - * 获得最近几天的日期集合 - * @param recently - */ - getRecentlyDates(recently, format = 'YYYY-MM-DD') { - moment.locale('zh-cn'); - const dates = []; - for (let i = 0; i < recently; i++) { - dates.push(moment().subtract(i, 'days').format(format)); - } - return dates.reverse(); - } - /** - * 获得最近几个月的月数 - * @param recently - */ - getRecentlyMonths(recently, format = 'YYYY-MM') { - moment.locale('zh-cn'); - const dates = []; - const date = moment(Date.now()).format('YYYY-MM'); - for (let i = 0; i < recently; i++) { - dates.push(moment(date).subtract(i, 'months').format(format)); - } - return dates.reverse(); - } - - /** - * 根据开始和结束时间,获得时间段内的日期集合 - * @param start - * @param end - */ - getBetweenDays(start, end, format = 'YYYY-MM-DD') { - moment.locale('zh-cn'); - const dates = []; - const startTime = moment(start).format(format); - const endTime = moment(end).format(format); - const days = moment(endTime).diff(moment(startTime), 'days'); - for (let i = 0; i <= days; i++) { - dates.push(moment(startTime).add(i, 'days').format(format)); - } - return dates; - } - - /** - * 根据开始和结束时间,获得时间段内的月份集合 - * @param start - * @param end - */ - getBetweenMonths(start, end, format = 'YYYY-MM') { - moment.locale('zh-cn'); - const dates = []; - const startTime = moment(start).format(format); - const endTime = moment(end).format(format); - const months = moment(endTime).diff(moment(startTime), 'months'); - for (let i = 0; i <= months; i++) { - dates.push(moment(startTime).add(i, 'months').format(format)); - } - return dates; - } - - /** - * 根据开始和结束时间,获得时间段内的小时集合 - * @param start - * @param end - */ - getBetweenHours(start, end, format = 'YYYY-MM-DD HH') { - moment.locale('zh-cn'); - const dates = []; - const startTime = moment(start).format(format); - const endTime = moment(end).format(format); - const hours = moment(endTime).diff(moment(startTime), 'hours'); - for (let i = 0; i <= hours; i++) { - dates.push(moment(startTime).add(i, 'hours').format(format)); - } - return dates; - } - - /** - * 字段转驼峰法 - * @param obj - * @returns - */ - toCamelCase(obj) { - let camelCaseObject = {}; - for (let i in obj) { - let camelCase = i.replace(/([-_][a-z])/gi, $1 => { - return $1.toUpperCase().replace('-', '').replace('_', ''); - }); - camelCaseObject[camelCase] = obj[i]; - } - return camelCaseObject; - } -} diff --git a/src/config/config.default.ts b/src/config/config.default.ts deleted file mode 100644 index 2aa8331..0000000 --- a/src/config/config.default.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { CoolConfig } from '@cool-midway/core'; -import { MidwayConfig } from '@midwayjs/core'; -import { CoolCacheStore } from '@cool-midway/core'; - -// redis缓存 -// import { redisStore } from 'cache-manager-ioredis-yet'; - -export default { - // use for cookie sign key, should change to your own and keep security - keys: 'cool-admin-keys-xxxxxx', - koa: { - port: 8001, - }, - // 模板渲染 - view: { - mapping: { - '.html': 'ejs', - }, - }, - // 静态文件配置 - staticFile: { - buffer: true, - }, - // 文件上传 - upload: { - fileSize: '200mb', - whitelist: null, - }, - // 缓存 可切换成其他缓存如:redis http://www.midwayjs.org/docs/extensions/caching - cacheManager: { - clients: { - default: { - store: CoolCacheStore, - options: { - path: 'cache', - ttl: 0, - }, - }, - }, - }, - // cacheManager: { - // clients: { - // default: { - // store: redisStore, - // options: { - // port: 6379, - // host: '127.0.0.1', - // password: '', - // ttl: 0, - // db: 0, - // }, - // }, - // }, - // }, - cool: { - // 已经插件化,本地文件上传查看 plugin/config.ts,其他云存储查看对应插件的使用 - file: {}, - // crud配置 - crud: { - // 插入模式,save不会校验字段(允许传入不存在的字段),insert会校验字段 - upsert: 'save', - // 软删除 - softDelete: true, - }, - } as CoolConfig, -} as MidwayConfig; diff --git a/src/config/config.local.ts b/src/config/config.local.ts deleted file mode 100644 index 862721b..0000000 --- a/src/config/config.local.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { CoolConfig } from '@cool-midway/core'; -import { MidwayConfig } from '@midwayjs/core'; - -/** - * 本地开发 npm run dev 读取的配置文件 - */ -export default { - typeorm: { - dataSource: { - default: { - type: 'mysql', - host: '127.0.0.1', - port: 3306, - username: 'root', - password: '123456', - database: 'cool', - // 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失 - synchronize: true, - // 打印日志 - logging: false, - // 字符集 - charset: 'utf8mb4', - // 是否开启缓存 - cache: true, - // 实体路径 - entities: ['**/modules/*/entity'], - }, - }, - }, - cool: { - // 实体与路径,跟生成代码、前端请求、swagger文档相关 注意:线上不建议开启,以免暴露敏感信息 - eps: true, - // 是否自动导入模块数据库 - initDB: true, - // 判断是否初始化的方式 - initJudge: 'db', - // 是否自动导入模块菜单 - initMenu: true, - } as CoolConfig, -} as MidwayConfig; diff --git a/src/config/config.prod.ts b/src/config/config.prod.ts deleted file mode 100644 index 35f2dbb..0000000 --- a/src/config/config.prod.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { CoolConfig } from '@cool-midway/core'; -import { MidwayConfig } from '@midwayjs/core'; - -/** - * 本地开发 npm run prod 读取的配置文件 - */ -export default { - typeorm: { - dataSource: { - default: { - type: 'mysql', - host: '127.0.0.1', - port: 3306, - username: 'root', - password: '123456', - database: 'cool', - // 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失 - synchronize: false, - // 打印日志 - logging: false, - // 字符集 - charset: 'utf8mb4', - // 是否开启缓存 - cache: true, - // 实体路径 - entities: ['**/modules/*/entity'], - }, - }, - }, - cool: { - // 是否自动导入数据库,生产环境不建议开,用本地的数据库手动初始化 - initDB: false, - } as CoolConfig, -} as MidwayConfig; diff --git a/src/configuration.ts b/src/configuration.ts deleted file mode 100644 index 9aaaa93..0000000 --- a/src/configuration.ts +++ /dev/null @@ -1,60 +0,0 @@ -import * as orm from '@midwayjs/typeorm'; -import { Configuration, App, Inject } from '@midwayjs/decorator'; -import * as koa from '@midwayjs/koa'; -import * as validate from '@midwayjs/validate'; -import * as info from '@midwayjs/info'; -import { join } from 'path'; -import * as view from '@midwayjs/view-ejs'; -import * as staticFile from '@midwayjs/static-file'; -import * as cron from '@midwayjs/cron'; -// import * as crossDomain from '@midwayjs/cross-domain'; -import * as cool from '@cool-midway/core'; -import { ILogger } from '@midwayjs/logger'; -import * as upload from '@midwayjs/upload'; -import { IMidwayApplication } from '@midwayjs/core'; -// import * as swagger from '@midwayjs/swagger'; -// import * as rpc from '@cool-midway/rpc'; -// import * as task from '@cool-midway/task'; - -@Configuration({ - imports: [ - // https://koajs.com/ - koa, - // 是否开启跨域(注:顺序不能乱放!!!) http://www.midwayjs.org/docs/extensions/cross_domain - // crossDomain, - // 模板渲染 https://midwayjs.org/docs/extensions/render - view, - // 静态文件托管 https://midwayjs.org/docs/extensions/static_file - staticFile, - // orm https://midwayjs.org/docs/extensions/orm - orm, - // 参数验证 https://midwayjs.org/docs/extensions/validate - validate, - // 本地任务 http://www.midwayjs.org/docs/extensions/cron - cron, - // 文件上传 - upload, - // cool-admin 官方组件 https://cool-js.com - cool, - // rpc 微服务 远程调用 - // rpc, - // 任务与队列 - // task, - // swagger 文档 http://www.midwayjs.org/docs/extensions/swagger - // swagger, - { - component: info, - enabledEnvironment: ['local'], - }, - ], - importConfigs: [join(__dirname, './config')], -}) -export class ContainerLifeCycle { - @App() - app: IMidwayApplication; - - @Inject() - logger: ILogger; - - async onReady() {} -} diff --git a/src/interface.ts b/src/interface.ts deleted file mode 100644 index 13daae8..0000000 --- a/src/interface.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @description User-Service parameters - */ -export interface IUserOptions { - uid: number; -} diff --git a/src/modules/base/config.ts b/src/modules/base/config.ts deleted file mode 100644 index 62e3189..0000000 --- a/src/modules/base/config.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { BaseLogMiddleware } from './middleware/log'; -import { BaseAuthorityMiddleware } from './middleware/authority'; -import { ModuleConfig } from '@cool-midway/core'; - -/** - * 模块的配置 - */ -export default () => { - return { - // 模块名称 - name: '权限管理', - // 模块描述 - description: '基础的权限管理功能,包括登录,权限校验', - // 中间件 - globalMiddlewares: [BaseAuthorityMiddleware, BaseLogMiddleware], - // 模块加载顺序,默认为0,值越大越优先加载 - order: 10, - // app参数配置允许读取的key - allowKeys: [], - // jwt 生成解密token的 - jwt: { - // 单点登录 - sso: false, - // 注意: 最好重新修改,防止破解 - secret: 'cool-admin-xxxxxx', - // token - token: { - // 2小时过期,需要用刷新token - expire: 2 * 3600, - // 15天内,如果没操作过就需要重新登录 - refreshExpire: 24 * 3600 * 15, - }, - }, - } as ModuleConfig; -}; diff --git a/src/modules/base/controller/admin/comm.ts b/src/modules/base/controller/admin/comm.ts deleted file mode 100644 index 439d7b4..0000000 --- a/src/modules/base/controller/admin/comm.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { - BaseController, - CoolController, - CoolTag, - CoolUrlTag, - TagTypes, -} from '@cool-midway/core'; -import { ALL, Body, Get, Inject, Post, Provide } from '@midwayjs/decorator'; -import { Context } from '@midwayjs/koa'; -import { PluginService } from '../../../plugin/service/info'; -import { BaseSysUserEntity } from '../../entity/sys/user'; -import { BaseSysLoginService } from '../../service/sys/login'; -import { BaseSysPermsService } from '../../service/sys/perms'; -import { BaseSysUserService } from '../../service/sys/user'; - -/** - * Base 通用接口 一般写不需要权限过滤的接口 - */ -@CoolUrlTag() -@Provide() -@CoolController() -export class BaseCommController extends BaseController { - @Inject() - baseSysUserService: BaseSysUserService; - - @Inject() - baseSysPermsService: BaseSysPermsService; - - @Inject() - baseSysLoginService: BaseSysLoginService; - - @Inject() - ctx: Context; - - @Inject() - pluginService: PluginService; - - /** - * 获得个人信息 - */ - @Get('/person', { summary: '个人信息' }) - async person() { - return this.ok( - await this.baseSysUserService.person(this.ctx.admin?.userId) - ); - } - - /** - * 修改个人信息 - */ - @Post('/personUpdate', { summary: '修改个人信息' }) - async personUpdate(@Body(ALL) user: BaseSysUserEntity) { - await this.baseSysUserService.personUpdate(user); - return this.ok(); - } - - /** - * 权限菜单 - */ - @Get('/permmenu', { summary: '权限与菜单' }) - async permmenu() { - return this.ok( - await this.baseSysPermsService.permmenu(this.ctx.admin.roleIds) - ); - } - - /** - * 文件上传 - */ - @Post('/upload', { summary: '文件上传' }) - async upload() { - const file = await this.pluginService.getInstance('upload'); - return this.ok(await file.upload(this.ctx)); - } - - /** - * 文件上传模式,本地或者云存储 - */ - @Get('/uploadMode', { summary: '文件上传模式' }) - async uploadMode() { - const file = await this.pluginService.getInstance('upload'); - return this.ok(await file.getMode()); - } - - /** - * 退出 - */ - @Post('/logout', { summary: '退出' }) - async logout() { - await this.baseSysLoginService.logout(); - return this.ok(); - } - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Get('/program', { summary: '编程' }) - async program() { - return this.ok('Node'); - } -} diff --git a/src/modules/base/controller/admin/open.ts b/src/modules/base/controller/admin/open.ts deleted file mode 100644 index b42785b..0000000 --- a/src/modules/base/controller/admin/open.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Provide, Body, Inject, Post, Get, Query } from '@midwayjs/decorator'; -import { - CoolController, - BaseController, - CoolEps, - CoolUrlTag, - CoolTag, - TagTypes, - RESCODE, -} from '@cool-midway/core'; -import { LoginDTO } from '../../dto/login'; -import { BaseSysLoginService } from '../../service/sys/login'; -import { BaseSysParamService } from '../../service/sys/param'; -import { Context } from '@midwayjs/koa'; -import { Validate } from '@midwayjs/validate'; - -/** - * 不需要登录的后台接口 - */ -@Provide() -@CoolController({ description: '开放接口' }) -@CoolUrlTag() -export class BaseOpenController extends BaseController { - @Inject() - baseSysLoginService: BaseSysLoginService; - - @Inject() - baseSysParamService: BaseSysParamService; - - @Inject() - ctx: Context; - - @Inject() - eps: CoolEps; - - /** - * 实体信息与路径 - * @returns - */ - @CoolTag(TagTypes.IGNORE_TOKEN) - @Get('/eps', { summary: '实体信息与路径' }) - public async getEps() { - return this.ok(this.eps.admin); - } - - /** - * 根据配置参数key获得网页内容(富文本) - */ - @CoolTag(TagTypes.IGNORE_TOKEN) - @Get('/html', { summary: '获得网页内容的参数值' }) - async htmlByKey(@Query('key') key: string) { - this.ctx.body = await this.baseSysParamService.htmlByKey(key); - } - - /** - * 登录 - * @param login - */ - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/login', { summary: '登录' }) - @Validate() - async login(@Body() login: LoginDTO) { - return this.ok(await this.baseSysLoginService.login(login)); - } - - /** - * 获得验证码 - */ - @CoolTag(TagTypes.IGNORE_TOKEN) - @Get('/captcha', { summary: '验证码' }) - async captcha( - @Query('type') type: string, - @Query('width') width: number, - @Query('height') height: number, - @Query('color') color: string - ) { - return this.ok( - await this.baseSysLoginService.captcha(type, width, height, color) - ); - } - - /** - * 刷新token - */ - @CoolTag(TagTypes.IGNORE_TOKEN) - @Get('/refreshToken', { summary: '刷新token' }) - async refreshToken(@Query('refreshToken') refreshToken: string) { - try { - const token = await this.baseSysLoginService.refreshToken(refreshToken); - return this.ok(token); - } catch (e) { - this.ctx.status = 401; - this.ctx.body = { - code: RESCODE.COMMFAIL, - message: '登录失效~', - }; - } - } -} diff --git a/src/modules/base/controller/admin/sys/department.ts b/src/modules/base/controller/admin/sys/department.ts deleted file mode 100644 index 4c2b0b2..0000000 --- a/src/modules/base/controller/admin/sys/department.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ALL, Body, Inject, Post, Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { BaseSysDepartmentEntity } from '../../../entity/sys/department'; -import { BaseSysDepartmentService } from '../../../service/sys/department'; - -/** - * 部门 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'list'], - entity: BaseSysDepartmentEntity, - service: BaseSysDepartmentService, -}) -export class BaseDepartmentController extends BaseController { - @Inject() - baseDepartmentService: BaseSysDepartmentService; - - /** - * 部门排序 - */ - @Post('/order', { summary: '排序' }) - async order(@Body(ALL) params: any) { - await this.baseDepartmentService.order(params); - return this.ok(); - } -} diff --git a/src/modules/base/controller/admin/sys/log.ts b/src/modules/base/controller/admin/sys/log.ts deleted file mode 100644 index caf463c..0000000 --- a/src/modules/base/controller/admin/sys/log.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Provide, Post, Inject, Body, Get } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { BaseSysLogEntity } from '../../../entity/sys/log'; -import { BaseSysUserEntity } from '../../../entity/sys/user'; -import { BaseSysConfService } from '../../../service/sys/conf'; -import { BaseSysLogService } from '../../../service/sys/log'; - -/** - * 系统日志 - */ -@Provide() -@CoolController({ - api: ['page'], - entity: BaseSysLogEntity, - urlTag: { - name: 'a', - url: ['add'], - }, - pageQueryOp: { - keyWordLikeFields: ['b.name', 'a.action', 'a.ip'], - select: ['a.*', 'b.name'], - join: [ - { - entity: BaseSysUserEntity, - alias: 'b', - condition: 'a.userId = b.id', - type: 'leftJoin', - }, - ], - }, -}) -export class BaseSysLogController extends BaseController { - @Inject() - baseSysLogService: BaseSysLogService; - - @Inject() - baseSysConfService: BaseSysConfService; - - /** - * 清空日志 - */ - @Post('/clear', { summary: '清理' }) - public async clear() { - await this.baseSysLogService.clear(true); - return this.ok(); - } - - /** - * 设置日志保存时间 - */ - @Post('/setKeep', { summary: '日志保存时间' }) - public async setKeep(@Body('value') value: number) { - await this.baseSysConfService.updateVaule('logKeep', value); - return this.ok(); - } - - /** - * 获得日志保存时间 - */ - @Get('/getKeep', { summary: '获得日志保存时间' }) - public async getKeep() { - return this.ok(await this.baseSysConfService.getValue('logKeep')); - } -} diff --git a/src/modules/base/controller/admin/sys/menu.ts b/src/modules/base/controller/admin/sys/menu.ts deleted file mode 100644 index fd3f3d4..0000000 --- a/src/modules/base/controller/admin/sys/menu.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Body, Inject, Post, Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { BaseSysMenuEntity } from '../../../entity/sys/menu'; -import { BaseSysMenuService } from '../../../service/sys/menu'; - -/** - * 菜单 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: BaseSysMenuEntity, - service: BaseSysMenuService, -}) -export class BaseSysMenuController extends BaseController { - @Inject() - baseSysMenuService: BaseSysMenuService; - - @Post('/parse', { summary: '解析' }) - async parse( - @Body('entity') entity: string, - @Body('controller') controller: string, - @Body('module') module: string - ) { - return this.ok( - await this.baseSysMenuService.parse(entity, controller, module) - ); - } - - @Post('/create', { summary: '创建代码' }) - async create(@Body() body) { - await this.baseSysMenuService.create(body); - return this.ok(); - } - - @Post('/export', { summary: '导出' }) - async export(@Body('ids') ids: number[]) { - return this.ok(await this.baseSysMenuService.export(ids)); - } - - @Post('/import', { summary: '导入' }) - async import(@Body('menus') menus: any[]) { - await this.baseSysMenuService.import(menus); - return this.ok(); - } -} diff --git a/src/modules/base/controller/admin/sys/param.ts b/src/modules/base/controller/admin/sys/param.ts deleted file mode 100644 index a6082c7..0000000 --- a/src/modules/base/controller/admin/sys/param.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Get, Inject, Provide, Query } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { BaseSysParamEntity } from '../../../entity/sys/param'; -import { BaseSysParamService } from '../../../service/sys/param'; -import { Context } from '@midwayjs/koa'; - -/** - * 参数配置 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'page'], - entity: BaseSysParamEntity, - service: BaseSysParamService, - pageQueryOp: { - keyWordLikeFields: ['name', 'keyName'], - fieldEq: ['dataType'], - }, -}) -export class BaseSysParamController extends BaseController { - @Inject() - baseSysParamService: BaseSysParamService; - - @Inject() - ctx: Context; - - /** - * 根据配置参数key获得网页内容(富文本) - */ - @Get('/html', { summary: '获得网页内容的参数值' }) - async htmlByKey(@Query('key') key: string) { - this.ctx.body = await this.baseSysParamService.htmlByKey(key); - } -} diff --git a/src/modules/base/controller/admin/sys/role.ts b/src/modules/base/controller/admin/sys/role.ts deleted file mode 100644 index 586410e..0000000 --- a/src/modules/base/controller/admin/sys/role.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { Context } from 'vm'; -import { BaseSysRoleEntity } from '../../../entity/sys/role'; -import { BaseSysRoleService } from '../../../service/sys/role'; - -/** - * 系统角色 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: BaseSysRoleEntity, - service: BaseSysRoleService, - // 新增的时候插入当前用户ID - insertParam: async (ctx: Context) => { - return { - userId: ctx.admin.userId, - }; - }, - pageQueryOp: { - keyWordLikeFields: ['a.name', 'a.label'], - where: async (ctx: Context) => { - const { userId, roleIds, username } = ctx.admin; - return [ - // 超级管理员的角色不展示 - ['label != :label', { label: 'admin' }], - // 如果不是超管,只能看到自己新建的或者自己有的角色 - [ - `(userId=:userId or id in (${roleIds.join(',')}))`, - { userId }, - username !== 'admin', - ], - ]; - }, - }, -}) -export class BaseSysRoleController extends BaseController {} diff --git a/src/modules/base/controller/admin/sys/user.ts b/src/modules/base/controller/admin/sys/user.ts deleted file mode 100644 index 82056de..0000000 --- a/src/modules/base/controller/admin/sys/user.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Body, Inject, Post, Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { BaseSysUserEntity } from '../../../entity/sys/user'; -import { BaseSysUserService } from '../../../service/sys/user'; - -/** - * 系统用户 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: BaseSysUserEntity, - service: BaseSysUserService, -}) -export class BaseSysUserController extends BaseController { - @Inject() - baseSysUserService: BaseSysUserService; - - /** - * 移动部门 - */ - @Post('/move', { summary: '移动部门' }) - async move( - @Body('departmentId') departmentId: number, - @Body('userIds') userIds: [] - ) { - await this.baseSysUserService.move(departmentId, userIds); - return this.ok(); - } -} diff --git a/src/modules/base/controller/app/README.md b/src/modules/base/controller/app/README.md deleted file mode 100644 index df64e76..0000000 --- a/src/modules/base/controller/app/README.md +++ /dev/null @@ -1 +0,0 @@ -这里写对外的api接口 \ No newline at end of file diff --git a/src/modules/base/controller/app/comm.ts b/src/modules/base/controller/app/comm.ts deleted file mode 100644 index 4c477a3..0000000 --- a/src/modules/base/controller/app/comm.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Provide, Inject, Get, Post, Query, Config } from '@midwayjs/decorator'; -import { - CoolController, - BaseController, - CoolEps, - TagTypes, - CoolUrlTag, - CoolTag, -} from '@cool-midway/core'; -import { Context } from '@midwayjs/koa'; -import { BaseSysParamService } from '../../service/sys/param'; -import { PluginService } from '../../../plugin/service/info'; - -/** - * 不需要登录的后台接口 - */ -@CoolUrlTag() -@Provide() -@CoolController() -export class BaseAppCommController extends BaseController { - @Inject() - pluginService: PluginService; - - @Inject() - ctx: Context; - - @Config('module.base.allowKeys') - allowKeys: string[]; - - @Inject() - eps: CoolEps; - - @Inject() - baseSysParamService: BaseSysParamService; - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Get('/param', { summary: '参数配置' }) - async param(@Query('key') key: string) { - if (!this.allowKeys.includes(key)) { - return this.fail('非法操作'); - } - return this.ok(await this.baseSysParamService.dataByKey(key)); - } - - /** - * 实体信息与路径 - * @returns - */ - @CoolTag(TagTypes.IGNORE_TOKEN) - @Get('/eps', { summary: '实体信息与路径' }) - public async getEps() { - return this.ok(this.eps.app); - } - - /** - * 文件上传 - */ - @Post('/upload', { summary: '文件上传' }) - async upload() { - const file = await this.pluginService.getInstance('upload'); - return this.ok(await file.upload(this.ctx)); - } - - /** - * 文件上传模式,本地或者云存储 - */ - @Get('/uploadMode', { summary: '文件上传模式' }) - async uploadMode() { - const file = await this.pluginService.getInstance('upload'); - return this.ok(await file.getMode()); - } -} diff --git a/src/modules/base/db.json b/src/modules/base/db.json deleted file mode 100644 index 81ffd6f..0000000 --- a/src/modules/base/db.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "base_sys_param": [ - { - "keyName": "rich", - "name": "富文本参数", - "data": "

这是一个富文本

xxx

xxxxxxxxxx


", - "dataType": 1, - "remark": null - }, - { - "keyName": "json", - "name": "JSON参数", - "data": "{\n \"code\": 111233\n}", - "dataType": 0, - "remark": null - }, - { - "keyName": "file", - "name": "文件", - "data": "", - "dataType": 2, - "remark": null - }, - { - "keyName": "text", - "name": "测试", - "data": "这是一段字符串", - "dataType": 0, - "remark": null - } - ], - "base_sys_conf": [ - { - "cKey": "logKeep", - "cValue": "31" - }, - { - "cKey": "recycleKeep", - "cValue": "31" - } - ], - "base_sys_department": [ - { - "id": 1, - "name": "COOL", - "parentId": null, - "orderNum": 0 - }, - { - "id": 11, - "name": "开发", - "parentId": 12, - "orderNum": 2 - }, - { - "id": 12, - "name": "测试", - "parentId": 1, - "orderNum": 1 - }, - { - "id": 13, - "name": "游客", - "parentId": 1, - "orderNum": 3 - } - ], - "base_sys_role": [ - { - "id": 1, - "userId": "1", - "name": "超管", - "label": "admin", - "remark": "最高权限的角色", - "relevance": 1, - "menuIdList": "null", - "departmentIdList": "null" - } - ], - "base_sys_user": [ - { - "id": 1, - "departmentId": 1, - "name": "超级管理员", - "username": "admin", - "password": "e10adc3949ba59abbe56e057f20f883e", - "passwordV": 7, - "nickName": "管理员", - "headImg": "https://cool-js.com/admin/headimg.jpg", - "phone": "18000000000", - "email": "team@cool-js.com", - "status": 1, - "remark": "拥有最高权限的用户", - "socketId": null - } - ], - "base_sys_user_role": [ - { - "userId": 1, - "roleId": 1 - } - ] -} \ No newline at end of file diff --git a/src/modules/base/dto/login.ts b/src/modules/base/dto/login.ts deleted file mode 100644 index 5b4b30c..0000000 --- a/src/modules/base/dto/login.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Rule, RuleType } from '@midwayjs/validate'; -/** - * 登录参数校验 - */ -export class LoginDTO { - // 用户名 - @Rule(RuleType.string().required()) - username: string; - - // 密码 - @Rule(RuleType.string().required()) - password: string; - - // 验证码ID - @Rule(RuleType.string().required()) - captchaId: string; - - // 验证码 - @Rule(RuleType.required()) - verifyCode: number; -} diff --git a/src/modules/base/entity/sys/conf.ts b/src/modules/base/entity/sys/conf.ts deleted file mode 100644 index fcfc5e1..0000000 --- a/src/modules/base/entity/sys/conf.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Column, Index, Entity } from 'typeorm'; -import { BaseEntity } from '@cool-midway/core'; - -/** - * 系统配置 - */ -@Entity('base_sys_conf') -export class BaseSysConfEntity extends BaseEntity { - @Index({ unique: true }) - @Column({ comment: '配置键' }) - cKey: string; - - @Column({ comment: '配置值' }) - cValue: string; -} diff --git a/src/modules/base/entity/sys/department.ts b/src/modules/base/entity/sys/department.ts deleted file mode 100644 index f340ecc..0000000 --- a/src/modules/base/entity/sys/department.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity } from 'typeorm'; - -/** - * 部门 - */ -@Entity('base_sys_department') -export class BaseSysDepartmentEntity extends BaseEntity { - @Column({ comment: '部门名称' }) - name: string; - - @Column({ comment: '上级部门ID', nullable: true }) - parentId: number; - - @Column({ comment: '排序', default: 0 }) - orderNum: number; - // 父菜单名称 - parentName: string; -} diff --git a/src/modules/base/entity/sys/log.ts b/src/modules/base/entity/sys/log.ts deleted file mode 100644 index c5fb13d..0000000 --- a/src/modules/base/entity/sys/log.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Index, Entity } from 'typeorm'; - -/** - * 系统日志 - */ -@Entity('base_sys_log') -export class BaseSysLogEntity extends BaseEntity { - @Index() - @Column({ comment: '用户ID', nullable: true }) - userId: number; - - @Index() - @Column({ comment: '行为' }) - action: string; - - @Index() - @Column({ comment: 'ip', nullable: true }) - ip: string; - - @Column({ comment: '参数', nullable: true, type: 'json' }) - params: string; -} diff --git a/src/modules/base/entity/sys/menu.ts b/src/modules/base/entity/sys/menu.ts deleted file mode 100644 index d816713..0000000 --- a/src/modules/base/entity/sys/menu.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity } from 'typeorm'; - -/** - * 菜单 - */ -@Entity('base_sys_menu') -export class BaseSysMenuEntity extends BaseEntity { - @Column({ comment: '父菜单ID', nullable: true }) - parentId: number; - - @Column({ comment: '菜单名称' }) - name: string; - - @Column({ comment: '菜单地址', nullable: true }) - router: string; - - @Column({ comment: '权限标识', type: 'text', nullable: true }) - perms: string; - - @Column({ - comment: '类型 0-目录 1-菜单 2-按钮', - default: 0, - }) - type: number; - - @Column({ comment: '图标', nullable: true }) - icon: string; - - @Column({ comment: '排序', default: 0 }) - orderNum: number; - - @Column({ comment: '视图地址', nullable: true }) - viewPath: string; - - @Column({ comment: '路由缓存', default: true }) - keepAlive: boolean; - - @Column({ comment: '是否显示', default: true }) - isShow: boolean; - - // 父菜单名称 - parentName: string; - - // 子菜单 - childMenus: any; -} diff --git a/src/modules/base/entity/sys/param.ts b/src/modules/base/entity/sys/param.ts deleted file mode 100644 index f147f89..0000000 --- a/src/modules/base/entity/sys/param.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Index, Entity } from 'typeorm'; - -/** - * 参数配置 - */ -@Entity('base_sys_param') -export class BaseSysParamEntity extends BaseEntity { - @Index({ unique: true }) - @Column({ comment: '键' }) - keyName: string; - - @Column({ comment: '名称' }) - name: string; - - @Column({ comment: '数据', type: 'text' }) - data: string; - - @Column({ - comment: '数据类型 0-字符串 1-富文本 2-文件 ', - default: 0, - }) - dataType: number; - - @Column({ comment: '备注', nullable: true }) - remark: string; -} diff --git a/src/modules/base/entity/sys/role.ts b/src/modules/base/entity/sys/role.ts deleted file mode 100644 index c1498d1..0000000 --- a/src/modules/base/entity/sys/role.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Index, Entity } from 'typeorm'; - -/** - * 角色 - */ -@Entity('base_sys_role') -export class BaseSysRoleEntity extends BaseEntity { - @Column({ comment: '用户ID' }) - userId: string; - - @Index({ unique: true }) - @Column({ comment: '名称' }) - name: string; - - @Index({ unique: true }) - @Column({ comment: '角色标签', nullable: true, length: 50 }) - label: string; - - @Column({ comment: '备注', nullable: true }) - remark: string; - - @Column({ comment: '数据权限是否关联上下级', default: false }) - relevance: boolean; - - @Column({ comment: '菜单权限', type: 'json' }) - menuIdList: number[]; - - @Column({ comment: '部门权限', type: 'json' }) - departmentIdList: number[]; -} diff --git a/src/modules/base/entity/sys/role_department.ts b/src/modules/base/entity/sys/role_department.ts deleted file mode 100644 index e0a52a8..0000000 --- a/src/modules/base/entity/sys/role_department.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity } from 'typeorm'; - -/** - * 角色部门 - */ -@Entity('base_sys_role_department') -export class BaseSysRoleDepartmentEntity extends BaseEntity { - @Column({ comment: '角色ID' }) - roleId: number; - - @Column({ comment: '部门ID' }) - departmentId: number; -} diff --git a/src/modules/base/entity/sys/role_menu.ts b/src/modules/base/entity/sys/role_menu.ts deleted file mode 100644 index 667e312..0000000 --- a/src/modules/base/entity/sys/role_menu.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity } from 'typeorm'; - -/** - * 角色菜单 - */ -@Entity('base_sys_role_menu') -export class BaseSysRoleMenuEntity extends BaseEntity { - @Column({ comment: '角色ID' }) - roleId: number; - - @Column({ comment: '菜单ID' }) - menuId: number; -} diff --git a/src/modules/base/entity/sys/user.ts b/src/modules/base/entity/sys/user.ts deleted file mode 100644 index a97e7c9..0000000 --- a/src/modules/base/entity/sys/user.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Index, Entity } from 'typeorm'; - -/** - * 系统用户 - */ -@Entity('base_sys_user') -export class BaseSysUserEntity extends BaseEntity { - @Index() - @Column({ comment: '部门ID', nullable: true }) - departmentId: number; - - @Column({ comment: '姓名', nullable: true }) - name: string; - - @Index({ unique: true }) - @Column({ comment: '用户名', length: 100 }) - username: string; - - @Column({ comment: '密码' }) - password: string; - - @Column({ - comment: '密码版本, 作用是改完密码,让原来的token失效', - default: 1, - }) - passwordV: number; - - @Column({ comment: '昵称', nullable: true }) - nickName: string; - - @Column({ comment: '头像', nullable: true }) - headImg: string; - - @Index() - @Column({ comment: '手机', nullable: true, length: 20 }) - phone: string; - - @Column({ comment: '邮箱', nullable: true }) - email: string; - - @Column({ comment: '备注', nullable: true }) - remark: string; - - @Column({ comment: '状态 0-禁用 1-启用', default: 1 }) - status: number; - // 部门名称 - departmentName: string; - // 角色ID列表 - roleIdList: number[]; - - @Column({ comment: 'socketId', nullable: true }) - socketId: string; -} diff --git a/src/modules/base/entity/sys/user_role.ts b/src/modules/base/entity/sys/user_role.ts deleted file mode 100644 index c15f00c..0000000 --- a/src/modules/base/entity/sys/user_role.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity } from 'typeorm'; - -/** - * 用户角色 - */ -@Entity('base_sys_user_role') -export class BaseSysUserRoleEntity extends BaseEntity { - @Column({ comment: '用户ID' }) - userId: number; - - @Column({ comment: '角色ID' }) - roleId: number; -} diff --git a/src/modules/base/event/app.ts b/src/modules/base/event/app.ts deleted file mode 100644 index 508b79b..0000000 --- a/src/modules/base/event/app.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { CoolEvent, Event } from '@cool-midway/core'; -import { App, Config, ILogger, Logger } from '@midwayjs/core'; -import { IMidwayKoaApplication } from '@midwayjs/koa'; -import * as fs from 'fs'; -import * as path from 'path'; -import { v1 as uuid } from 'uuid'; - -/** - * 修改jwt.secret - */ -@CoolEvent() -export class BaseAppEvent { - @Logger() - coreLogger: ILogger; - - @Config('module') - config; - - @Config('keys') - configKeys; - - @Config('koa.port') - port; - - @App() - app: IMidwayKoaApplication; - - @Event('onMenuInit') - async onMenuInit() { - if (this.app.getEnv() != 'local') return; - this.checkConfig(); - this.checkKeys(); - } - - @Event('onServerReady') - async onServerReady() { - this.coreLogger.info(`服务启动成功,端口:${this.port}`); - } - - /** - * 检查配置 - */ - async checkConfig() { - if (this.config.base.jwt.secret == 'cool-admin-xxxxxx') { - this.coreLogger.warn( - '\x1B[36m 检测到模块[base] jwt.secret 配置是默认值,请不要关闭!即将自动修改... \x1B[0m' - ); - setTimeout(() => { - const filePath = path.join( - this.app.getBaseDir(), - '..', - 'src', - 'modules', - 'base', - 'config.ts' - ); - // 替换文件内容 - let fileData = fs.readFileSync(filePath, 'utf8'); - const secret = uuid().replace(/-/g, ''); - this.config.base.jwt.secret = secret; - fs.writeFileSync( - filePath, - fileData.replace('cool-admin-xxxxxx', secret) - ); - this.coreLogger.info( - '\x1B[36m [cool:module:base] midwayjs cool module base auto modify jwt.secret\x1B[0m' - ); - }, 6000); - } - } - - /** - * 检查keys - */ - async checkKeys() { - if (this.configKeys == 'cool-admin-keys-xxxxxx') { - this.coreLogger.warn( - '\x1B[36m 检测到基础配置[Keys] 是默认值,请不要关闭!即将自动修改... \x1B[0m' - ); - setTimeout(() => { - const filePath = path.join( - this.app.getBaseDir(), - '..', - 'src', - 'config', - 'config.default.ts' - ); - // 替换文件内容 - let fileData = fs.readFileSync(filePath, 'utf8'); - const secret = uuid().replace(/-/g, ''); - this.config.base.jwt.secret = secret; - fs.writeFileSync( - filePath, - fileData.replace('cool-admin-keys-xxxxxx', secret) - ); - this.coreLogger.info( - '\x1B[36m [cool:module:base] midwayjs cool keys auto modify \x1B[0m' - ); - }, 6000); - } - } -} diff --git a/src/modules/base/event/menu.ts b/src/modules/base/event/menu.ts deleted file mode 100644 index 3257b43..0000000 --- a/src/modules/base/event/menu.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { CoolEvent, CoolEventManager, Event } from '@cool-midway/core'; -import { BaseSysMenuService } from '../service/sys/menu'; -import { - App, - ILogger, - IMidwayApplication, - Inject, - Logger, -} from '@midwayjs/core'; - -/** - * 导入菜单 - */ -@CoolEvent() -export class BaseMenuEvent { - @Logger() - coreLogger: ILogger; - - @Inject() - baseSysMenuService: BaseSysMenuService; - - @App() - app: IMidwayApplication; - - @Inject() - coolEventManager: CoolEventManager; - - @Event('onMenuImport') - async onMenuImport(datas) { - for (const module in datas) { - await this.baseSysMenuService.import(datas[module]); - this.coreLogger.info( - '\x1B[36m [cool:module:base] midwayjs cool module base import [' + - module + - '] module menu success \x1B[0m' - ); - } - this.coolEventManager.emit('onMenuInit', {}); - } -} diff --git a/src/modules/base/job/log.ts b/src/modules/base/job/log.ts deleted file mode 100644 index 0e35727..0000000 --- a/src/modules/base/job/log.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Job, IJob } from '@midwayjs/cron'; -import { FORMAT, ILogger, Inject } from '@midwayjs/core'; -import { BaseSysLogService } from '../service/sys/log'; - -/** - * 日志定时任务 - */ -@Job({ - cronTime: FORMAT.CRONTAB.EVERY_DAY, - start: true, -}) -export class BaseLogJob implements IJob { - @Inject() - baseSysLogService: BaseSysLogService; - - @Inject() - logger: ILogger; - - async onTick() { - this.logger.info('清除日志定时任务开始执行'); - const startTime = Date.now(); - await this.baseSysLogService.clear(); - this.logger.info(`清除日志定时任务结束,耗时:${Date.now() - startTime}ms`); - } -} diff --git a/src/modules/base/menu.json b/src/modules/base/menu.json deleted file mode 100644 index c0e0cfb..0000000 --- a/src/modules/base/menu.json +++ /dev/null @@ -1,875 +0,0 @@ -[ - { - "name": "系统管理", - "router": "/sys", - "perms": null, - "type": 0, - "icon": "icon-system", - "orderNum": 2, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "权限管理", - "router": null, - "perms": null, - "type": 0, - "icon": "icon-auth", - "orderNum": 1, - "viewPath": null, - "keepAlive": false, - "isShow": true, - "childMenus": [ - { - "name": "菜单列表", - "router": "/sys/menu", - "perms": null, - "type": 1, - "icon": "icon-menu", - "orderNum": 2, - "viewPath": "modules/base/views/menu/index.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "新增", - "router": null, - "perms": "base:sys:menu:add", - "type": 2, - "icon": null, - "orderNum": 1, - "viewPath": null, - "keepAlive": false, - "isShow": true, - "childMenus": [] - }, - { - "name": "删除", - "router": null, - "perms": "base:sys:menu:delete", - "type": 2, - "icon": null, - "orderNum": 2, - "viewPath": null, - "keepAlive": false, - "isShow": true, - "childMenus": [] - }, - { - "name": "查询", - "router": null, - "perms": "base:sys:menu:page,base:sys:menu:list,base:sys:menu:info", - "type": 2, - "icon": null, - "orderNum": 4, - "viewPath": null, - "keepAlive": false, - "isShow": true, - "childMenus": [] - }, - { - "name": "参数", - "router": "/test/aa", - "perms": null, - "type": 1, - "icon": "icon-goods", - "orderNum": 0, - "viewPath": "modules/base/views/info.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "编辑", - "router": null, - "perms": "base:sys:menu:info,base:sys:menu:update", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - }, - { - "name": "角色列表", - "router": "/sys/role", - "perms": null, - "type": 1, - "icon": "icon-dept", - "orderNum": 3, - "viewPath": "cool/modules/base/views/role.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "新增", - "router": null, - "perms": "base:sys:role:add", - "type": 2, - "icon": null, - "orderNum": 1, - "viewPath": null, - "keepAlive": false, - "isShow": true, - "childMenus": [] - }, - { - "name": "删除", - "router": null, - "perms": "base:sys:role:delete", - "type": 2, - "icon": null, - "orderNum": 2, - "viewPath": null, - "keepAlive": false, - "isShow": true, - "childMenus": [] - }, - { - "name": "修改", - "router": null, - "perms": "base:sys:role:update", - "type": 2, - "icon": null, - "orderNum": 3, - "viewPath": null, - "keepAlive": false, - "isShow": true, - "childMenus": [] - }, - { - "name": "查询", - "router": null, - "perms": "base:sys:role:page,base:sys:role:list,base:sys:role:info", - "type": 2, - "icon": null, - "orderNum": 4, - "viewPath": null, - "keepAlive": false, - "isShow": true, - "childMenus": [] - } - ] - }, - { - "name": "用户列表", - "router": "/sys/user", - "perms": null, - "type": 1, - "icon": "icon-user", - "orderNum": 0, - "viewPath": "modules/base/views/user/index.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "部门列表", - "router": null, - "perms": "base:sys:department:list", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "新增部门", - "router": null, - "perms": "base:sys:department:add", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "更新部门", - "router": null, - "perms": "base:sys:department:update", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "删除部门", - "router": null, - "perms": "base:sys:department:delete", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "部门排序", - "router": null, - "perms": "base:sys:department:order", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "用户转移", - "router": null, - "perms": "base:sys:user:move", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "新增", - "router": null, - "perms": "base:sys:user:add", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "删除", - "router": null, - "perms": "base:sys:user:delete", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "修改", - "router": null, - "perms": "base:sys:user:delete,base:sys:user:update", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "查询", - "router": null, - "perms": "base:sys:user:page,base:sys:user:list,base:sys:user:info", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - } - ] - }, - { - "name": "参数配置", - "router": null, - "perms": null, - "type": 0, - "icon": "icon-params", - "orderNum": 3, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "参数列表", - "router": "/sys/param", - "perms": null, - "type": 1, - "icon": "icon-menu", - "orderNum": 0, - "viewPath": "cool/modules/base/views/param.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "新增", - "router": null, - "perms": "base:sys:param:add", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "修改", - "router": null, - "perms": "base:sys:param:info,base:sys:param:update", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "删除", - "router": null, - "perms": "base:sys:param:delete", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "查看", - "router": null, - "perms": "base:sys:param:page,base:sys:param:list,base:sys:param:info", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - } - ] - }, - { - "name": "监控管理", - "router": null, - "perms": null, - "type": 0, - "icon": "icon-monitor", - "orderNum": 9, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "请求日志", - "router": "/sys/log", - "perms": null, - "type": 1, - "icon": "icon-log", - "orderNum": 1, - "viewPath": "cool/modules/base/views/log.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "权限", - "router": null, - "perms": "base:sys:log:page,base:sys:log:clear,base:sys:log:getKeep,base:sys:log:setKeep", - "type": 2, - "icon": null, - "orderNum": 1, - "viewPath": null, - "keepAlive": false, - "isShow": true, - "childMenus": [] - } - ] - } - ] - }, - { - "name": "任务管理", - "router": null, - "perms": null, - "type": 0, - "icon": "icon-activity", - "orderNum": 9, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "任务列表", - "router": "/task/list", - "perms": null, - "type": 1, - "icon": "icon-menu", - "orderNum": 0, - "viewPath": "modules/task/views/list.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "权限", - "router": null, - "perms": "task:info:page,task:info:list,task:info:info,task:info:add,task:info:delete,task:info:update,task:info:stop,task:info:start,task:info:once,task:info:log", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - } - ] - } - ] - }, - { - "name": "框架教程", - "router": "/tutorial", - "perms": null, - "type": 0, - "icon": "icon-task", - "orderNum": 98, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "文档官网", - "router": "/tutorial/doc", - "perms": null, - "type": 1, - "icon": "icon-log", - "orderNum": 0, - "viewPath": "https://admin.cool-js.com", - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "crud 示例", - "router": "/demo/crud", - "perms": null, - "type": 1, - "icon": "icon-favor", - "orderNum": 1, - "viewPath": "modules/demo/views/crud/index.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - }, - { - "name": "通用", - "router": null, - "perms": null, - "type": 0, - "icon": "icon-radioboxfill", - "orderNum": 99, - "viewPath": null, - "keepAlive": true, - "isShow": false, - "childMenus": [ - { - "name": "图片上传", - "router": null, - "perms": "space:info:page,space:info:list,space:info:info,space:info:add,space:info:delete,space:info:update,space:type:page,space:type:list,space:type:info,space:type:add,space:type:delete,space:type:update", - "type": 2, - "icon": null, - "orderNum": 1, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - }, - { - "name": "首页", - "router": "/", - "perms": null, - "type": 1, - "icon": null, - "orderNum": 0, - "viewPath": "modules/demo/views/home/index.vue", - "keepAlive": true, - "isShow": false, - "childMenus": [] - }, - { - "name": "数据管理", - "router": null, - "perms": null, - "type": 0, - "icon": "icon-data", - "orderNum": 7, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "字典管理", - "router": "/dict/list", - "perms": null, - "type": 1, - "icon": "icon-dict", - "orderNum": 3, - "viewPath": "modules/dict/views/list.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "删除", - "router": null, - "perms": "dict:info:delete", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "修改", - "router": null, - "perms": "dict:info:update,dict:info:info", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "获得字典数据", - "router": null, - "perms": "dict:info:data", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "单个信息", - "router": null, - "perms": "dict:info:info", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "列表查询", - "router": null, - "perms": "dict:info:list", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "分页查询", - "router": null, - "perms": "dict:info:page", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "新增", - "router": null, - "perms": "dict:info:add", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "组权限", - "router": null, - "perms": "dict:type:list,dict:type:update,dict:type:delete,dict:type:add", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "字典类型", - "router": null, - "perms": "dict:type:delete,dict:type:update,dict:type:info,dict:type:list,dict:type:page,dict:type:add", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - }, - { - "name": "数据回收站", - "router": "/recycle/data", - "perms": null, - "type": 1, - "icon": "icon-delete", - "orderNum": 6, - "viewPath": "modules/recycle/views/data.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "恢复数据", - "router": null, - "perms": "recycle:data:restore", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "单个信息", - "router": null, - "perms": "recycle:data:info", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "分页查询", - "router": null, - "perms": "recycle:data:page", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - }, - { - "name": "文件管理", - "router": "/upload/list", - "perms": null, - "type": 1, - "icon": "icon-log", - "orderNum": 5, - "viewPath": "modules/space/views/list.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "权限", - "router": null, - "perms": "space:type:delete,space:type:update,space:type:info,space:type:list,space:type:page,space:type:add,space:info:getConfig,space:info:delete,space:info:update,space:info:info,space:info:list,space:info:page,space:info:add", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - } - ] - }, - { - "name": "用户管理", - "router": null, - "perms": null, - "type": 0, - "icon": "icon-user", - "orderNum": 11, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "用户列表", - "router": "/user/list", - "perms": null, - "type": 1, - "icon": "icon-menu", - "orderNum": 1, - "viewPath": "modules/user/views/list.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "删除", - "router": null, - "perms": "user:info:delete", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "修改", - "router": null, - "perms": "user:info:update,user:info:info", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "单个信息", - "router": null, - "perms": "user:info:info", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "列表查询", - "router": null, - "perms": "user:info:list", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "分页查询", - "router": null, - "perms": "user:info:page", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - }, - { - "name": "新增", - "router": null, - "perms": "user:info:add", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - } - ] - }, - { - "name": "扩展管理", - "router": null, - "perms": null, - "type": 0, - "icon": "icon-favor", - "orderNum": 8, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "后端插件", - "router": "/helper/plugins/serve", - "perms": null, - "type": 1, - "icon": "icon-component", - "orderNum": 2, - "viewPath": "modules/helper/views/plugins/serve.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [ - { - "name": "权限", - "router": null, - "perms": "plugin:info:install,plugin:info:delete,plugin:info:update,plugin:info:page,plugin:info:info", - "type": 2, - "icon": null, - "orderNum": 0, - "viewPath": null, - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - }, - { - "name": "前端插件", - "router": "/helper/plugins/vue", - "perms": null, - "type": 1, - "icon": "icon-vue", - "orderNum": 1, - "viewPath": "modules/helper/views/plugins/vue.vue", - "keepAlive": true, - "isShow": true, - "childMenus": [] - } - ] - } -] \ No newline at end of file diff --git a/src/modules/base/middleware/authority.ts b/src/modules/base/middleware/authority.ts deleted file mode 100644 index 47e4381..0000000 --- a/src/modules/base/middleware/authority.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { App, Config, Inject, Middleware } from '@midwayjs/decorator'; -import * as _ from 'lodash'; -import { CoolUrlTagData, RESCODE, TagTypes } from '@cool-midway/core'; -import * as jwt from 'jsonwebtoken'; -import { NextFunction, Context } from '@midwayjs/koa'; -import { - IMiddleware, - IMidwayApplication, - Init, - InjectClient, -} from '@midwayjs/core'; -import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; - -/** - * 权限校验 - */ -@Middleware() -export class BaseAuthorityMiddleware - implements IMiddleware -{ - @Config('koa.globalPrefix') - prefix; - - @Config('module.base') - jwtConfig; - - @InjectClient(CachingFactory, 'default') - midwayCache: MidwayCache; - - @Inject() - coolUrlTagData: CoolUrlTagData; - - @App() - app: IMidwayApplication; - - ignoreUrls: string[] = []; - - @Init() - async init() { - this.ignoreUrls = this.coolUrlTagData.byKey(TagTypes.IGNORE_TOKEN, 'admin'); - } - - resolve() { - return async (ctx: Context, next: NextFunction) => { - let statusCode = 200; - let { url } = ctx; - url = url.replace(this.prefix, '').split('?')[0]; - const token = ctx.get('Authorization'); - const adminUrl = '/admin/'; - // 路由地址为 admin前缀的 需要权限校验 - if (_.startsWith(url, adminUrl)) { - try { - ctx.admin = jwt.verify(token, this.jwtConfig.jwt.secret); - if (ctx.admin.isRefresh) { - ctx.status = 401; - ctx.body = { - code: RESCODE.COMMFAIL, - message: '登录失效~', - }; - return; - } - } catch (error) {} - // 使用matchUrl方法来检查URL是否应该被忽略 - const isIgnored = this.ignoreUrls.some(pattern => - this.matchUrl(pattern, url) - ); - if (isIgnored) { - await next(); - return; - } - if (ctx.admin) { - const rToken = await this.midwayCache.get( - `admin:token:${ctx.admin.userId}` - ); - // 判断密码版本是否正确 - const passwordV = await this.midwayCache.get( - `admin:passwordVersion:${ctx.admin.userId}` - ); - if (passwordV != ctx.admin.passwordVersion) { - ctx.status = 401; - ctx.body = { - code: RESCODE.COMMFAIL, - message: '登录失效~', - }; - return; - } - // 超管拥有所有权限 - if (ctx.admin.username == 'admin' && !ctx.admin.isRefresh) { - if (rToken !== token && this.jwtConfig.jwt.sso) { - ctx.status = 401; - ctx.body = { - code: RESCODE.COMMFAIL, - message: '登录失效~', - }; - return; - } else { - await next(); - return; - } - } - // 要登录每个人都有权限的接口 - if ( - new RegExp(`^${adminUrl}?.*/comm/`).test(url) || - // 字典接口 - url == '/admin/dict/info/data' - ) { - await next(); - return; - } - // 如果传的token是refreshToken则校验失败 - if (ctx.admin.isRefresh) { - ctx.status = 401; - ctx.body = { - code: RESCODE.COMMFAIL, - message: '登录失效~', - }; - return; - } - if (!rToken) { - ctx.status = 401; - ctx.body = { - code: RESCODE.COMMFAIL, - message: '登录失效或无权限访问~', - }; - return; - } - if (rToken !== token && this.jwtConfig.jwt.sso) { - statusCode = 401; - } else { - let perms: string[] = await this.midwayCache.get( - `admin:perms:${ctx.admin.userId}` - ); - if (!_.isEmpty(perms)) { - perms = perms.map(e => { - return e.replace(/:/g, '/'); - }); - if (!perms.includes(url.split('?')[0].replace('/admin/', ''))) { - statusCode = 403; - } - } else { - statusCode = 403; - } - } - } else { - statusCode = 401; - } - if (statusCode > 200) { - ctx.status = statusCode; - ctx.body = { - code: RESCODE.COMMFAIL, - message: '登录失效或无权限访问~', - }; - return; - } - } - await next(); - }; - } - - // 匹配URL的方法 - matchUrl(pattern, url) { - const patternSegments = pattern.split('/').filter(Boolean); - const urlSegments = url.split('/').filter(Boolean); - - // 如果段的数量不同,则无法匹配 - if (patternSegments.length !== urlSegments.length) { - return false; - } - - // 逐段进行匹配 - for (let i = 0; i < patternSegments.length; i++) { - if (patternSegments[i].startsWith(':')) { - // 如果模式段以':'开始,我们认为它是一个参数,可以匹配任何内容 - continue; - } - // 如果两个段不相同,则不匹配 - if (patternSegments[i] !== urlSegments[i]) { - return false; - } - } - - // 所有段都匹配 - return true; - } -} diff --git a/src/modules/base/middleware/log.ts b/src/modules/base/middleware/log.ts deleted file mode 100644 index 2b3486e..0000000 --- a/src/modules/base/middleware/log.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Middleware } from '@midwayjs/decorator'; -import * as _ from 'lodash'; -import { NextFunction, Context } from '@midwayjs/koa'; -import { IMiddleware } from '@midwayjs/core'; -import { BaseSysLogService } from '../service/sys/log'; - -/** - * 日志中间件 - */ -@Middleware() -export class BaseLogMiddleware implements IMiddleware { - resolve() { - return async (ctx: Context, next: NextFunction) => { - const baseSysLogService = await ctx.requestContext.getAsync( - BaseSysLogService - ); - baseSysLogService.record( - ctx, - ctx.url, - ctx.req.method === 'GET' ? ctx.request.query : ctx.request.body, - ctx.admin ? ctx.admin.userId : null - ); - await next(); - }; - } -} diff --git a/src/modules/base/service/sys/conf.ts b/src/modules/base/service/sys/conf.ts deleted file mode 100644 index dbff81d..0000000 --- a/src/modules/base/service/sys/conf.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { BaseSysConfEntity } from '../../entity/sys/conf'; - -/** - * 系统配置 - */ -@Provide() -export class BaseSysConfService extends BaseService { - @InjectEntityModel(BaseSysConfEntity) - baseSysConfEntity: Repository; - - /** - * 获得配置参数值 - * @param key - */ - async getValue(key) { - const conf = await this.baseSysConfEntity.findOneBy({ cKey: key }); - if (conf) { - return conf.cValue; - } - } - - /** - * 更新配置参数 - * @param cKey - * @param cValue - */ - async updateVaule(cKey, cValue) { - await this.baseSysConfEntity - .createQueryBuilder() - .update() - .where({ cKey }) - .set({ cKey, cValue }) - .execute(); - } -} diff --git a/src/modules/base/service/sys/data.ts b/src/modules/base/service/sys/data.ts deleted file mode 100644 index 42b03c9..0000000 --- a/src/modules/base/service/sys/data.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { DataSource } from 'typeorm'; - -export class TempDataSource extends DataSource { - /** - * 重新构造元数据 - */ - async buildMetadatas() { - await super.buildMetadatas(); - } -} diff --git a/src/modules/base/service/sys/department.ts b/src/modules/base/service/sys/department.ts deleted file mode 100644 index 714e882..0000000 --- a/src/modules/base/service/sys/department.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Inject, Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { In, Repository } from 'typeorm'; -import { BaseSysDepartmentEntity } from '../../entity/sys/department'; -import * as _ from 'lodash'; -import { BaseSysRoleDepartmentEntity } from '../../entity/sys/role_department'; -import { BaseSysPermsService } from './perms'; -import { BaseSysUserEntity } from '../../entity/sys/user'; - -/** - * 描述 - */ -@Provide() -export class BaseSysDepartmentService extends BaseService { - @InjectEntityModel(BaseSysDepartmentEntity) - baseSysDepartmentEntity: Repository; - - @InjectEntityModel(BaseSysUserEntity) - baseSysUserEntity: Repository; - - @InjectEntityModel(BaseSysRoleDepartmentEntity) - baseSysRoleDepartmentEntity: Repository; - - @Inject() - baseSysPermsService: BaseSysPermsService; - - @Inject() - ctx; - - /** - * 获得部门菜单 - */ - async list() { - // 部门权限 - const permsDepartmentArr = await this.baseSysPermsService.departmentIds( - this.ctx.admin.userId - ); - - // 过滤部门权限 - const find = this.baseSysDepartmentEntity.createQueryBuilder('a'); - if (this.ctx.admin.username !== 'admin') - find.andWhere('a.id in (:...ids)', { - ids: !_.isEmpty(permsDepartmentArr) ? permsDepartmentArr : [null], - }); - find.addOrderBy('a.orderNum', 'ASC'); - const departments: BaseSysDepartmentEntity[] = await find.getMany(); - - if (!_.isEmpty(departments)) { - departments.forEach(e => { - const parentMenu = departments.filter(m => { - e.parentId = parseInt(e.parentId + ''); - if (e.parentId == m.id) { - return m.name; - } - }); - if (!_.isEmpty(parentMenu)) { - e.parentName = parentMenu[0].name; - } - }); - } - return departments; - } - - /** - * 根据多个ID获得部门权限信息 - * @param {[]} roleIds 数组 - * @param isAdmin 是否超管 - */ - async getByRoleIds(roleIds: number[], isAdmin) { - if (!_.isEmpty(roleIds)) { - if (isAdmin) { - const result = await this.baseSysDepartmentEntity.find(); - return result.map(e => { - return e.id; - }); - } - const result = await this.baseSysRoleDepartmentEntity - .createQueryBuilder('a') - .where('a.roleId in (:...roleIds)', { roleIds }) - .getMany(); - if (!_.isEmpty(result)) { - return _.uniq( - result.map(e => { - return e.departmentId; - }) - ); - } - } - return []; - } - - /** - * 部门排序 - * @param params - */ - async order(params) { - for (const e of params) { - await this.baseSysDepartmentEntity.update(e.id, e); - } - } - - /** - * 删除 - */ - async delete(ids: number[]) { - const { deleteUser } = this.ctx.request.body; - await super.delete(ids); - if (deleteUser) { - await this.baseSysUserEntity.delete({ departmentId: In(ids) }); - } else { - const topDepartment = await this.baseSysDepartmentEntity - .createQueryBuilder('a') - .where('a.parentId is null') - .getOne(); - if (topDepartment) { - await this.baseSysUserEntity.update( - { departmentId: In(ids) }, - { departmentId: topDepartment.id } - ); - } - } - } -} diff --git a/src/modules/base/service/sys/log.ts b/src/modules/base/service/sys/log.ts deleted file mode 100644 index 2ed448e..0000000 --- a/src/modules/base/service/sys/log.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Inject, Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { LessThan, Repository } from 'typeorm'; -import * as _ from 'lodash'; -import { BaseSysLogEntity } from '../../entity/sys/log'; -import * as moment from 'moment'; -import { Utils } from '../../../../comm/utils'; -import { BaseSysConfService } from './conf'; -import { Context } from '@midwayjs/koa'; - -/** - * 描述 - */ -@Provide() -export class BaseSysLogService extends BaseService { - @Inject() - ctx; - - @Inject() - utils: Utils; - - @InjectEntityModel(BaseSysLogEntity) - baseSysLogEntity: Repository; - - @Inject() - baseSysConfService: BaseSysConfService; - - /** - * 记录 - * @param url URL地址 - * @param params 参数 - * @param userId 用户ID - */ - async record(context: Context, url, params, userId) { - const ip = await this.utils.getReqIP(context); - const sysLog = new BaseSysLogEntity(); - sysLog.userId = userId; - sysLog.ip = typeof ip === 'string' ? ip : ip.join(','); - sysLog.action = url.split('?')[0]; - sysLog.params = params; - await this.baseSysLogEntity.insert(sysLog); - } - - /** - * 日志 - * @param isAll 是否清除全部 - */ - async clear(isAll?) { - if (isAll) { - await this.baseSysLogEntity.clear(); - return; - } - const keepDay = await this.baseSysConfService.getValue('logKeep'); - if (keepDay) { - const beforeDate = moment().add(-keepDay, 'days').startOf('day').toDate(); - await this.baseSysLogEntity.delete({ createTime: LessThan(beforeDate) }); - } else { - await this.baseSysLogEntity.clear(); - } - } -} diff --git a/src/modules/base/service/sys/login.ts b/src/modules/base/service/sys/login.ts deleted file mode 100644 index f4faf87..0000000 --- a/src/modules/base/service/sys/login.ts +++ /dev/null @@ -1,251 +0,0 @@ -import { Inject, Provide, Config, InjectClient } from '@midwayjs/decorator'; -import { BaseService, CoolCommException } from '@cool-midway/core'; -import { LoginDTO } from '../../dto/login'; -import * as svgCaptcha from 'svg-captcha'; -import { v1 as uuid } from 'uuid'; -import { BaseSysUserEntity } from '../../entity/sys/user'; -import { Repository } from 'typeorm'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import * as md5 from 'md5'; -import { BaseSysRoleService } from './role'; -import * as _ from 'lodash'; -import { BaseSysMenuService } from './menu'; -import { BaseSysDepartmentService } from './department'; -import * as jwt from 'jsonwebtoken'; -import * as svgToDataURL from 'mini-svg-data-uri'; -import { Context } from '@midwayjs/koa'; -import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; -import { readFileSync } from 'fs'; -const { svg2png, initialize } = require('svg2png-wasm'); -initialize(readFileSync('./node_modules/svg2png-wasm/svg2png_wasm_bg.wasm')); - -/** - * 登录 - */ -@Provide() -export class BaseSysLoginService extends BaseService { - @InjectClient(CachingFactory, 'default') - midwayCache: MidwayCache; - - @InjectEntityModel(BaseSysUserEntity) - baseSysUserEntity: Repository; - - @Inject() - baseSysRoleService: BaseSysRoleService; - - @Inject() - baseSysMenuService: BaseSysMenuService; - - @Inject() - baseSysDepartmentService: BaseSysDepartmentService; - - @Inject() - ctx: Context; - - @Config('module.base') - coolConfig; - - /** - * 登录 - * @param login - */ - async login(login: LoginDTO) { - const { username, captchaId, verifyCode, password } = login; - // 校验验证码 - const checkV = await this.captchaCheck(captchaId, verifyCode); - if (checkV) { - const user = await this.baseSysUserEntity.findOneBy({ username }); - // 校验用户 - if (user) { - // 校验用户状态及密码 - if (user.status === 0 || user.password !== md5(password)) { - throw new CoolCommException('账户或密码不正确~'); - } - } else { - throw new CoolCommException('账户或密码不正确~'); - } - // 校验角色 - const roleIds = await this.baseSysRoleService.getByUser(user.id); - if (_.isEmpty(roleIds)) { - throw new CoolCommException('该用户未设置任何角色,无法登录~'); - } - - // 生成token - const { expire, refreshExpire } = this.coolConfig.jwt.token; - const result = { - expire, - token: await this.generateToken(user, roleIds, expire), - refreshExpire, - refreshToken: await this.generateToken( - user, - roleIds, - refreshExpire, - true - ), - }; - - // 将用户相关信息保存到缓存 - const perms = await this.baseSysMenuService.getPerms(roleIds); - const departments = await this.baseSysDepartmentService.getByRoleIds( - roleIds, - user.username === 'admin' - ); - await this.midwayCache.set(`admin:department:${user.id}`, departments); - await this.midwayCache.set(`admin:perms:${user.id}`, perms); - await this.midwayCache.set(`admin:token:${user.id}`, result.token); - await this.midwayCache.set( - `admin:token:refresh:${user.id}`, - result.token - ); - - return result; - } else { - throw new CoolCommException('验证码不正确'); - } - } - - /** - * 验证码 - * @param type 图片验证码类型 svg - * @param width 宽 - * @param height 高 - */ - async captcha(type: string, width = 150, height = 50, color = '#fff') { - const svg = svgCaptcha.create({ - ignoreChars: 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM', - width, - height, - }); - const result = { - captchaId: uuid(), - data: svg.data.replace(/"/g, "'"), - }; - // 文字变白 - const rpList = [ - '#111', - '#222', - '#333', - '#444', - '#555', - '#666', - '#777', - '#888', - '#999', - ]; - rpList.forEach(rp => { - result.data = result.data['replaceAll'](rp, color); - }); - if (type === 'base64') { - result.data = svgToDataURL(result.data); - } - if (type === 'png') { - result.data = await svg2png(result.data, { - scale: 2, // optional - width, // optional - height, // optional - backgroundColor: 'white', // optional - }); - result.data = - 'data:image/png;base64,' + - Buffer.from(result.data, 'binary').toString('base64'); - } - // 半小时过期 - await this.midwayCache.set( - `verify:img:${result.captchaId}`, - svg.text.toLowerCase(), - 1800 * 1000 - ); - return result; - } - - /** - * 退出登录 - */ - async logout() { - if (!this.coolConfig.jwt.sso) return; - const { userId } = this.ctx.admin; - await this.midwayCache.del(`admin:department:${userId}`); - await this.midwayCache.del(`admin:perms:${userId}`); - await this.midwayCache.del(`admin:token:${userId}`); - await this.midwayCache.del(`admin:token:refresh:${userId}`); - await this.midwayCache.del(`admin:passwordVersion:${userId}`); - } - - /** - * 检验图片验证码 - * @param captchaId 验证码ID - * @param value 验证码 - */ - async captchaCheck(captchaId, value) { - const rv = await this.midwayCache.get(`verify:img:${captchaId}`); - if (!rv || !value || value.toLowerCase() !== rv) { - return false; - } else { - this.midwayCache.del(`verify:img:${captchaId}`); - return true; - } - } - - /** - * 生成token - * @param user 用户对象 - * @param roleIds 角色集合 - * @param expire 过期 - * @param isRefresh 是否是刷新 - */ - async generateToken(user, roleIds, expire, isRefresh?) { - await this.midwayCache.set( - `admin:passwordVersion:${user.id}`, - user.passwordV - ); - const tokenInfo = { - isRefresh: false, - roleIds, - username: user.username, - userId: user.id, - passwordVersion: user.passwordV, - }; - if (isRefresh) { - tokenInfo.isRefresh = true; - } - return jwt.sign(tokenInfo, this.coolConfig.jwt.secret, { - expiresIn: expire, - }); - } - - /** - * 刷新token - * @param token - */ - async refreshToken(token: string) { - const decoded = jwt.verify(token, this.coolConfig.jwt.secret); - if (decoded && decoded['isRefresh']) { - delete decoded['exp']; - delete decoded['iat']; - - const { expire, refreshExpire } = this.coolConfig.jwt.token; - decoded['isRefresh'] = false; - const result = { - expire, - token: jwt.sign(decoded, this.coolConfig.jwt.secret, { - expiresIn: expire, - }), - refreshExpire, - refreshToken: '', - }; - decoded['isRefresh'] = true; - result.refreshToken = jwt.sign(decoded, this.coolConfig.jwt.secret, { - expiresIn: refreshExpire, - }); - await this.midwayCache.set( - `admin:passwordVersion:${decoded['userId']}`, - decoded['passwordVersion'] - ); - await this.midwayCache.set( - `admin:token:${decoded['userId']}`, - result.token - ); - return result; - } - } -} diff --git a/src/modules/base/service/sys/menu.ts b/src/modules/base/service/sys/menu.ts deleted file mode 100644 index b07d132..0000000 --- a/src/modules/base/service/sys/menu.ts +++ /dev/null @@ -1,463 +0,0 @@ -import { App, IMidwayApplication, Scope, ScopeEnum } from '@midwayjs/core'; -import { ALL, Config, Inject, Provide } from '@midwayjs/decorator'; -import { BaseService, CoolCommException } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { In, Repository } from 'typeorm'; -import { BaseSysMenuEntity } from '../../entity/sys/menu'; -import * as _ from 'lodash'; -import { BaseSysPermsService } from './perms'; -import { Context } from '@midwayjs/koa'; -import { TempDataSource } from './data'; -// eslint-disable-next-line node/no-unpublished-import -import * as ts from 'typescript'; -import * as fs from 'fs'; -import * as pathUtil from 'path'; -import { BaseSysRoleMenuEntity } from '../../entity/sys/role_menu'; -import { BaseSysUserRoleEntity } from '../../entity/sys/user_role'; - -/** - * 菜单 - */ -@Scope(ScopeEnum.Request, { allowDowngrade: true }) -@Provide() -export class BaseSysMenuService extends BaseService { - @Inject() - ctx: Context; - - @InjectEntityModel(BaseSysMenuEntity) - baseSysMenuEntity: Repository; - - @InjectEntityModel(BaseSysRoleMenuEntity) - baseSysRoleMenuEntity: Repository; - - @Inject() - baseSysPermsService: BaseSysPermsService; - - @Config(ALL) - config; - - @App() - app: IMidwayApplication; - - /** - * 获得所有菜单 - */ - async list() { - const menus = await this.getMenus( - this.ctx.admin.roleIds, - this.ctx.admin.username === 'admin' - ); - if (!_.isEmpty(menus)) { - menus.forEach((e: any) => { - const parentMenu = menus.filter(m => { - e.parentId = parseInt(e.parentId); - if (e.parentId == m.id) { - return m.name; - } - }); - if (!_.isEmpty(parentMenu)) { - e.parentName = parentMenu[0].name; - } - }); - } - return menus; - } - - /** - * 修改之后 - * @param param - */ - async modifyAfter(param) { - if (param.id) { - await this.refreshPerms(param.id); - } - } - - /** - * 根据角色获得权限信息 - * @param {[]} roleIds 数组 - */ - async getPerms(roleIds) { - let perms = []; - if (!_.isEmpty(roleIds)) { - const find = await this.baseSysMenuEntity.createQueryBuilder('a'); - if (!roleIds.includes(1)) { - find.innerJoinAndSelect( - BaseSysRoleMenuEntity, - 'b', - 'a.id = b.menuId AND b.roleId in (:...roleIds)', - { roleIds } - ); - } - find.where('a.perms is not NULL'); - const result = await find.getMany(); - if (result) { - result.forEach(d => { - if (d.perms) { - perms = perms.concat(d.perms.split(',')); - } - }); - } - perms = _.uniq(perms); - perms = _.remove(perms, n => { - return !_.isEmpty(n); - }); - } - return _.uniq(perms); - } - - /** - * 获得用户菜单信息 - * @param roleIds - * @param isAdmin 是否是超管 - */ - async getMenus(roleIds, isAdmin) { - const find = this.baseSysMenuEntity.createQueryBuilder('a'); - if (!isAdmin) { - find.innerJoinAndSelect( - BaseSysRoleMenuEntity, - 'b', - 'a.id = b.menuId AND b.roleId in (:...roleIds)', - { roleIds } - ); - } - find.orderBy('a.orderNum', 'ASC'); - const list = await find.getMany(); - return _.uniqBy(list, 'id'); - } - - /** - * 删除 - * @param ids - */ - async delete(ids) { - let idArr; - if (ids instanceof Array) { - idArr = ids; - } else { - idArr = ids.split(','); - } - for (const id of idArr) { - await this.baseSysMenuEntity.delete({ id }); - await this.delChildMenu(id); - } - } - - /** - * 删除子菜单 - * @param id - */ - private async delChildMenu(id) { - await this.refreshPerms(id); - const delMenu = await this.baseSysMenuEntity.findBy({ parentId: id }); - if (_.isEmpty(delMenu)) { - return; - } - const delMenuIds = delMenu.map(e => { - return e.id; - }); - await this.baseSysMenuEntity.delete(delMenuIds); - for (const menuId of delMenuIds) { - await this.delChildMenu(menuId); - } - } - - /** - * 更新权限 - * @param menuId - */ - async refreshPerms(menuId) { - const find = this.baseSysRoleMenuEntity.createQueryBuilder('a'); - find.leftJoinAndSelect(BaseSysUserRoleEntity, 'b', 'a.roleId = b.roleId'); - find.where('a.menuId = :menuId', { menuId: menuId }); - find.select('b.userId', 'userId'); - const users = await find.getRawMany(); - // 刷新admin权限 - await this.baseSysPermsService.refreshPerms(1); - if (!_.isEmpty(users)) { - // 刷新其他权限 - for (const user of _.uniqBy(users, 'userId')) { - await this.baseSysPermsService.refreshPerms(user.userId); - } - } - } - - /** - * 解析实体和Controller - * @param entityString - * @param controller - * @param module - */ - async parse(entityString: string, controller: string, module: string) { - const tempDataSource = new TempDataSource({ - ...this.config.typeorm.dataSource.default, - entities: [], - }); - // 连接数据库 - await tempDataSource.initialize(); - const { newCode, className, oldTableName } = this.parseCode(entityString); - const code = ts.transpile( - `${newCode} - tempDataSource.options.entities.push(${className}) - `, - { - emitDecoratorMetadata: true, - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES2018, - removeComments: true, - experimentalDecorators: true, - noImplicitThis: true, - noUnusedLocals: true, - stripInternal: true, - skipLibCheck: true, - pretty: true, - declaration: true, - noImplicitAny: false, - } - ); - eval(code); - await tempDataSource.buildMetadatas(); - const meta = tempDataSource.getMetadata(className); - const columnArr = meta.columns; - await tempDataSource.destroy(); - - const commColums = []; - const columns = _.filter( - columnArr.map(e => { - return { - propertyName: e.propertyName, - type: typeof e.type == 'string' ? e.type : e.type.name.toLowerCase(), - length: e.length, - comment: e.comment, - nullable: e.isNullable, - }; - }), - o => { - if (['createTime', 'updateTime'].includes(o.propertyName)) { - commColums.push(o); - } - return o && !['createTime', 'updateTime'].includes(o.propertyName); - } - ).concat(commColums); - if (!controller) { - const tableNames = oldTableName.split('_'); - const fileName = tableNames[tableNames.length - 1]; - return { - columns, - className: className.replace('TEMP', ''), - tableName: oldTableName, - fileName, - path: `/admin/${module}/${fileName}`, - }; - } - const fileName = await this.fileName(controller); - return { - columns, - path: `/admin/${module}/${fileName}`, - }; - } - - /** - * 解析Entity类名 - * @param code - * @returns - */ - parseCode(code: string) { - try { - const oldClassName = code - .match('class(.*)extends')[1] - .replace(/\s*/g, ''); - const oldTableStart = code.indexOf('@Entity('); - const oldTableEnd = code.indexOf(')'); - - const oldTableName = code - .substring(oldTableStart + 9, oldTableEnd - 1) - .replace(/\s*/g, '') - // eslint-disable-next-line no-useless-escape - .replace(/\"/g, '') - // eslint-disable-next-line no-useless-escape - .replace(/\'/g, ''); - const className = `${oldClassName}TEMP`; - return { - newCode: code - .replace(oldClassName, className) - .replace(oldTableName, `func_${oldTableName}`), - className, - tableName: `func_${oldTableName}`, - oldTableName, - }; - } catch (err) { - throw new CoolCommException('代码结构不正确,请检查'); - } - } - - /** - * 创建代码 - * @param body body - */ - async create(body) { - const { module, entity, controller, service, fileName } = body; - const basePath = this.app.getBaseDir(); - const modulePath = pathUtil.join(basePath, '..', 'src', 'modules', module); - // 生成Entity - const entityPath = pathUtil.join(modulePath, 'entity', `${fileName}.ts`); - // 生成Controller - const controllerPath = pathUtil.join( - modulePath, - 'controller', - 'admin', - `${fileName}.ts` - ); - // 生成Service - const servicePath = pathUtil.join(modulePath, 'service', `${fileName}.ts`); - this.createConfigFile(module); - this.createFile(entityPath, entity); - this.createFile(controllerPath, controller); - this.createFile(servicePath, service); - } - - /** - * 创建配置文件 - * @param module - */ - async createConfigFile(module: string) { - const basePath = this.app.getBaseDir(); - const configFilePath = pathUtil.join( - basePath, - '..', - 'src', - 'modules', - module, - 'config.ts' - ); - if (!fs.existsSync(configFilePath)) { - const data = `import { ModuleConfig } from '@cool-midway/core'; - -/** - * 模块配置 - */ -export default () => { - return { - // 模块名称 - name: 'xxx', - // 模块描述 - description: 'xxx', - // 中间件,只对本模块有效 - middlewares: [], - // 中间件,全局有效 - globalMiddlewares: [], - // 模块加载顺序,默认为0,值越大越优先加载 - order: 0, - } as ModuleConfig; -}; -`; - await this.createFile(configFilePath, data); - } - } - - /** - * 找到文件名 - * @param controller - * @returns - */ - async fileName(controller: string) { - const regex = /import\s*{\s*\w+\s*}\s*from\s*'[^']*\/([\w-]+)';/; - const match = regex.exec(controller); - - if (match && match.length > 1) { - return match[1]; - } - - return null; - } - - /** - * 创建文件 - * @param filePath - * @param content - */ - async createFile(filePath: string, content: string) { - const folderPath = pathUtil.dirname(filePath); - if (!fs.existsSync(folderPath)) { - fs.mkdirSync(folderPath, { recursive: true }); - } - fs.writeFileSync(filePath, content); - } - - /** - * 导出菜单 - * @param ids - * @returns - */ - async export(ids: number[]) { - const result: any[] = []; - const menus = await this.baseSysMenuEntity.findBy({ id: In(ids) }); - - // 递归取出子菜单 - const getChildMenus = (parentId: number): any[] => { - const children = _.remove(menus, e => e.parentId == parentId); - children.forEach(child => { - child.childMenus = getChildMenus(child.id); - // 删除不需要的字段 - delete child.id; - delete child.createTime; - delete child.updateTime; - delete child.parentId; - }); - return children; - }; - - // lodash取出父级菜单(parentId为 null), 并从menus 删除 - const parentMenus = _.remove(menus, e => { - return e.parentId == null; - }); - - // 对于每个父级菜单,获取它的子菜单 - parentMenus.forEach(parent => { - parent.childMenus = getChildMenus(parent.id); - // 删除不需要的字段 - delete parent.id; - delete parent.createTime; - delete parent.updateTime; - delete parent.parentId; - - result.push(parent); - }); - - return result; - } - - /** - * 导入 - * @param menus - */ - async import(menus: any[]) { - // 递归保存子菜单 - const saveChildMenus = async (parentMenu: any, parentId: number | null) => { - const children = parentMenu.childMenus || []; - for (let child of children) { - const childData = { ...child, parentId: parentId }; // 保持与数据库的parentId字段的一致性 - delete childData.childMenus; // 删除childMenus属性,因为我们不想将它保存到数据库中 - - // 保存子菜单并获取其ID,以便为其子菜单设置parentId - const savedChild = await this.baseSysMenuEntity.save(childData); - - if (!_.isEmpty(child.childMenus)) { - await saveChildMenus(child, savedChild.id); - } - } - }; - - for (let menu of menus) { - const menuData = { ...menu }; - delete menuData.childMenus; // 删除childMenus属性,因为我们不想将它保存到数据库中 - - // 保存主菜单并获取其ID - const savedMenu = await this.baseSysMenuEntity.save(menuData); - - if (menu.childMenus && menu.childMenus.length > 0) { - await saveChildMenus(menu, savedMenu.id); - } - } - } -} diff --git a/src/modules/base/service/sys/param.ts b/src/modules/base/service/sys/param.ts deleted file mode 100644 index 7e75a26..0000000 --- a/src/modules/base/service/sys/param.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Inject, InjectClient, Provide } from '@midwayjs/decorator'; -import { BaseService, CoolCommException } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Not, Repository } from 'typeorm'; -import { BaseSysParamEntity } from '../../entity/sys/param'; -import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; - -/** - * 参数配置 - */ -@Provide() -export class BaseSysParamService extends BaseService { - @InjectEntityModel(BaseSysParamEntity) - baseSysParamEntity: Repository; - - @InjectClient(CachingFactory, 'default') - midwayCache: MidwayCache; - - /** - * 根据key获得对应的参数 - * @param key - */ - async dataByKey(key) { - let result: any = await this.midwayCache.get(`param:${key}`); - if (!result) { - result = await this.baseSysParamEntity.findOneBy({ keyName: key }); - this.midwayCache.set(`param:${key}`, result); - } - if (result) { - if (result.dataType == 0) { - try { - return JSON.parse(result.data); - } catch (error) { - return result.data; - } - } - if (result.dataType == 1) { - return result.data; - } - if (result.dataType == 2) { - return result.data.split(','); - } - } - return; - } - - /** - * 根据key获得对应的网页数据 - * @param key - */ - async htmlByKey(key) { - let html = '@title@content'; - let result: any = await this.midwayCache.get(`param:${key}`); - if (result) { - html = html - .replace('@content', result.data) - .replace('@title', result.name); - } else { - html = html.replace('@content', 'key notfound'); - } - return html; - } - - /** - * 添加或者修改 - * @param param - */ - async addOrUpdate(param: any, type): Promise { - const find = { - keyName: param.keyName, - }; - if (param.id) { - find['id'] = Not(param.id); - } - const check = await this.baseSysParamEntity.findOneBy(find); - if (check) { - throw new CoolCommException('存在相同的keyName'); - } - await super.addOrUpdate(param, type); - } - - /** - * 重新初始化缓存 - */ - async modifyAfter() { - const params = await this.baseSysParamEntity.find(); - for (const param of params) { - await this.midwayCache.set(`param:${param.keyName}`, param); - } - } -} diff --git a/src/modules/base/service/sys/perms.ts b/src/modules/base/service/sys/perms.ts deleted file mode 100644 index fc64f21..0000000 --- a/src/modules/base/service/sys/perms.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Inject, InjectClient, Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { BaseSysMenuService } from './menu'; -import { BaseSysRoleService } from './role'; -import { BaseSysDepartmentService } from './department'; -import { Context } from '@midwayjs/koa'; -import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; -import { BaseSysRoleEntity } from '../../entity/sys/role'; -import { In, Repository } from 'typeorm'; -import { InjectEntityModel } from '@midwayjs/typeorm'; - -/** - * 权限 - */ -@Provide() -export class BaseSysPermsService extends BaseService { - @InjectClient(CachingFactory, 'default') - midwayCache: MidwayCache; - - @Inject() - baseSysMenuService: BaseSysMenuService; - - @Inject() - baseSysRoleService: BaseSysRoleService; - - @Inject() - baseSysDepartmentService: BaseSysDepartmentService; - - @InjectEntityModel(BaseSysRoleEntity) - baseSysRoleEntity: Repository; - - @Inject() - ctx: Context; - base: any; - - /** - * 刷新权限 - * @param userId 用户ID - */ - async refreshPerms(userId) { - const roleIds = await this.baseSysRoleService.getByUser(userId); - const perms = await this.baseSysMenuService.getPerms(roleIds); - await this.midwayCache.set(`admin:perms:${userId}`, perms); - // 更新部门权限 - const departments = await this.baseSysDepartmentService.getByRoleIds( - roleIds, - await this.isAdmin(roleIds) - ); - await this.midwayCache.set(`admin:department:${userId}`, departments); - } - - /** - * 根据角色判断是不是超管 - * @param roleIds - */ - async isAdmin(roleIds: number[]) { - const roles = await this.baseSysRoleEntity.findBy({ id: In(roleIds) }); - const roleLabels = roles.map(item => item.label); - return roleLabels.includes('admin'); - } - - /** - * 获得权限菜单 - * @param roleIds - */ - async permmenu(roleIds: number[]) { - const perms = await this.baseSysMenuService.getPerms(roleIds); - const menus = await this.baseSysMenuService.getMenus( - roleIds, - this.ctx.admin.username === 'admin' - ); - return { perms, menus }; - } - - /** - * 根据用户ID获得部门权限 - * @param userId - * @return 部门ID数组 - */ - async departmentIds(userId: number) { - const department: any = await this.midwayCache.get( - `admin:department:${userId}` - ); - if (department) { - return department; - } else { - return []; - } - } -} diff --git a/src/modules/base/service/sys/role.ts b/src/modules/base/service/sys/role.ts deleted file mode 100644 index e013b52..0000000 --- a/src/modules/base/service/sys/role.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { Inject, Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { BaseSysRoleEntity } from '../../entity/sys/role'; -import { BaseSysUserRoleEntity } from '../../entity/sys/user_role'; -import * as _ from 'lodash'; -import { BaseSysRoleMenuEntity } from '../../entity/sys/role_menu'; -import { BaseSysRoleDepartmentEntity } from '../../entity/sys/role_department'; -import { BaseSysPermsService } from './perms'; -import { Brackets } from 'typeorm'; - -/** - * 角色 - */ -@Provide() -export class BaseSysRoleService extends BaseService { - @InjectEntityModel(BaseSysRoleEntity) - baseSysRoleEntity: Repository; - - @InjectEntityModel(BaseSysUserRoleEntity) - baseSysUserRoleEntity: Repository; - - @InjectEntityModel(BaseSysRoleMenuEntity) - baseSysRoleMenuEntity: Repository; - - @InjectEntityModel(BaseSysRoleDepartmentEntity) - baseSysRoleDepartmentEntity: Repository; - - @Inject() - baseSysPermsService: BaseSysPermsService; - - @Inject() - ctx; - - /** - * 根据用户ID获得所有用户角色 - * @param userId - */ - async getByUser(userId: number): Promise { - const userRole = await this.baseSysUserRoleEntity.findBy({ userId }); - if (!_.isEmpty(userRole)) { - return userRole.map(e => { - return e.roleId; - }); - } - return []; - } - - /** - * - * @param param - */ - async modifyAfter(param) { - if (param.id) { - this.updatePerms(param.id, param.menuIdList, param.departmentIdList); - } - } - - /** - * 更新权限 - * @param roleId - * @param menuIdList - * @param departmentIds - */ - async updatePerms(roleId, menuIdList?, departmentIds = []) { - // 更新菜单权限 - await this.baseSysRoleMenuEntity.delete({ roleId }); - await Promise.all( - menuIdList.map(async e => { - return await this.baseSysRoleMenuEntity.save({ roleId, menuId: e }); - }) - ); - // 更新部门权限 - await this.baseSysRoleDepartmentEntity.delete({ roleId }); - await Promise.all( - departmentIds.map(async e => { - return await this.baseSysRoleDepartmentEntity.save({ - roleId, - departmentId: e, - }); - }) - ); - // 刷新权限 - const userRoles = await this.baseSysUserRoleEntity.findBy({ roleId }); - for (const userRole of userRoles) { - await this.baseSysPermsService.refreshPerms(userRole.userId); - } - } - - /** - * 角色信息 - * @param id - */ - async info(id) { - const info = await this.baseSysRoleEntity.findOneBy({ id }); - if (info) { - const menus = await this.baseSysRoleMenuEntity.findBy( - id !== 1 ? { roleId: id } : {} - ); - const menuIdList = menus.map(e => { - return parseInt(e.menuId + ''); - }); - const departments = await this.baseSysRoleDepartmentEntity.findBy( - id !== 1 ? { roleId: id } : {} - ); - const departmentIdList = departments.map(e => { - return parseInt(e.departmentId + ''); - }); - return { - ...info, - menuIdList, - departmentIdList, - }; - } - return {}; - } - - async list() { - return this.baseSysRoleEntity - .createQueryBuilder('a') - .where( - new Brackets(qb => { - qb.where('a.id !=:id', { id: 1 }); // 超级管理员的角色不展示 - // 如果不是超管,只能看到自己新建的或者自己有的角色 - if (this.ctx.admin.username !== 'admin') { - qb.andWhere('(a.userId=:userId or a.id in (:...roleId))', { - userId: this.ctx.admin.userId, - roleId: this.ctx.admin.roleIds, - }); - } - }) - ) - .getMany(); - } -} diff --git a/src/modules/base/service/sys/user.ts b/src/modules/base/service/sys/user.ts deleted file mode 100644 index 96c3bc8..0000000 --- a/src/modules/base/service/sys/user.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { Inject, InjectClient, Provide } from '@midwayjs/decorator'; -import { BaseService, CoolCommException } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Equal, In, Repository } from 'typeorm'; -import { BaseSysUserEntity } from '../../entity/sys/user'; -import { BaseSysPermsService } from './perms'; -import * as _ from 'lodash'; -import { BaseSysUserRoleEntity } from '../../entity/sys/user_role'; -import * as md5 from 'md5'; -import { BaseSysDepartmentEntity } from '../../entity/sys/department'; -import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; - -/** - * 系统用户 - */ -@Provide() -export class BaseSysUserService extends BaseService { - @InjectEntityModel(BaseSysUserEntity) - baseSysUserEntity: Repository; - - @InjectEntityModel(BaseSysUserRoleEntity) - baseSysUserRoleEntity: Repository; - - @InjectEntityModel(BaseSysDepartmentEntity) - baseSysDepartmentEntity: Repository; - - @InjectClient(CachingFactory, 'default') - midwayCache: MidwayCache; - - @Inject() - baseSysPermsService: BaseSysPermsService; - - @Inject() - ctx; - - /** - * 分页查询 - * @param query - */ - async page(query) { - const { keyWord, status, departmentIds = [] } = query; - const permsDepartmentArr = await this.baseSysPermsService.departmentIds( - this.ctx.admin.userId - ); // 部门权限 - const sql = ` - SELECT - a.id,a.name,a.nickName,a.headImg,a.email,a.remark,a.status,a.createTime,a.updateTime,a.username,a.phone,a.departmentId, - b.name as "departmentName" - FROM - base_sys_user a - LEFT JOIN base_sys_department b on a.departmentId = b.id - WHERE 1 = 1 - ${this.setSql( - !_.isEmpty(departmentIds), - 'and a.departmentId in (?)', - [departmentIds] - )} - ${this.setSql(status, 'and a.status = ?', [status])} - ${this.setSql(keyWord, 'and (a.name LIKE ? or a.username LIKE ?)', [ - `%${keyWord}%`, - `%${keyWord}%`, - ])} - ${this.setSql(true, 'and a.username != ?', ['admin'])} - ${this.setSql( - this.ctx.admin.username !== 'admin', - 'and a.departmentId in (?)', - [!_.isEmpty(permsDepartmentArr) ? permsDepartmentArr : [null]] - )} `; - const result = await this.sqlRenderPage(sql, query); - // 匹配角色 - if (!_.isEmpty(result.list)) { - const userIds = result.list.map(e => e.id); - const roles = await this.nativeQuery( - 'SELECT b.name, a.userId FROM base_sys_user_role a LEFT JOIN base_sys_role b ON a.roleId = b.id WHERE a.userId in (?) ', - [userIds] - ); - result.list.forEach(e => { - e['roleName'] = roles - .filter(role => role.userId == e.id) - .map(role => role.name) - .join(','); - }); - } - return result; - } - - /** - * 移动部门 - * @param departmentId - * @param userIds - */ - async move(departmentId, userIds) { - await this.baseSysUserEntity.update({ id: In(userIds) }, { departmentId }); - } - - /** - * 获得个人信息 - */ - async person(userId) { - const info = await this.baseSysUserEntity.findOneBy({ - id: Equal(userId), - }); - delete info?.password; - return info; - } - - /** - * 更新用户角色关系 - * @param user - */ - async updateUserRole(user) { - if (_.isEmpty(user.roleIdList)) { - return; - } - if (user.username === 'admin') { - throw new CoolCommException('非法操作~'); - } - await this.baseSysUserRoleEntity.delete({ userId: user.id }); - if (user.roleIdList) { - for (const roleId of user.roleIdList) { - await this.baseSysUserRoleEntity.save({ userId: user.id, roleId }); - } - } - await this.baseSysPermsService.refreshPerms(user.id); - } - - /** - * 新增 - * @param param - */ - async add(param) { - const exists = await this.baseSysUserEntity.findOneBy({ - username: param.username, - }); - if (!_.isEmpty(exists)) { - throw new CoolCommException('用户名已经存在~'); - } - param.password = md5(param.password); - await this.baseSysUserEntity.save(param); - await this.updateUserRole(param); - return param.id; - } - - /** - * 根据ID获得信息 - * @param id - */ - public async info(id) { - const info = await this.baseSysUserEntity.findOneBy({ id }); - const userRoles = await this.nativeQuery( - 'select a.roleId from base_sys_user_role a where a.userId = ?', - [id] - ); - const department = await this.baseSysDepartmentEntity.findOneBy({ - id: info.departmentId, - }); - if (info) { - delete info.password; - if (userRoles) { - info.roleIdList = userRoles.map(e => { - return parseInt(e.roleId); - }); - } - } - delete info.password; - if (department) { - info.departmentName = department.name; - } - return info; - } - - /** - * 修改个人信息 - * @param param - */ - public async personUpdate(param) { - param.id = this.ctx.admin.userId; - if (!_.isEmpty(param.password)) { - param.password = md5(param.password); - const oldPassword = md5(param.oldPassword); - const userInfo = await this.baseSysUserEntity.findOneBy({ id: param.id }); - if (!userInfo) { - throw new CoolCommException('用户不存在'); - } - if (oldPassword !== userInfo.password) { - throw new CoolCommException('原密码错误'); - } - param.passwordV = userInfo.passwordV + 1; - await this.midwayCache.set( - `admin:passwordVersion:${param.id}`, - param.passwordV - ); - } else { - delete param.password; - } - await this.baseSysUserEntity.save(param); - } - - /** - * 修改 - * @param param 数据 - */ - async update(param) { - if (param.id && param.username === 'admin') { - throw new CoolCommException('非法操作~'); - } - if (!_.isEmpty(param.password)) { - param.password = md5(param.password); - const userInfo = await this.baseSysUserEntity.findOneBy({ id: param.id }); - if (!userInfo) { - throw new CoolCommException('用户不存在'); - } - param.passwordV = userInfo.passwordV + 1; - await this.midwayCache.set( - `admin:passwordVersion:${param.id}`, - param.passwordV - ); - } else { - delete param.password; - } - if (param.status === 0) { - await this.forbidden(param.id); - } - await this.baseSysUserEntity.save(param); - await this.updateUserRole(param); - } - - /** - * 禁用用户 - * @param userId - */ - async forbidden(userId) { - await this.midwayCache.del(`admin:token:${userId}`); - } -} diff --git a/src/modules/demo/config.ts b/src/modules/demo/config.ts deleted file mode 100644 index a0f978c..0000000 --- a/src/modules/demo/config.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ModuleConfig } from '@cool-midway/core'; - -/** - * 模块配置 - */ -export default () => { - return { - // 模块名称 - name: 'demo模块', - // 模块描述 - description: '演示用', - // 中间件,只对本模块有效 - middlewares: [], - // 中间件,全局有效 - globalMiddlewares: [], - // 模块加载顺序,默认为0,值越大越优先加载 - order: 0, - } as ModuleConfig; -}; diff --git a/src/modules/demo/controller/admin/goods.ts b/src/modules/demo/controller/admin/goods.ts deleted file mode 100644 index 2bf6fdb..0000000 --- a/src/modules/demo/controller/admin/goods.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { CoolController, BaseController } from '@cool-midway/core'; -import { DemoGoodsEntity } from '../../entity/goods'; - -/** - * 商品模块-商品信息 - */ -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: DemoGoodsEntity, -}) -export class AdminDemoGoodsController extends BaseController {} diff --git a/src/modules/demo/controller/open/cache.ts b/src/modules/demo/controller/open/cache.ts deleted file mode 100644 index cf3ac4b..0000000 --- a/src/modules/demo/controller/open/cache.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { DemoCacheService } from '../../service/cache'; -import { Inject, Post, Provide, Get, InjectClient } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; - -/** - * 缓存 - */ -@CoolController() -export class OpenDemoCacheController extends BaseController { - @InjectClient(CachingFactory, 'default') - midwayCache: MidwayCache; - - @Inject() - demoCacheService: DemoCacheService; - - /** - * 设置缓存 - * @returns - */ - @Post('/set') - async set() { - await this.midwayCache.set('a', 1); - // 缓存10秒 - await this.midwayCache.set('a', 1, 10 * 1000); - return this.ok(await this.midwayCache.get('a')); - } - - /** - * 获得缓存 - * @returns - */ - @Get('/get') - async get() { - return this.ok(await this.demoCacheService.get()); - } -} diff --git a/src/modules/demo/controller/open/event.ts b/src/modules/demo/controller/open/event.ts deleted file mode 100644 index 826bf6f..0000000 --- a/src/modules/demo/controller/open/event.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Inject, Post } from '@midwayjs/decorator'; -import { - CoolController, - BaseController, - CoolEventManager, -} from '@cool-midway/core'; - -/** - * 事件 - */ -@CoolController() -export class OpenDemoEventController extends BaseController { - @Inject() - coolEventManager: CoolEventManager; - - @Post('/comm', { summary: '普通事件,本进程生效' }) - async comm() { - await this.coolEventManager.emit('demo', { a: 2 }, 1); - return this.ok(); - } - - @Post('/global', { summary: '全局事件,多进程都有效' }) - async global() { - await this.coolEventManager.globalEmit('demo', false, { a: 2 }, 1); - return this.ok(); - } -} diff --git a/src/modules/demo/controller/open/goods.ts b/src/modules/demo/controller/open/goods.ts deleted file mode 100644 index 8a42ecd..0000000 --- a/src/modules/demo/controller/open/goods.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { DemoGoodsService } from '../../service/goods'; -import { DemoGoodsEntity } from '../../entity/goods'; -import { Body, Config, Inject, Post, Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; - -/** - * 测试 - */ -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: DemoGoodsEntity, - service: DemoGoodsService, -}) -export class OpenDemoGoodsController extends BaseController { - @InjectEntityModel(DemoGoodsEntity) - demoGoodsEntity: Repository; - - @Inject() - demoGoodsService: DemoGoodsService; - - @Post('/sqlPage', { summary: 'sql分页查询' }) - async sqlPage(@Body() query) { - return this.ok(await this.demoGoodsService.sqlPage(query)); - } - - @Post('/entityPage', { summary: 'entity分页查询' }) - async entityPage(@Body() query) { - return this.ok(await this.demoGoodsService.entityPage(query)); - } -} diff --git a/src/modules/demo/controller/open/plugin.ts b/src/modules/demo/controller/open/plugin.ts deleted file mode 100644 index c2d3310..0000000 --- a/src/modules/demo/controller/open/plugin.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { CoolController, BaseController } from '@cool-midway/core'; -import { PluginService } from '../../../plugin/service/info'; -import { Get, Inject } from '@midwayjs/core'; - -/** - * 插件 - */ -@CoolController() -export class OpenDemoPluginController extends BaseController { - @Inject() - pluginService: PluginService; - - @Get('/invoke', { summary: '调用插件' }) - async invoke() { - // 获取插件实例 - const instance: any = await this.pluginService.getInstance('ollama'); - // 调用chat - const messages = [ - { role: 'system', content: '你叫小酷,是一个智能助理' }, - { role: 'user', content: '写一个1000字的关于春天的文章' }, - ]; - for (let i = 0; i < 3; i++) { - instance.chat(messages, { stream: true }, res => { - console.log(i, res.content); - }); - } - return this.ok(); - } -} diff --git a/src/modules/demo/controller/open/queue.ts b/src/modules/demo/controller/open/queue.ts deleted file mode 100644 index df5c639..0000000 --- a/src/modules/demo/controller/open/queue.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Get, Inject, Post, Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { DemoCommQueue } from '../../queue/comm'; -import { DemoGetterQueue } from '../../queue/getter'; - -/** - * 队列 - */ -@CoolController() -export class OpenDemoQueueController extends BaseController { - // 普通队列 - @Inject() - demoCommQueue: DemoCommQueue; - - // 主动消费队列 - @Inject() - demoGetterQueue: DemoGetterQueue; - - /** - * 发送数据到队列 - */ - @Post('/add', { summary: '发送队列数据' }) - async queue() { - this.demoCommQueue.add({ a: 2 }); - return this.ok(); - } - - @Post('/addGetter') - async addGetter() { - await this.demoGetterQueue.add({ a: new Date() }); - return this.ok(); - } - - /** - * 获得队列中的数据,只有当队列类型为getter时有效 - */ - @Get('/getter') - async getter() { - const job = await this.demoGetterQueue.getters.getJobs( - ['wait'], - 0, - 0, - true - ); - // 获得完将数据从队列移除 - await job[0]?.remove(); - return this.ok(job[0]?.data); - } -} diff --git a/src/modules/demo/controller/open/rpc.ts b/src/modules/demo/controller/open/rpc.ts deleted file mode 100644 index 2086169..0000000 --- a/src/modules/demo/controller/open/rpc.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Inject, Provide, Get } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { DemoRpcService } from '../../service/rpc'; - -/** - * 远程RPC调用 - */ -@CoolController() -export class OpenDemoRpcController extends BaseController { - @Inject() - demoRpcService: DemoRpcService; - - @Get('/call', { summary: '远程调用' }) - async call() { - return this.ok(await this.demoRpcService.call()); - } - - @Get('/event', { summary: '集群事件' }) - async event() { - await this.demoRpcService.event(); - return this.ok(); - } - - @Get('/transaction', { summary: '分布式事务' }) - async transaction() { - await this.demoRpcService.transaction({ a: 1 }); - return this.ok(); - } -} diff --git a/src/modules/demo/controller/open/sse.ts b/src/modules/demo/controller/open/sse.ts deleted file mode 100644 index 9733dd2..0000000 --- a/src/modules/demo/controller/open/sse.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { CoolController, BaseController } from '@cool-midway/core'; -import { Get, Inject } from '@midwayjs/core'; -import { Context } from 'koa'; -import { PluginService } from '../../../plugin/service/info'; -import { PassThrough } from 'stream'; - -/** - * 事件流 服务端主动推送 - */ -@CoolController() -export class OpenDemoSSEController extends BaseController { - @Inject() - ctx: Context; - - @Inject() - pluginService: PluginService; - - @Get('/call', { summary: '事件流 服务端主动推送' }) - async call() { - // 设置响应头 - this.ctx.set('Content-Type', 'text/event-stream'); - this.ctx.set('Cache-Control', 'no-cache'); - this.ctx.set('Connection', 'keep-alive'); - - const stream = new PassThrough(); - - // 发送数据 - const send = (data: any) => { - stream.write(`data: ${JSON.stringify(data)}\n\n`); - }; - - // 获取插件实例 - const instance: any = await this.pluginService.getInstance('ollama'); - // 调用chat - const messages = [ - { role: 'system', content: '你叫小酷,是个编程助手' }, - { role: 'user', content: '用js写个Hello World' }, - ]; - instance.chat(messages, { stream: true }, res => { - send(res); - if (res.isEnd) { - this.ctx.res.end(); - } - }); - - this.ctx.status = 200; - this.ctx.body = stream; - } -} diff --git a/src/modules/demo/controller/open/transaction.ts b/src/modules/demo/controller/open/transaction.ts deleted file mode 100644 index 804f055..0000000 --- a/src/modules/demo/controller/open/transaction.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DemoGoodsEntity } from '../../entity/goods'; -import { Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { DemoTransactionService } from '../../service/transaction'; - -/** - * 事务 - */ -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: DemoGoodsEntity, - service: DemoTransactionService, -}) -export class OpenDemoTransactionController extends BaseController {} diff --git a/src/modules/demo/entity/goods.ts b/src/modules/demo/entity/goods.ts deleted file mode 100644 index 4667633..0000000 --- a/src/modules/demo/entity/goods.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity, Index } from 'typeorm'; - -/** - * 商品模块-商品信息 - */ -@Entity('demo_goods') -export class DemoGoodsEntity extends BaseEntity { - @Index() - @Column({ comment: '标题', length: 50 }) - title: string; - - @Column({ - comment: '价格', - type: 'decimal', - precision: 5, - scale: 2, - }) - price: number; - - @Column({ comment: '描述', nullable: true }) - description: string; - - @Column({ comment: '主图', nullable: true }) - mainImage: string; - - @Column({ comment: '示例图', nullable: true, type: 'json' }) - exampleImages: string[]; - - @Column({ comment: '库存', default: 0 }) - stock: number; -} diff --git a/src/modules/demo/event/comm.ts b/src/modules/demo/event/comm.ts deleted file mode 100644 index ae00a64..0000000 --- a/src/modules/demo/event/comm.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { CoolEvent, Event } from '@cool-midway/core'; -import { EVENT_PLUGIN_READY } from '../../plugin/service/center'; - -/** - * 普通事件 - */ -@CoolEvent() -export class DemoCommEvent { - /** - * 根据事件名接收事件 - * @param msg - * @param a - */ - @Event('demo') - async demo(msg, a) { - console.log(`comm当前进程的ID是: ${process.pid}`); - console.log('comm收到消息', msg, a); - } - - /** - * 插件已就绪 - */ - @Event(EVENT_PLUGIN_READY) - async pluginReady() { - // TODO 插件已就绪 - } -} diff --git a/src/modules/demo/queue/comm.ts b/src/modules/demo/queue/comm.ts deleted file mode 100644 index 7bb9134..0000000 --- a/src/modules/demo/queue/comm.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { BaseCoolQueue, CoolQueue } from '@cool-midway/task'; -import { IMidwayApplication } from '@midwayjs/core'; -import { App } from '@midwayjs/decorator'; - -/** - * 普通队列 - */ -@CoolQueue() -export class DemoCommQueue extends BaseCoolQueue { - @App() - app: IMidwayApplication; - - async data(job: any, done: any): Promise { - // 这边可以执行定时任务具体的业务或队列的业务 - console.log('数据', job.data); - // 抛出错误 可以让队列重试,默认重试5次 - //throw new Error('错误'); - done(); - } -} diff --git a/src/modules/demo/queue/getter.ts b/src/modules/demo/queue/getter.ts deleted file mode 100644 index 8da42c9..0000000 --- a/src/modules/demo/queue/getter.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { BaseCoolQueue, CoolQueue } from '@cool-midway/task'; - -/** - * 主动消费队列 - */ -@CoolQueue({ type: 'getter' }) -export class DemoGetterQueue extends BaseCoolQueue {} diff --git a/src/modules/demo/queue/single.ts b/src/modules/demo/queue/single.ts deleted file mode 100644 index 67bcc6b..0000000 --- a/src/modules/demo/queue/single.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { BaseCoolQueue, CoolQueue } from '@cool-midway/task'; -import { IMidwayApplication } from '@midwayjs/core'; -import { App } from '@midwayjs/decorator'; - -/** - * 单例队列,cluster 或 集群模式下 只会有一个实例消费数据 - */ -@CoolQueue({ type: 'single' }) -export class DemoSingleQueue extends BaseCoolQueue { - @App() - app: IMidwayApplication; - - async data(job: any, done: any): Promise { - // 这边可以执行定时任务具体的业务或队列的业务 - console.log('数据', job.data); - // 抛出错误 可以让队列重试,默认重试5次 - //throw new Error('错误'); - done(); - } -} diff --git a/src/modules/demo/service/cache.ts b/src/modules/demo/service/cache.ts deleted file mode 100644 index 01d3de8..0000000 --- a/src/modules/demo/service/cache.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Provide } from '@midwayjs/decorator'; -import { CoolCache } from '@cool-midway/core'; - -/** - * 缓存 - */ -@Provide() -export class DemoCacheService { - // 数据缓存5秒 - @CoolCache(5) - async get() { - console.log('执行方法'); - return { - a: 1, - b: 2, - }; - } -} diff --git a/src/modules/demo/service/goods.ts b/src/modules/demo/service/goods.ts deleted file mode 100644 index 979656a..0000000 --- a/src/modules/demo/service/goods.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { DemoGoodsEntity } from './../entity/goods'; -import { Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; - -/** - * 商品示例 - */ -@Provide() -export class DemoGoodsService extends BaseService { - @InjectEntityModel(DemoGoodsEntity) - demoGoodsEntity: Repository; - - /** - * 执行sql分页 - */ - async sqlPage(query) { - await this.demoGoodsEntity.save({ - id: 1, - title: '标题', - price: 99.0, - description: '商品描述', - mainImage: 'https://cool-js.com/logo.png', - }); - return this.sqlRenderPage( - 'select * from demo_goods ORDER BY id ASC', - query, - false - ); - } - - /** - * 执行entity分页 - */ - async entityPage(query) { - const find = this.demoGoodsEntity.createQueryBuilder(); - return this.entityRenderPage(find, query); - } -} diff --git a/src/modules/demo/service/rpc.ts b/src/modules/demo/service/rpc.ts deleted file mode 100644 index e95ca39..0000000 --- a/src/modules/demo/service/rpc.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { App, Provide } from '@midwayjs/decorator'; -import { DemoGoodsEntity } from '../entity/goods'; -import { IMidwayApplication, Inject } from '@midwayjs/core'; -import { - BaseRpcService, - CoolRpc, - CoolRpcService, - CoolRpcTransaction, -} from '@cool-midway/rpc'; -import { QueryRunner } from 'typeorm'; - -@Provide() -@CoolRpcService({ - entity: DemoGoodsEntity, - method: ['info', 'add', 'page'], -}) -export class DemoRpcService extends BaseRpcService { - @App() - app: IMidwayApplication; - - @Inject() - rpc: CoolRpc; - - /** - * 远程调用 - * @returns - */ - async call() { - return await this.rpc.call('goods', 'demoGoodsService', 'test', { - a: 1, - }); - } - - /** - * 集群事件 - */ - async event() { - this.rpc.event('test', { a: 1 }); - } - - async info(params) { - return params; - } - async getUser() { - return { - uid: '123', - username: 'mockedName', - phone: '12345678901', - email: 'xxx.xxx@xxx.com', - }; - } - - @CoolRpcTransaction() - async transaction(params, rpcTransactionId?, queryRunner?: QueryRunner) { - console.log('获得的参数', params); - const data = { - title: '商品标题', - pic: 'https://xxx', - price: 99.0, - type: 1, - }; - await queryRunner.manager.save(DemoGoodsEntity, data); - - // 将事务id传给调用的远程服务方法 - await this.rpc.call('goods', 'demoGoodsService', 'transaction', { - rpcTransactionId, - ...params, - }); - } -} diff --git a/src/modules/demo/service/transaction.ts b/src/modules/demo/service/transaction.ts deleted file mode 100644 index 3aa45e8..0000000 --- a/src/modules/demo/service/transaction.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { DemoGoodsEntity } from './../entity/goods'; -import { Provide } from '@midwayjs/decorator'; -import { BaseService, CoolTransaction } from '@cool-midway/core'; -import { QueryRunner } from 'typeorm'; - -/** - * 操作事务 - */ -@Provide() -export class DemoTransactionService extends BaseService { - /** - * 事务操作 - */ - @CoolTransaction({ - connectionName: 'default', - }) - async add(param, queryRunner?: QueryRunner) { - await queryRunner.manager.insert(DemoGoodsEntity, param); - return { - id: param.id, - }; - } -} diff --git a/src/modules/dict/config.ts b/src/modules/dict/config.ts deleted file mode 100644 index 0c7e579..0000000 --- a/src/modules/dict/config.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ModuleConfig } from '@cool-midway/core'; - -/** - * 模块配置 - */ -export default () => { - return { - // 模块名称 - name: '字典管理', - // 模块描述 - description: '数据字典等', - // 中间件,只对本模块有效 - middlewares: [], - // 中间件,全局有效 - globalMiddlewares: [], - // 模块加载顺序,默认为0,值越大越优先加载 - order: 0, - } as ModuleConfig; -}; diff --git a/src/modules/dict/controller/admin/info.ts b/src/modules/dict/controller/admin/info.ts deleted file mode 100644 index ebe684a..0000000 --- a/src/modules/dict/controller/admin/info.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { DictInfoEntity } from './../../entity/info'; -import { Body, Inject, Post, Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { DictInfoService } from '../../service/info'; - -/** - * 字典信息 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: DictInfoEntity, - service: DictInfoService, - listQueryOp: { - fieldEq: ['typeId'], - keyWordLikeFields: ['name'], - addOrderBy: { - createTime: 'ASC', - }, - }, -}) -export class AdminDictInfoController extends BaseController { - @Inject() - dictInfoService: DictInfoService; - - @Post('/data', { summary: '获得字典数据' }) - async data(@Body('types') types: string[] = []) { - return this.ok(await this.dictInfoService.data(types)); - } -} diff --git a/src/modules/dict/controller/admin/type.ts b/src/modules/dict/controller/admin/type.ts deleted file mode 100644 index e31cdd8..0000000 --- a/src/modules/dict/controller/admin/type.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { DictTypeEntity } from './../../entity/type'; -import { Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { DictTypeService } from '../../service/type'; - -/** - * 字典类型 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: DictTypeEntity, - service: DictTypeService, - listQueryOp: { - keyWordLikeFields: ['name'], - }, -}) -export class AdminDictTypeController extends BaseController {} diff --git a/src/modules/dict/controller/app/info.ts b/src/modules/dict/controller/app/info.ts deleted file mode 100644 index b83a849..0000000 --- a/src/modules/dict/controller/app/info.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Body, Inject, Post, Provide } from '@midwayjs/decorator'; -import { - CoolController, - BaseController, - CoolUrlTag, - TagTypes, - CoolTag, -} from '@cool-midway/core'; -import { DictInfoService } from '../../service/info'; - -/** - * 字典信息 - */ -@Provide() -@CoolController() -@CoolUrlTag() -export class AppDictInfoController extends BaseController { - @Inject() - dictInfoService: DictInfoService; - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/data', { summary: '获得字典数据' }) - async data(@Body('types') types: string[] = []) { - return this.ok(await this.dictInfoService.data(types)); - } -} diff --git a/src/modules/dict/db.json b/src/modules/dict/db.json deleted file mode 100644 index 31c79a2..0000000 --- a/src/modules/dict/db.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "dict_info": [ - { - "id": 21, - "typeId": 19, - "name": "COOL", - "orderNum": 1, - "remark": null, - "parentId": null, - "value": "cool" - }, - { - "id": 22, - "typeId": 19, - "name": "闪酷", - "orderNum": 2, - "remark": null, - "parentId": null, - "value": "https://show.cool-admin.com/api/public/uploads/20230308/c731b0cba84046268b10edbbcf36f948_315c243a448e1369fa145c5ea3f020da.gif" - }, - { - "id": 23, - "typeId": 20, - "name": "法师", - "orderNum": 1, - "remark": null, - "parentId": null, - "value": "4" - }, - { - "id": 24, - "typeId": 20, - "name": "战士", - "orderNum": 2, - "remark": null, - "parentId": null, - "value": "3" - }, - { - "id": 25, - "typeId": 20, - "name": "坦克", - "orderNum": 3, - "remark": null, - "parentId": null, - "value": "2" - }, - { - "id": 26, - "typeId": 20, - "name": "刺客", - "orderNum": 4, - "remark": null, - "parentId": null, - "value": "1" - }, - { - "id": 27, - "typeId": 20, - "name": "射手", - "orderNum": 5, - "remark": null, - "parentId": null, - "value": "0" - }, - { - "id": 30, - "typeId": 20, - "name": "幻影刺客", - "orderNum": 1, - "remark": null, - "parentId": 26, - "value": "5" - } - ], - "dict_type": [ - { - "id": 19, - "name": "品牌", - "key": "brand" - }, - { - "id": 20, - "name": "职业", - "key": "occupation" - } - ] -} \ No newline at end of file diff --git a/src/modules/dict/entity/info.ts b/src/modules/dict/entity/info.ts deleted file mode 100644 index 68d4701..0000000 --- a/src/modules/dict/entity/info.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity } from 'typeorm'; - -/** - * 字典信息 - */ -@Entity('dict_info') -export class DictInfoEntity extends BaseEntity { - @Column({ comment: '类型ID' }) - typeId: number; - - @Column({ comment: '名称' }) - name: string; - - @Column({ comment: '值', nullable: true }) - value: string; - - @Column({ comment: '排序', default: 0 }) - orderNum: number; - - @Column({ comment: '备注', nullable: true }) - remark: string; - - @Column({ comment: '父ID', default: null }) - parentId: number; -} diff --git a/src/modules/dict/entity/type.ts b/src/modules/dict/entity/type.ts deleted file mode 100644 index 1b5d1b4..0000000 --- a/src/modules/dict/entity/type.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity } from 'typeorm'; - -/** - * 字典类别 - */ -@Entity('dict_type') -export class DictTypeEntity extends BaseEntity { - @Column({ comment: '名称' }) - name: string; - - @Column({ comment: '标识' }) - key: string; -} diff --git a/src/modules/dict/service/info.ts b/src/modules/dict/service/info.ts deleted file mode 100644 index 5643e09..0000000 --- a/src/modules/dict/service/info.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { DictTypeEntity } from './../entity/type'; -import { DictInfoEntity } from './../entity/info'; -import { Config, Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository, In } from 'typeorm'; -import * as _ from 'lodash'; - -/** - * 字典信息 - */ -@Provide() -export class DictInfoService extends BaseService { - @InjectEntityModel(DictInfoEntity) - dictInfoEntity: Repository; - - @InjectEntityModel(DictTypeEntity) - dictTypeEntity: Repository; - - @Config('typeorm.dataSource.default.type') - ormType: string; - - /** - * 获得字典数据 - * @param types - */ - async data(types: string[]) { - const result = {}; - let typeData = await this.dictTypeEntity.find(); - if (!_.isEmpty(types)) { - typeData = await this.dictTypeEntity.findBy({ key: In(types) }); - } - if (_.isEmpty(typeData)) { - return {}; - } - const data = await this.dictInfoEntity - .createQueryBuilder('a') - .select([ - 'a.id', - 'a.name', - 'a.typeId', - 'a.parentId', - 'a.orderNum', - 'a.value', - ]) - .where('a.typeId in(:...typeIds)', { - typeIds: typeData.map(e => { - return e.id; - }), - }) - .orderBy('a.orderNum', 'ASC') - .addOrderBy('a.createTime', 'ASC') - .getMany(); - for (const item of typeData) { - result[item.key] = _.filter(data, { typeId: item.id }).map(e => { - const value = e.value ? Number(e.value) : e.value; - return { - ...e, - value: isNaN(value) ? e.value : value, - }; - }); - } - return result; - } - - /** - * 获得单个或多个字典值 - * @param value 字典值或字典值数组 - * @param key 字典类型 - * @returns - */ - async getValues(value: string | string[], key: string) { - // 获取字典类型 - const type = await this.dictTypeEntity.findOneBy({ key }); - if (!type) { - return null; // 或者适当的错误处理 - } - - // 根据typeId获取所有相关的字典信息 - const dictValues = await this.dictInfoEntity.find({ - where: { typeId: type.id }, - }); - - // 如果value是字符串,直接查找 - if (typeof value === 'string') { - return this.findValueInDictValues(value, dictValues); - } - - // 如果value是数组,遍历数组,对每个元素进行查找 - return value.map(val => this.findValueInDictValues(val, dictValues)); - } - - /** - * 在字典值数组中查找指定的值 - * @param value 要查找的值 - * @param dictValues 字典值数组 - * @returns - */ - findValueInDictValues(value: string, dictValues: any[]) { - let result = dictValues.find(dictValue => dictValue.value === value); - if (!result) { - result = dictValues.find(dictValue => dictValue.id === parseInt(value)); - } - return result ? result.name : null; // 或者适当的错误处理 - } - - /** - * 修改之后 - * @param data - * @param type - */ - async modifyAfter(data: any, type: 'delete' | 'update' | 'add') { - if (type === 'delete') { - for (const id of data) { - await this.delChildDict(id); - } - } - } - - /** - * 删除子字典 - * @param id - */ - private async delChildDict(id) { - const delDict = await this.dictInfoEntity.findBy({ parentId: id }); - if (_.isEmpty(delDict)) { - return; - } - const delDictIds = delDict.map(e => { - return e.id; - }); - await this.dictInfoEntity.delete(delDictIds); - for (const dictId of delDictIds) { - await this.delChildDict(dictId); - } - } -} diff --git a/src/modules/dict/service/type.ts b/src/modules/dict/service/type.ts deleted file mode 100644 index 7ff4b9d..0000000 --- a/src/modules/dict/service/type.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { DictInfoEntity } from './../entity/info'; -import { Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository, In } from 'typeorm'; - -/** - * 描述 - */ -@Provide() -export class DictTypeService extends BaseService { - @InjectEntityModel(DictInfoEntity) - dictInfoEntity: Repository; - - /** - * 删除 - * @param ids - */ - async delete(ids) { - super.delete(ids); - await this.dictInfoEntity.delete({ - typeId: In(ids), - }); - } -} diff --git a/src/modules/plugin/config.ts b/src/modules/plugin/config.ts deleted file mode 100644 index 74aa56b..0000000 --- a/src/modules/plugin/config.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ModuleConfig } from '@cool-midway/core'; - -/** - * 模块配置 - */ -export default options => { - return { - // 模块名称 - name: '插件模块', - // 模块描述 - description: '插件查看、安装、卸载、配置等', - // 中间件,只对本模块有效 - middlewares: [], - // 中间件,全局有效 - globalMiddlewares: [], - // 模块加载顺序,默认为0,值越大越优先加载 - order: 0, - // 基础插件配置 - hooks: { - // 文件上传 - upload: { - // 地址前缀 - domain: `http://127.0.0.1:${options?.app?.getConfig('koa.port')}`, - }, - }, - } as ModuleConfig; -}; diff --git a/src/modules/plugin/controller/admin/info.ts b/src/modules/plugin/controller/admin/info.ts deleted file mode 100644 index f8c9e15..0000000 --- a/src/modules/plugin/controller/admin/info.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { - CoolController, - BaseController, - CoolTag, - CoolUrlTag, - TagTypes, -} from '@cool-midway/core'; -import { PluginInfoEntity } from '../../entity/info'; -import { Body, Fields, Files, Inject, Post } from '@midwayjs/core'; -import { PluginService } from '../../service/info'; - -/** - * 插件信息 - */ -@CoolUrlTag({ - key: TagTypes.IGNORE_TOKEN, - value: [], -}) -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: PluginInfoEntity, - service: PluginService, - pageQueryOp: { - select: [ - 'a.id', - 'a.name', - 'a.keyName', - 'a.hook', - 'a.version', - 'a.status', - 'a.readme', - 'a.author', - 'a.logo', - 'a.description', - 'a.pluginJson', - 'a.config', - 'a.createTime', - 'a.updateTime', - ], - addOrderBy: { - id: 'DESC', - }, - }, -}) -export class AdminPluginInfoController extends BaseController { - @Inject() - pluginService: PluginService; - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/install', { summary: '安装插件' }) - async install(@Files() files, @Fields() fields) { - return this.ok( - await this.pluginService.install(files[0].data, fields.force) - ); - } -} diff --git a/src/modules/plugin/entity/info.ts b/src/modules/plugin/entity/info.ts deleted file mode 100644 index 2c75d57..0000000 --- a/src/modules/plugin/entity/info.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity, DataSource, Index } from 'typeorm'; - -console.log(DataSource); - -/** - * 插件信息 - */ -@Entity('plugin_info') -export class PluginInfoEntity extends BaseEntity { - @Column({ comment: '名称' }) - name: string; - - @Column({ comment: '简介' }) - description: string; - - @Index() - @Column({ comment: 'Key名' }) - keyName: string; - - @Column({ comment: 'Hook' }) - hook: string; - - @Column({ comment: '描述', type: 'text' }) - readme: string; - - @Column({ comment: '版本' }) - version: string; - - @Column({ comment: 'Logo(base64)', type: 'text', nullable: true }) - logo: string; - - @Column({ comment: '作者' }) - author: string; - - @Column({ comment: '状态 0-禁用 1-启用', default: 0 }) - status: number; - - @Column({ comment: '插件的plugin.json', type: 'json', nullable: true }) - pluginJson: any; - - @Column({ comment: '配置', type: 'json', nullable: true }) - config: any; -} diff --git a/src/modules/plugin/event/app.ts b/src/modules/plugin/event/app.ts deleted file mode 100644 index 2ef8f5c..0000000 --- a/src/modules/plugin/event/app.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { CoolEvent, Event } from '@cool-midway/core'; -import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; -import { - App, - Config, - ILogger, - Inject, - InjectClient, - Logger, -} from '@midwayjs/core'; -import { IMidwayKoaApplication } from '@midwayjs/koa'; -import { PLUGIN_CACHE_KEY, PluginCenterService } from '../service/center'; -import { PluginTypesService } from '../service/types'; - -/** - * 插件事件 - */ -@CoolEvent() -export class PluginAppEvent { - @Logger() - coreLogger: ILogger; - - @Config('module') - config; - - @App() - app: IMidwayKoaApplication; - - @InjectClient(CachingFactory, 'default') - midwayCache: MidwayCache; - - @Inject() - pluginCenterService: PluginCenterService; - - @Inject() - pluginTypesService: PluginTypesService; - - @Event('onServerReady') - async onServerReady() { - await this.midwayCache.set(PLUGIN_CACHE_KEY, []); - this.pluginCenterService.init(); - // this.pluginTypesService.reGenerate(); - } -} diff --git a/src/modules/plugin/event/init.ts b/src/modules/plugin/event/init.ts deleted file mode 100644 index 4a55409..0000000 --- a/src/modules/plugin/event/init.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { CoolEvent, Event } from '@cool-midway/core'; -import { Inject } from '@midwayjs/core'; -import { PluginCenterService } from '../service/center'; - -// 插件初始化全局事件 -export const GLOBAL_EVENT_PLUGIN_INIT = 'globalPluginInit'; -// 插件移除全局事件 -export const GLOBAL_EVENT_PLUGIN_REMOVE = 'globalPluginRemove'; - -/** - * 接收事件 - */ -@CoolEvent() -export class PluginInitEvent { - @Inject() - pluginCenterService: PluginCenterService; - - /** - * 插件初始化事件,某个插件重新初始化 - * @param key - */ - @Event(GLOBAL_EVENT_PLUGIN_INIT) - async globalPluginInit(key: string) { - await this.pluginCenterService.initOne(key); - } - - /** - * 插件移除或者关闭事件 - * @param key - * @param isHook - */ - @Event(GLOBAL_EVENT_PLUGIN_REMOVE) - async globalPluginRemove(key: string, isHook: boolean) { - await this.pluginCenterService.remove(key, isHook); - } -} diff --git a/src/modules/plugin/hooks/base.ts b/src/modules/plugin/hooks/base.ts deleted file mode 100644 index 05aa206..0000000 --- a/src/modules/plugin/hooks/base.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { IMidwayContext, IMidwayApplication } from '@midwayjs/core'; -import { PluginInfo } from '../interface'; - -/** - * hook基类 - */ -export class BasePluginHook { - /** 请求上下文,用到此项无法本地调试,需安装到cool-admin中才能调试 */ - ctx: IMidwayContext; - /** 应用实例,用到此项无法本地调试,需安装到cool-admin中才能调试 */ - app: IMidwayApplication; - /** 插件信息 */ - pluginInfo: PluginInfo; - /** - * 初始化 - */ - async init( - pluginInfo: PluginInfo, - ctx?: IMidwayContext, - app?: IMidwayApplication - ) { - this.pluginInfo = pluginInfo; - this.ctx = ctx; - this.app = app; - } -} diff --git a/src/modules/plugin/hooks/upload/index.ts b/src/modules/plugin/hooks/upload/index.ts deleted file mode 100644 index a29df88..0000000 --- a/src/modules/plugin/hooks/upload/index.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { BaseUpload, MODETYPE } from './interface'; -import { BasePluginHook } from '../base'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as moment from 'moment'; -import { v1 as uuid } from 'uuid'; -import { CoolCommException } from '@cool-midway/core'; -import * as _ from 'lodash'; - -/** - * 文件上传 - */ -export class CoolPlugin extends BasePluginHook implements BaseUpload { - /** - * 获得上传模式 - * @returns - */ - async getMode() { - return { - mode: MODETYPE.LOCAL, - type: MODETYPE.LOCAL, - }; - } - - /** - * 获得原始操作对象 - * @returns - */ - async getMetaFileObj() { - return; - } - - /** - * 下载并上传 - * @param url - * @param fileName - */ - async downAndUpload(url: string, fileName?: string) { - const { domain } = this.pluginInfo.config; - // 从url获取扩展名 - const extend = path.extname(url); - const download = require('download'); - // 数据 - const data = url.includes('http') - ? await download(url) - : fs.readFileSync(url); - // 创建文件夹 - const dirPath = path.join( - this.app.getBaseDir(), - '..', - `public/uploads/${moment().format('YYYYMMDD')}` - ); - if (!fs.existsSync(dirPath)) { - fs.mkdirSync(dirPath, { recursive: true }); - } - const uuidStr = uuid(); - const name = `uploads/${moment().format('YYYYMMDD')}/${ - fileName ? fileName : uuidStr + extend - }`; - fs.writeFileSync( - `${dirPath}/${fileName ? fileName : uuid() + extend}`, - data - ); - return `${domain}/public/${name}`; - } - - /** - * 指定Key(路径)上传,本地文件上传到存储服务 - * @param filePath 文件路径 - * @param key 路径一致会覆盖源文件 - */ - async uploadWithKey(filePath: any, key: any) { - const { domain } = this.pluginInfo.config; - const data = fs.readFileSync(filePath); - fs.writeFileSync(path.join(this.app.getBaseDir(), '..', key), data); - return domain + key; - } - - /** - * 上传文件 - * @param ctx - * @param key 文件路径 - */ - async upload(ctx: any) { - const { domain } = this.pluginInfo.config; - try { - const { key } = ctx.fields; - if (_.isEmpty(ctx.files)) { - throw new CoolCommException('上传文件为空'); - } - // 检查public/uploads文件夹是否存在,不存在则创建 - const basePath = path.join( - this.app.getBaseDir(), - '..', - 'public', - 'uploads' - ); - if (!fs.existsSync(basePath)) { - fs.mkdirSync(basePath); - } - - const file = ctx.files[0]; - const extension = file.filename.split('.').pop(); - const name = - moment().format('YYYYMMDD') + '/' + (key || `${uuid()}.${extension}`); - const target = path.join(basePath, name); - const dirPath = path.join(basePath, moment().format('YYYYMMDD')); - if (!fs.existsSync(dirPath)) { - fs.mkdirSync(dirPath); - } - const data = fs.readFileSync(file.data); - fs.writeFileSync(target, data); - return domain + '/public/uploads/' + name; - } catch (err) { - console.error(err); - throw new CoolCommException('上传失败' + err.message); - } - } -} - -// 导出插件实例, Plugin名称不可修改 -export const Plugin = CoolPlugin; diff --git a/src/modules/plugin/hooks/upload/interface.ts b/src/modules/plugin/hooks/upload/interface.ts deleted file mode 100644 index 4f0cdfc..0000000 --- a/src/modules/plugin/hooks/upload/interface.ts +++ /dev/null @@ -1,56 +0,0 @@ -// 模式 -export enum MODETYPE { - // 本地 - LOCAL = 'local', - // 云存储 - CLOUD = 'cloud', - // 其他 - OTHER = 'other', -} - -/** - * 上传模式 - */ -export interface Mode { - // 模式 - mode: MODETYPE; - // 类型 - type: string; -} - -/** - * 文件上传 - */ -export interface BaseUpload { - /** - * 获得上传模式 - */ - getMode(): Promise; - - /** - * 获得原始操作对象 - * @returns - */ - getMetaFileObj(): Promise; - - /** - * 下载并上传 - * @param url - * @param fileName 文件名 - */ - downAndUpload(url: string, fileName?: string): Promise; - - /** - * 指定Key(路径)上传,本地文件上传到存储服务 - * @param filePath 文件路径 - * @param key 路径一致会覆盖源文件 - */ - uploadWithKey(filePath, key): Promise; - - /** - * 上传文件 - * @param ctx - * @param key 文件路径 - */ - upload(ctx): Promise; -} diff --git a/src/modules/plugin/interface.ts b/src/modules/plugin/interface.ts deleted file mode 100644 index 5af915d..0000000 --- a/src/modules/plugin/interface.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * 插件信息 - */ -export interface PluginInfo { - /** 名称 */ - name?: string; - /** 唯一标识 */ - key?: string; - /** 钩子 */ - hook?: string; - /** 是否单例 */ - singleton?: boolean; - /** 版本 */ - version?: string; - /** 描述 */ - description?: string; - /** 作者 */ - author?: string; - /** logo */ - logo?: string; - /** README 使用说明 */ - readme?: string; - /** 配置 */ - config?: any; -} diff --git a/src/modules/plugin/service/center.ts b/src/modules/plugin/service/center.ts deleted file mode 100644 index a922a17..0000000 --- a/src/modules/plugin/service/center.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { Provide } from '@midwayjs/decorator'; -import { - App, - IMidwayApplication, - Inject, - InjectClient, - Scope, - ScopeEnum, -} from '@midwayjs/core'; -import * as fs from 'fs'; -import * as path from 'path'; -import { PluginInfoEntity } from '../entity/info'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { PluginInfo } from '../interface'; -import * as _ from 'lodash'; -import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; -import { CoolEventManager } from '@cool-midway/core'; -import { PluginService } from './info'; - -export const PLUGIN_CACHE_KEY = 'plugin:init'; - -export const EVENT_PLUGIN_READY = 'EVENT_PLUGIN_READY'; - -/** - * 插件中心 - */ -@Provide() -@Scope(ScopeEnum.Singleton) -export class PluginCenterService { - // 插件列表 - plugins: Map = new Map(); - - // 插件配置 - pluginInfos: Map = new Map(); - - @App() - app: IMidwayApplication; - - @InjectEntityModel(PluginInfoEntity) - pluginInfoEntity: Repository; - - @InjectClient(CachingFactory, 'default') - midwayCache: MidwayCache; - - @Inject() - coolEventManager: CoolEventManager; - - @Inject() - pluginService: PluginService; - - /** - * 初始化 - * @returns - */ - async init() { - this.plugins.clear(); - await this.initHooks(); - await this.initPlugin(); - this.coolEventManager.emit(EVENT_PLUGIN_READY); - } - - /** - * 初始化一个 - * @param keyName key名 - */ - async initOne(keyName: string) { - await this.initPlugin({ - keyName, - }); - this.coolEventManager.emit(EVENT_PLUGIN_READY, keyName); - } - - /** - * 移除插件 - * @param keyName - * @param isHook - */ - async remove(keyName: string, isHook = false) { - this.plugins.delete(keyName); - this.pluginInfos.delete(keyName); - if (isHook) { - await this.initHooks(); - } - } - - /** - * 注册插件 - * @param key 唯一标识 - * @param cls 类 - * @param pluginInfo 插件信息 - */ - async register(key: string, cls: any, pluginInfo?: PluginInfo) { - // 单例插件 - if (pluginInfo?.singleton) { - const instance = new cls(); - await instance.init(this.pluginInfos.get(key), null, this.app, { - cache: this.midwayCache, - pluginService: this.pluginService, - }); - this.plugins.set(key, instance); - } else { - // 普通插件 - this.plugins.set(key, cls); - } - } - - /** - * 初始化钩子 - */ - async initHooks() { - const hooksPath = path.join( - this.app.getBaseDir(), - 'modules', - 'plugin', - 'hooks' - ); - for (const key of fs.readdirSync(hooksPath)) { - const stat = fs.statSync(path.join(hooksPath, key)); - if (!stat.isDirectory()) { - continue; - } - const { Plugin } = await import(path.join(hooksPath, key, 'index')); - await this.register(key, Plugin); - this.pluginInfos.set(key, { - name: key, - config: this.app.getConfig('module.plugin.hooks.' + key), - }); - } - } - - /** - * 初始化插件 - * @param condition 插件条件 - */ - async initPlugin(condition?: { - hook?: string; - id?: number; - keyName?: string; - }) { - let find: any = { status: 1 }; - if (condition) { - find = { - ...find, - ...condition, - }; - } - const plugins = await this.pluginInfoEntity.findBy(find); - for (const plugin of plugins) { - const data = await this.pluginService.getData(plugin.keyName); - if (!data) { - continue; - } - const instance = await this.getInstance(data.content.data); - const pluginInfo = { - ...plugin.pluginJson, - config: this.getConfig(plugin.config), - }; - if (plugin.hook) { - this.pluginInfos.set(plugin.hook, pluginInfo); - await this.register(plugin.hook, instance, pluginInfo); - } else { - this.pluginInfos.set(plugin.keyName, pluginInfo); - await this.register(plugin.keyName, instance, pluginInfo); - } - } - } - - /** - * 获得配置 - * @param config - * @returns - */ - private getConfig(config: any) { - const env = this.app.getEnv(); - let isMulti = false; - for (const key in config) { - if (key.includes('@')) { - isMulti = true; - break; - } - } - return isMulti ? config[`@${env}`] : config; - } - - /** - * 获得实例 - * @param content - * @returns - */ - async getInstance(content: string) { - let _instance; - const script = ` - ${content} - _instance = Plugin; - `; - eval(script); - return _instance; - } -} diff --git a/src/modules/plugin/service/info.ts b/src/modules/plugin/service/info.ts deleted file mode 100644 index ea977dc..0000000 --- a/src/modules/plugin/service/info.ts +++ /dev/null @@ -1,445 +0,0 @@ -import { App, Inject, Provide } from '@midwayjs/decorator'; -import { - BaseService, - CoolCommException, - CoolEventManager, -} from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Equal, In, Not, Repository } from 'typeorm'; -import { PluginInfoEntity } from '../entity/info'; -import { - Config, - ILogger, - IMidwayApplication, - IMidwayContext, - InjectClient, - Logger, -} from '@midwayjs/core'; -import * as _ from 'lodash'; -import { PluginInfo } from '../interface'; -import { PluginCenterService } from './center'; -import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; -import { - GLOBAL_EVENT_PLUGIN_INIT, - GLOBAL_EVENT_PLUGIN_REMOVE, -} from '../event/init'; -import { PluginMap, AnyString } from '../../../../typings/plugin'; -import { PluginTypesService } from './types'; -import * as path from 'path'; -import * as fs from 'fs'; -/** - * 插件信息 - */ -@Provide() -export class PluginService extends BaseService { - @InjectEntityModel(PluginInfoEntity) - pluginInfoEntity: Repository; - - @Inject() - ctx: IMidwayContext; - - @App() - app: IMidwayApplication; - - @Inject() - pluginCenterService: PluginCenterService; - - @Config('module.plugin.hooks') - hooksConfig; - - @InjectClient(CachingFactory, 'default') - midwayCache: MidwayCache; - - @Inject() - coolEventManager: CoolEventManager; - - @Inject() - pluginTypesService: PluginTypesService; - - @Logger() - logger: ILogger; - - /** - * 新增或更新 - * @param param - * @param type - */ - async addOrUpdate(param: any, type?: 'add' | 'update') { - await super.addOrUpdate(param, type); - const info = await this.pluginInfoEntity - .createQueryBuilder('a') - .select(['a.id', 'a.keyName', 'a.status', 'a.hook']) - .where({ - id: Equal(param.id), - }) - .getOne(); - if (info.status == 1) { - await this.reInit(info.keyName); - } else { - await this.remove(info.keyName, !!info.hook); - } - } - - /** - * 重新初始化插件 - */ - async reInit(keyName: string) { - // 多进程发送全局事件,pm2下生效,本地开发则通过普通事件 - this.coolEventManager.globalEmit(GLOBAL_EVENT_PLUGIN_INIT, false, keyName); - } - - /** - * 移除插件 - * @param keyName - * @param isHook - */ - async remove(keyName: string, isHook = false) { - // 多进程发送全局事件,pm2下生效 - this.coolEventManager.globalEmit( - GLOBAL_EVENT_PLUGIN_REMOVE, - false, - keyName, - isHook - ); - this.pluginTypesService.deleteDtsFile(keyName); - } - - /** - * 删除不经过回收站 - * @param ids - */ - async delete(ids: any) { - const list = await this.pluginInfoEntity.findBy({ id: In(ids) }); - for (const item of list) { - await this.remove(item.keyName, !!item.hook); - // 删除文件 - await this.deleteData(item.keyName); - } - await this.pluginInfoEntity.delete(ids); - } - - /** - * 更新 - * @param param - */ - async update(param: any) { - const old = await this.pluginInfoEntity.findOne({ - where: { id: param.id }, - select: ['id', 'status', 'hook'], - }); - // 启用插件,禁用同名插件 - if (old.hook && param.status == 1 && old.status != param.status) { - await this.pluginInfoEntity.update( - { hook: old.hook, status: 1, id: Not(old.id) }, - { status: 0 } - ); - } - await super.update(param); - } - - /** - * 获得插件配置 - * @param key - */ - async getConfig(key: string) { - return this.pluginCenterService.pluginInfos.get(key)?.config; - } - - /** - * 调用插件 - * @param key 插件key - * @param method 方法 - * @param params 参数 - * @returns - */ - async invoke( - key: K | AnyString, - method: string, - ...params - ) { - // 实例 - const instance: any = await this.getInstance(key); - return await instance[method](...params); - } - - /** - * 获得插件实例 - * @param key - * @returns - */ - async getInstance( - key: K | AnyString - ): Promise { - const check = await this.checkStatus(key); - if (!check) throw new CoolCommException(`插件[${key}]不存在或已禁用`); - let instance; - const pluginInfo = this.pluginCenterService.pluginInfos.get(key); - if (pluginInfo.singleton) { - instance = this.pluginCenterService.plugins.get(key); - } else { - instance = new (await this.pluginCenterService.plugins.get(key))(); - await instance.init(pluginInfo, this.ctx, this.app, { - cache: this.midwayCache, - pluginService: this, - }); - } - return instance; - } - - /** - * 检查状态 - * @param key - */ - async checkStatus(key: string) { - if (Object.keys(this.hooksConfig).includes(key)) { - return true; - } - const info = await this.pluginInfoEntity - .createQueryBuilder('a') - .select(['a.id', 'a.status']) - .where({ status: 1, keyName: Equal(key) }) - .getOne(); - - return !!info; - } - - /** - * 检查 - * @param filePath - */ - async check(filePath: string) { - let data; - try { - data = await this.data(filePath); - } catch (e) { - return { - type: 0, - message: `插件信息不完整,请检查${data.errorData}`, - }; - } - const check = await this.pluginInfoEntity.findOne({ - where: { keyName: Equal(data.pluginJson.key) }, - select: ['id', 'hook', 'status'], - }); - if (check && !check.hook) { - return { - type: 1, - message: '插件已存在,继续安装将覆盖', - }; - } - if (check && check.hook && check.status == 1) { - return { - type: 2, - message: - '已存在同名Hook插件,你可以继续安装,但是多个相同的Hook插件只能同时开启一个', - }; - } - return { - type: 3, - message: '检查通过', - }; - } - - /** - * 获得插件数据 - * @param filePath - */ - async data(filePath: string): Promise<{ - pluginJson: any; - readme: string; - logo: string; - content: string; - tsContent: string; - errorData: string; - }> { - const decompress = require('decompress'); - const files = await decompress(filePath); - let errorData; - let pluginJson: PluginInfo, - readme: string, - logo: string, - content: string, - tsContent: string; - try { - errorData = 'plugin.json'; - pluginJson = JSON.parse( - _.find(files, { path: 'plugin.json', type: 'file' }).data.toString() - ); - errorData = 'readme'; - readme = _.find(files, { - path: pluginJson.readme, - type: 'file', - }).data.toString(); - errorData = 'logo'; - logo = _.find(files, { - path: pluginJson.logo, - type: 'file', - }).data.toString('base64'); - content = _.find(files, { - path: 'src/index.js', - type: 'file', - }).data.toString(); - tsContent = - _.find(files, { - path: 'source/index.ts', - type: 'file', - })?.data?.toString() || ''; - } catch (e) { - throw new CoolCommException('插件信息不完整'); - } - return { - pluginJson, - readme, - logo, - content, - tsContent, - errorData, - }; - } - - /** - * 安装插件 - * @param file 文件 - * @param force 是否强制安装 - */ - async install(filePath: string, force = false) { - const forceBool = typeof force === 'string' ? force === 'true' : force; - const checkResult = await this.check(filePath); - if (checkResult.type != 3 && !forceBool) { - return checkResult; - } - const { pluginJson, readme, logo, content, tsContent } = await this.data( - filePath - ); - if (pluginJson.key == 'plugin') { - throw new CoolCommException('插件key不能为plugin,请更换其他key'); - } - const check = await this.pluginInfoEntity.findOne({ - where: { keyName: Equal(pluginJson.key) }, - select: ['id', 'status', 'config'], - }); - const data = { - name: pluginJson.name, - keyName: pluginJson.key, - version: pluginJson.version, - author: pluginJson.author, - hook: pluginJson.hook, - readme, - logo, - description: pluginJson.description, - pluginJson, - config: pluginJson.config, - status: 1, - } as PluginInfoEntity; - // 存在同名插件,更新,保留配置 - if (check) { - await this.pluginInfoEntity.update(check.id, { - ...data, - status: check.status, - config: { - ...pluginJson.config, - ...check.config, - }, - }); - } else { - // 全新安装 - await this.pluginInfoEntity.insert(data); - } - // 保存插件内容 - await this.saveData( - { - content: { - type: 'comm', - data: content, - }, - tsContent: { - type: 'ts', - data: tsContent, - }, - }, - pluginJson.key - ); - this.pluginTypesService.generateDtsFile(pluginJson.key, tsContent); - // 初始化插件 - await this.reInit(pluginJson.key); - } - - /** - * 将插件内容保存到文件 - * @param content 内容 - * @param keyName 插件key - */ - async saveData( - data: { - content: { - type: 'comm' | 'module'; - data: string; - }; - tsContent: { - type: 'ts'; - data: string; - }; - }, - keyName: string - ) { - const filePath = this.pluginPath(keyName); - // 确保目录存在 - const dir = path.dirname(filePath); - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir, { recursive: true }); - } - // 写入文件,如果存在则覆盖 - fs.writeFileSync(filePath, JSON.stringify(data, null, 0), { flag: 'w' }); - } - - /** - * 获得插件数据 - * @param keyName - * @returns - */ - async getData(keyName: string): Promise<{ - content: { - type: 'comm' | 'module'; - data: string; - }; - tsContent: { - type: 'ts'; - data: string; - }; - }> { - const filePath = this.pluginPath(keyName); - if (!fs.existsSync(filePath)) { - this.logger.warn( - `插件[${keyName}]文件不存在,请卸载后重新安装: ${filePath}` - ); - return null; - } - return JSON.parse(await fs.promises.readFile(filePath, 'utf-8')); - } - - /** - * 删除插件 - * @param keyName - */ - async deleteData(keyName: string) { - const filePath = this.pluginPath(keyName); - if (fs.existsSync(filePath)) { - fs.unlinkSync(filePath); - } - } - - /** - * 获得插件路径 - * @param keyName - * @returns - */ - pluginPath(keyName: string) { - return path.join( - this.app.getBaseDir(), - '..', - 'cool', - 'plugin', - `${keyName}.cool` - ); - } -} diff --git a/src/modules/plugin/service/types.ts b/src/modules/plugin/service/types.ts deleted file mode 100644 index 59db655..0000000 --- a/src/modules/plugin/service/types.ts +++ /dev/null @@ -1,257 +0,0 @@ -import { BaseService } from '@cool-midway/core'; -import { IMidwayApplication, Inject } from '@midwayjs/core'; -import { App, Provide } from '@midwayjs/decorator'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as prettier from 'prettier'; -import { Repository } from 'typeorm'; -import * as ts from 'typescript'; -import { Utils } from '../../../comm/utils'; -import { PluginInfoEntity } from '../entity/info'; -import { PluginService } from './info'; - -/** - * 插件类型服务 - */ -@Provide() -export class PluginTypesService extends BaseService { - @App() - app: IMidwayApplication; - - @InjectEntityModel(PluginInfoEntity) - pluginInfoEntity: Repository; - - @Inject() - pluginService: PluginService; - - @Inject() - utils: Utils; - - /** - * 生成d.ts文件 - * @param tsContent - * @returns - */ - async dtsContent(tsContent: string) { - let output = ''; - - const compilerHost: ts.CompilerHost = { - fileExists: ts.sys.fileExists, - getCanonicalFileName: ts.sys.useCaseSensitiveFileNames - ? s => s - : s => s.toLowerCase(), - getCurrentDirectory: ts.sys.getCurrentDirectory, - getDefaultLibFileName: options => ts.getDefaultLibFilePath(options), - getDirectories: ts.sys.getDirectories, - getNewLine: () => ts.sys.newLine, - getSourceFile: (fileName, languageVersion) => { - if (fileName === 'file.ts') { - return ts.createSourceFile( - fileName, - tsContent, - languageVersion, - true - ); - } - const filePath = ts.sys.resolvePath(fileName); - return ts.sys.readFile(filePath) - ? ts.createSourceFile( - filePath, - ts.sys.readFile(filePath)!, - languageVersion, - true - ) - : undefined; - }, - readFile: ts.sys.readFile, - useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, - writeFile: (fileName, content) => { - if (fileName.includes('file.d.ts')) { - output = content || output; - } - }, - }; - - const options: ts.CompilerOptions = { - declaration: true, - emitDeclarationOnly: true, - outDir: './', - skipLibCheck: true, - skipDefaultLibCheck: true, - noEmitOnError: false, - target: ts.ScriptTarget.ES2018, - strict: false, - module: ts.ModuleKind.Node16, - moduleResolution: ts.ModuleResolutionKind.Node16, - types: ['node'], - }; - - const program = ts.createProgram(['file.ts'], options, compilerHost); - program.emit(); - - if (!output) { - // Provide a default value if the output is still empty - output = '/* No declaration content generated */'; - } - return output; - } - - /** - * 生成d.ts文件 - * @param key - * @param tsContent - * @returns - */ - async generateDtsFile(key: string, tsContent: string) { - const env = this.app.getEnv(); - // 不是本地开发环境不生成d.ts文件 - if (env != 'local' || !tsContent) { - return; - } - // 基础路径 - const basePath = path.join(this.app.getBaseDir(), '..', 'typings'); - // pluginDts文件路径 - const pluginDtsPath = path.join(basePath, 'plugin.d.ts'); - // plugin文件夹路径 - const pluginPath = path.join(basePath, `${key}.d.ts`); - // 生成d.ts文件 - const dtsContent = await this.dtsContent(tsContent); - - // 读取plugin.d.ts文件内容 - let pluginDtsContent = fs.readFileSync(pluginDtsPath, 'utf-8'); - - // 根据key判断是否在PluginMap中存在 - const keyWithHyphen = key.includes('-'); - const importStatement = keyWithHyphen - ? `import * as ${key.replace(/-/g, '_')} from './${key}';` - : `import * as ${key} from './${key}';`; - const pluginMapEntry = keyWithHyphen - ? `'${key}': ${key.replace(/-/g, '_')}.CoolPlugin;` - : `${key}: ${key}.CoolPlugin;`; - - // 检查import语句是否已经存在,若不存在则添加 - if (!pluginDtsContent.includes(importStatement)) { - pluginDtsContent = `${importStatement}\n${pluginDtsContent}`; - } - - // 检查PluginMap中的键是否存在,若不存在则添加 - if (pluginDtsContent.includes(pluginMapEntry)) { - // 键存在则覆盖 - const regex = new RegExp( - `(\\s*${keyWithHyphen ? `'${key}'` : key}:\\s*[^;]+;)` - ); - pluginDtsContent = pluginDtsContent.replace(regex, pluginMapEntry); - } else { - // 键不存在则追加 - const pluginMapRegex = /interface\s+PluginMap\s*{([^}]*)}/; - pluginDtsContent = pluginDtsContent.replace( - pluginMapRegex, - (match, p1) => { - return match.replace(p1, `${p1.trim()}\n ${pluginMapEntry}`); - } - ); - } - - // 格式化内容 - pluginDtsContent = await this.formatContent(pluginDtsContent); - - // 延迟2秒写入文件 - setTimeout(async () => { - // 写入d.ts文件,如果存在则覆盖 - fs.writeFile(pluginPath, await this.formatContent(dtsContent), () => {}); - - // 写入plugin.d.ts文件 - fs.writeFile(pluginDtsPath, pluginDtsContent, () => {}); - }, 2000); - } - - /** - * 删除d.ts文件中的指定key - * @param key - */ - async deleteDtsFile(key: string) { - const env = this.app.getEnv(); - // 不是本地开发环境不删除d.ts文件 - if (env != 'local') { - return; - } - // 基础路径 - const basePath = path.join(this.app.getBaseDir(), '..', 'typings'); - // pluginDts文件路径 - const pluginDtsPath = path.join(basePath, 'plugin.d.ts'); - // plugin文件夹路径 - const pluginPath = path.join(basePath, `${key}.d.ts`); - - // 读取plugin.d.ts文件内容 - let pluginDtsContent = fs.readFileSync(pluginDtsPath, 'utf-8'); - - // 根据key判断是否在PluginMap中存在 - const keyWithHyphen = key.includes('-'); - const importStatement = keyWithHyphen - ? `import \\* as ${key.replace(/-/g, '_')} from '\\./${key}';` - : `import \\* as ${key} from '\\./${key}';`; - const pluginMapEntry = keyWithHyphen - ? `'${key}': ${key.replace(/-/g, '_')}.CoolPlugin;` - : `${key}: ${key}.CoolPlugin;`; - - // 删除import语句 - const importRegex = new RegExp(`${importStatement}\\n`, 'g'); - pluginDtsContent = pluginDtsContent.replace(importRegex, ''); - - // 删除PluginMap中的键 - const pluginMapRegex = new RegExp(`\\s*${pluginMapEntry}`, 'g'); - pluginDtsContent = pluginDtsContent.replace(pluginMapRegex, ''); - - // 格式化内容 - pluginDtsContent = await this.formatContent(pluginDtsContent); - - // 延迟2秒写入文件 - setTimeout(async () => { - // 删除插件d.ts文件 - if (fs.existsSync(pluginPath)) { - fs.unlink(pluginPath, () => {}); - } - // 写入plugin.d.ts文件 - fs.writeFile(pluginDtsPath, pluginDtsContent, () => {}); - }, 2000); - } - - /** - * 格式化内容 - * @param content - */ - async formatContent(content: string) { - // 使用prettier格式化内容 - return prettier.format(content, { - parser: 'typescript', - singleQuote: true, - trailingComma: 'all', - bracketSpacing: true, - arrowParens: 'avoid', - printWidth: 80, - }); - } - - /** - * 重新生成d.ts文件 - */ - async reGenerate() { - const pluginInfos = await this.pluginInfoEntity - .createQueryBuilder('a') - .where('a.status = :status', { status: 1 }) - .select(['a.id', 'a.status', 'a.tsContent', 'a.keyName']) - .getMany(); - for (const pluginInfo of pluginInfos) { - const data = await this.pluginService.getData(pluginInfo.keyName); - if (!data) { - continue; - } - const tsContent = data.tsContent?.data; - if (tsContent) { - await this.generateDtsFile(pluginInfo.keyName, tsContent); - await this.utils.sleep(200); - } - } - } -} diff --git a/src/modules/recycle/config.ts b/src/modules/recycle/config.ts deleted file mode 100644 index 3421900..0000000 --- a/src/modules/recycle/config.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ModuleConfig } from '@cool-midway/core'; - -/** - * 模块配置 - */ -export default () => { - return { - // 模块名称 - name: '数据回收', - // 模块描述 - description: '收集被删除的数据,管理和恢复', - // 中间件,只对本模块有效 - middlewares: [], - // 中间件,全局有效 - globalMiddlewares: [], - // 模块加载顺序,默认为0,值越大越优先加载 - order: 0, - } as ModuleConfig; -}; diff --git a/src/modules/recycle/controller/admin/data.ts b/src/modules/recycle/controller/admin/data.ts deleted file mode 100644 index 926cd5e..0000000 --- a/src/modules/recycle/controller/admin/data.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { BaseSysUserEntity } from './../../../base/entity/sys/user'; -import { RecycleDataEntity } from './../../entity/data'; -import { Body, Inject, Post, Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { RecycleDataService } from '../../service/data'; - -/** - * 数据回收 - */ -@Provide() -@CoolController({ - api: ['info', 'page'], - entity: RecycleDataEntity, - pageQueryOp: { - keyWordLikeFields: ['b.name', 'a.url'], - select: ['a.*', 'b.name as userName'], - join: [ - { - entity: BaseSysUserEntity, - alias: 'b', - condition: 'a.userId = b.id', - }, - ], - }, -}) -export class AdminRecycleDataController extends BaseController { - @Inject() - recycleDataService: RecycleDataService; - - @Post('/restore', { summary: '恢复数据' }) - async restore(@Body('ids') ids: number[]) { - await this.recycleDataService.restore(ids); - return this.ok(); - } -} diff --git a/src/modules/recycle/entity/data.ts b/src/modules/recycle/entity/data.ts deleted file mode 100644 index e150f43..0000000 --- a/src/modules/recycle/entity/data.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Entity, Column, Index } from 'typeorm'; - -/** - * 数据回收站 软删除的时候数据会回收到该表 - */ -@Entity('recycle_data') -export class RecycleDataEntity extends BaseEntity { - @Column({ comment: '表', type: 'json' }) - entityInfo: { - // 数据源名称 - dataSourceName: string; - // entity - entity: string; - }; - - @Index() - @Column({ comment: '操作人', nullable: true }) - userId: number; - - @Column({ comment: '被删除的数据', type: 'json' }) - data: object[]; - - @Column({ comment: '请求的接口', nullable: true }) - url: string; - - @Column({ comment: '请求参数', nullable: true, type: 'json' }) - params: string; - - @Column({ comment: '删除数据条数', default: 1 }) - count: number; -} diff --git a/src/modules/recycle/event/data.ts b/src/modules/recycle/event/data.ts deleted file mode 100644 index 5c96bab..0000000 --- a/src/modules/recycle/event/data.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { CoolEvent, EVENT, Event } from '@cool-midway/core'; -import { Inject } from '@midwayjs/core'; -import { RecycleDataService } from '../service/data'; - -/** - * 接受数据事件 - */ -@CoolEvent() -export class RecycleDataEvent { - @Inject() - recycleDataService: RecycleDataService; - - /** - * 数据被删除 - * @param params - */ - @Event(EVENT.SOFT_DELETE) - async softDelete(params) { - await this.recycleDataService.record(params); - } -} diff --git a/src/modules/recycle/schedule/data.ts b/src/modules/recycle/schedule/data.ts deleted file mode 100644 index 5ac87b9..0000000 --- a/src/modules/recycle/schedule/data.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { - Provide, - Inject, - CommonSchedule, - TaskLocal, - FORMAT, -} from '@midwayjs/decorator'; -import { ILogger } from '@midwayjs/logger'; -import { RecycleDataService } from '../service/data'; - -/** - * 数据定时清除定时任务 - */ -@Provide() -export class BaseRecycleSchedule implements CommonSchedule { - @Inject() - recycleDataService: RecycleDataService; - - @Inject() - logger: ILogger; - - // 定时执行的具体任务 - @TaskLocal(FORMAT.CRONTAB.EVERY_DAY) - async exec() { - this.logger.info('清除回收站数据定时任务开始执行'); - const startTime = Date.now(); - await this.recycleDataService.clear(); - this.logger.info( - `清除回收站数据定时任务结束,耗时:${Date.now() - startTime}ms` - ); - } -} diff --git a/src/modules/recycle/service/data.ts b/src/modules/recycle/service/data.ts deleted file mode 100644 index 7684736..0000000 --- a/src/modules/recycle/service/data.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { RecycleDataEntity } from './../entity/data'; -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { InjectEntityModel, TypeORMDataSourceManager } from '@midwayjs/typeorm'; -import { LessThan, Repository } from 'typeorm'; -import * as _ from 'lodash'; -import * as moment from 'moment'; -import { BaseSysConfService } from '../../base/service/sys/conf'; - -/** - * 数据回收 - */ -@Provide() -@Scope(ScopeEnum.Request, { allowDowngrade: true }) -export class RecycleDataService extends BaseService { - @InjectEntityModel(RecycleDataEntity) - recycleDataEntity: Repository; - - @Inject() - typeORMDataSourceManager: TypeORMDataSourceManager; - - @Inject() - baseSysConfService: BaseSysConfService; - - /** - * 恢复数据 - * @param ids - */ - async restore(ids: number[]) { - for (const id of ids) { - const info = await this.recycleDataEntity.findOneBy({ id }); - if (!info) { - continue; - } - let entityModel = this.typeORMDataSourceManager - .getDataSource(info.entityInfo.dataSourceName) - .getRepository(info.entityInfo.entity); - await entityModel.save(info.data); - await this.recycleDataEntity.delete(id); - } - } - - /** - * 记录数据 - * @param params - */ - async record(params) { - const { ctx, data, entity } = params; - if (!ctx?.req) return; - const dataSourceName = - this.typeORMDataSourceManager.getDataSourceNameByModel(entity.target); - const url = ctx?.url; - await this.recycleDataEntity.save({ - entityInfo: { - dataSourceName, - entity: entity.target.name, - }, - url, - params: - ctx?.req.method === 'GET' ? ctx?.request.query : ctx?.request.body, - data, - count: data.length, - userId: _.startsWith(url, '/admin/') ? ctx?.admin.userId : ctx?.user?.id, - }); - } - - /** - * 日志 - * @param isAll 是否清除全部 - */ - async clear(isAll?) { - if (isAll) { - await this.recycleDataEntity.clear(); - return; - } - const keepDay = await this.baseSysConfService.getValue('recycleKeep'); - if (keepDay) { - const beforeDate = moment().add(-keepDay, 'days').startOf('day').toDate(); - await this.recycleDataEntity.delete({ createTime: LessThan(beforeDate) }); - } else { - await this.recycleDataEntity.clear(); - } - } -} diff --git a/src/modules/space/config.ts b/src/modules/space/config.ts deleted file mode 100644 index 10e7cff..0000000 --- a/src/modules/space/config.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ModuleConfig } from '@cool-midway/core'; - -/** - * 模块配置 - */ -export default () => { - return { - // 模块名称 - name: '文件空间', - // 模块描述 - description: '上传和管理文件资源', - // 中间件,只对本模块有效 - middlewares: [], - // 中间件,全局有效 - globalMiddlewares: [], - // 模块加载顺序,默认为0,值越大越优先加载 - order: 0, - // wps的配置 - wps: { - // 这是个测试的appId,会有水印 - appId: 'SX20230111NDUAGQ', - }, - } as ModuleConfig; -}; diff --git a/src/modules/space/controller/admin/info.ts b/src/modules/space/controller/admin/info.ts deleted file mode 100644 index 11f3a07..0000000 --- a/src/modules/space/controller/admin/info.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { SpaceInfoEntity } from '../../entity/info'; -import { SpaceInfoService } from '../../service/info'; - -/** - * 图片空间信息 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: SpaceInfoEntity, - service: SpaceInfoService, - pageQueryOp: { - fieldEq: ['type', 'classifyId'], - }, -}) -export class BaseAppSpaceInfoController extends BaseController {} diff --git a/src/modules/space/controller/admin/type.ts b/src/modules/space/controller/admin/type.ts deleted file mode 100644 index 6429242..0000000 --- a/src/modules/space/controller/admin/type.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { SpaceTypeEntity } from '../../entity/type'; -import { SpaceTypeService } from '../../service/type'; - -/** - * 空间分类 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: SpaceTypeEntity, - service: SpaceTypeService, -}) -export class BaseAppSpaceTypeController extends BaseController {} diff --git a/src/modules/space/controller/说明.md b/src/modules/space/controller/说明.md deleted file mode 100644 index 440a373..0000000 --- a/src/modules/space/controller/说明.md +++ /dev/null @@ -1 +0,0 @@ -编写接口 \ No newline at end of file diff --git a/src/modules/space/entity/info.ts b/src/modules/space/entity/info.ts deleted file mode 100644 index 3c2d4fc..0000000 --- a/src/modules/space/entity/info.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Index, Entity } from 'typeorm'; - -/** - * 文件空间信息 - */ -@Entity('space_info') -export class SpaceInfoEntity extends BaseEntity { - @Column({ comment: '地址' }) - url: string; - - @Column({ comment: '类型' }) - type: string; - - @Column({ comment: '分类ID', nullable: true }) - classifyId: number; - - @Index() - @Column({ comment: '文件id' }) - fileId: string; - - @Column({ comment: '文件名' }) - name: string; - - @Column({ comment: '文件大小' }) - size: number; - - @Column({ comment: '文档版本', default: 1 }) - version: number; - - @Column({ comment: '文件位置' }) - key: string; -} diff --git a/src/modules/space/entity/type.ts b/src/modules/space/entity/type.ts deleted file mode 100644 index 15c4308..0000000 --- a/src/modules/space/entity/type.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity } from 'typeorm'; - -/** - * 图片空间信息分类 - */ -@Entity('space_type') -export class SpaceTypeEntity extends BaseEntity { - @Column({ comment: '类别名称' }) - name: string; - - @Column({ comment: '父分类ID', nullable: true }) - parentId: number; -} diff --git a/src/modules/space/service/info.ts b/src/modules/space/service/info.ts deleted file mode 100644 index 417588a..0000000 --- a/src/modules/space/service/info.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { SpaceInfoEntity } from './../entity/info'; -import { Inject, Provide } from '@midwayjs/decorator'; -import { BaseService, MODETYPE } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { PluginService } from '../../plugin/service/info'; - -/** - * 文件信息 - */ -@Provide() -export class SpaceInfoService extends BaseService { - @InjectEntityModel(SpaceInfoEntity) - spaceInfoEntity: Repository; - - @Inject() - pluginService: PluginService; - - /** - * 新增 - */ - async add(param) { - const result = await this.pluginService.invoke('upload', 'getMode'); - const config = await this.pluginService.getConfig('upload'); - if (result.mode == MODETYPE.LOCAL) { - param.key = param.url.replace(config.domain, ''); - } - return super.add(param); - } -} diff --git a/src/modules/space/service/type.ts b/src/modules/space/service/type.ts deleted file mode 100644 index a9a6704..0000000 --- a/src/modules/space/service/type.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { In, Repository } from 'typeorm'; -import { SpaceTypeEntity } from '../entity/type'; -import { SpaceInfoEntity } from '../entity/info'; - -/** - * 文件分类 - */ -@Provide() -export class SpaceTypeService extends BaseService { - @InjectEntityModel(SpaceTypeEntity) - spaceTypeEntity: Repository; - - @InjectEntityModel(SpaceInfoEntity) - spaceInfoEntity: Repository; - - /** - * 删除 - * @param ids - */ - async delete(ids: any) { - await super.delete(ids); - // 删除该分类下的文件信息 - await this.spaceInfoEntity.delete({ classifyId: In(ids) }); - } -} diff --git a/src/modules/task/config.ts b/src/modules/task/config.ts deleted file mode 100644 index b919075..0000000 --- a/src/modules/task/config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ModuleConfig } from '@cool-midway/core'; -import { TaskMiddleware } from './middleware/task'; - -/** - * 模块配置 - */ -export default () => { - return { - // 模块名称 - name: '任务调度', - // 模块描述 - description: '任务调度模块,支持分布式任务,由redis整个集群的任务', - // 中间件 - middlewares: [TaskMiddleware], - // 模块加载顺序,默认为0,值越大越优先加载 - order: 0, - } as ModuleConfig; -}; diff --git a/src/modules/task/controller/admin/info.ts b/src/modules/task/controller/admin/info.ts deleted file mode 100644 index bca8ee9..0000000 --- a/src/modules/task/controller/admin/info.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { - ALL, - Body, - Get, - Inject, - Post, - Provide, - Query, -} from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { TaskInfoEntity } from '../../entity/info'; -import { TaskInfoService } from '../../service/info'; - -/** - * 任务 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'page'], - entity: TaskInfoEntity, - service: TaskInfoService, - before: ctx => { - ctx.request.body.limit = ctx.request.body.repeatCount; - }, - pageQueryOp: { - fieldEq: ['status', 'type'], - }, -}) -export class TaskInfoController extends BaseController { - @Inject() - taskInfoService: TaskInfoService; - - /** - * 手动执行一次 - */ - @Post('/once', { summary: '执行一次' }) - async once(@Body('id') id: number) { - await this.taskInfoService.once(id); - this.ok(); - } - - /** - * 暂停任务 - */ - @Post('/stop', { summary: '停止' }) - async stop(@Body('id') id: number) { - await this.taskInfoService.stop(id); - this.ok(); - } - - /** - * 开始任务 - */ - @Post('/start', { summary: '开始' }) - async start(@Body('id') id: number, @Body('type') type: number) { - await this.taskInfoService.start(id, type); - this.ok(); - } - - /** - * 日志 - */ - @Get('/log', { summary: '日志' }) - async log(@Query(ALL) params: any) { - return this.ok(await this.taskInfoService.log(params)); - } -} diff --git a/src/modules/task/controller/说明.md b/src/modules/task/controller/说明.md deleted file mode 100644 index 440a373..0000000 --- a/src/modules/task/controller/说明.md +++ /dev/null @@ -1 +0,0 @@ -编写接口 \ No newline at end of file diff --git a/src/modules/task/db.json b/src/modules/task/db.json deleted file mode 100644 index 2e318c7..0000000 --- a/src/modules/task/db.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "task_info": [ - { - "id": 1, - "jobId": null, - "repeatConf": "{\"count\":1,\"type\":1,\"limit\":5,\"name\":\"每秒执行,总共5次\",\"taskType\":1,\"every\":1000,\"service\":\"taskDemoService.test()\",\"status\":1,\"id\":1,\"createTime\":\"2021-03-10 14:25:13\",\"updateTime\":\"2021-03-10 14:25:13\",\"jobId\":1}", - "name": "每秒执行一次", - "cron": null, - "limit": null, - "every": 1000, - "remark": null, - "status": 0, - "startDate": null, - "endDate": null, - "data": null, - "service": "taskDemoService.test(1,2)", - "type": 1, - "nextRunTime": "2021-3-10 14:25:18", - "taskType": 1 - }, - { - "id": 2, - "jobId": null, - "repeatConf": "{\"count\":1,\"id\":2,\"createTime\":\"2021-03-10 14:25:53\",\"updateTime\":\"2021-03-10 14:25:55\",\"name\":\"cron任务,5秒执行一次\",\"cron\":\"0/5 * * * * ? \",\"status\":1,\"service\":\"taskDemoService.test()\",\"type\":1,\"nextRunTime\":\"2021-03-10 14:26:00\",\"taskType\":0,\"jobId\":2}", - "name": "cron任务,5秒执行一次", - "cron": "0/5 * * * * ? ", - "limit": null, - "every": null, - "remark": null, - "status": 0, - "startDate": null, - "endDate": null, - "data": null, - "service": "taskDemoService.test()", - "type": 1, - "nextRunTime": null, - "taskType": 0 - } - ] -} \ No newline at end of file diff --git a/src/modules/task/entity/info.ts b/src/modules/task/entity/info.ts deleted file mode 100644 index 0393e24..0000000 --- a/src/modules/task/entity/info.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity } from 'typeorm'; - -/** - * 任务信息 - */ -@Entity('task_info') -export class TaskInfoEntity extends BaseEntity { - @Column({ comment: '任务ID', nullable: true }) - jobId: string; - - @Column({ comment: '任务配置', nullable: true, length: 1000 }) - repeatConf: string; - - @Column({ comment: '名称' }) - name: string; - - @Column({ comment: 'cron', nullable: true }) - cron: string; - - @Column({ comment: '最大执行次数 不传为无限次', nullable: true }) - limit: number; - - @Column({ - comment: '每间隔多少毫秒执行一次 如果cron设置了 这项设置就无效', - nullable: true, - }) - every: number; - - @Column({ comment: '备注', nullable: true }) - remark: string; - - @Column({ comment: '状态 0-停止 1-运行', default: 1 }) - status: number; - - @Column({ comment: '开始时间', nullable: true }) - startDate: Date; - - @Column({ comment: '结束时间', nullable: true }) - endDate: Date; - - @Column({ comment: '数据', nullable: true }) - data: string; - - @Column({ comment: '执行的service实例ID', nullable: true }) - service: string; - - @Column({ comment: '状态 0-系统 1-用户', default: 0 }) - type: number; - - @Column({ comment: '下一次执行时间', nullable: true }) - nextRunTime: Date; - - @Column({ comment: '状态 0-cron 1-时间间隔', default: 0 }) - taskType: number; -} diff --git a/src/modules/task/entity/log.ts b/src/modules/task/entity/log.ts deleted file mode 100644 index 2f9030a..0000000 --- a/src/modules/task/entity/log.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Index, Entity } from 'typeorm'; - -/** - * 任务日志 - */ -@Entity('task_log') -export class TaskLogEntity extends BaseEntity { - @Index() - @Column({ comment: '任务ID', nullable: true }) - taskId: number; - - @Column({ comment: '状态 0-失败 1-成功', default: 0 }) - status: number; - - @Column({ comment: '详情描述', nullable: true, type: 'text' }) - detail: string; -} diff --git a/src/modules/task/event/app.ts b/src/modules/task/event/app.ts deleted file mode 100644 index 48e5c43..0000000 --- a/src/modules/task/event/app.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Inject } from '@midwayjs/core'; -import { TaskInfoService } from './../service/info'; -import { CoolEvent, Event } from '@cool-midway/core'; - -/** - * 应用事件 - */ -@CoolEvent() -export class TaskAppEvent { - @Inject() - taskInfoService: TaskInfoService; - - @Event('onServerReady') - async onServerReady() { - this.taskInfoService.initTask(); - } -} diff --git a/src/modules/task/middleware/task.ts b/src/modules/task/middleware/task.ts deleted file mode 100644 index 8926852..0000000 --- a/src/modules/task/middleware/task.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { CoolCommException } from '@cool-midway/core'; -import { Inject, Middleware } from '@midwayjs/decorator'; -import { NextFunction, Context } from '@midwayjs/koa'; -import { IMiddleware } from '@midwayjs/core'; -import { TaskInfoQueue } from '../queue/task'; - -/** - * 任务中间件 - */ -@Middleware() -export class TaskMiddleware implements IMiddleware { - @Inject() - taskInfoQueue: TaskInfoQueue; - resolve() { - return async (ctx: Context, next: NextFunction) => { - const urls = ctx.url.split('/'); - if ( - ['add', 'update', 'once', 'stop', 'start'].includes( - urls[urls.length - 1] - ) - ) { - if (!this.taskInfoQueue.metaQueue) { - throw new CoolCommException( - 'task插件未启用或redis配置错误或redis版本过低(>=6.x)' - ); - } - } - await next(); - }; - } -} diff --git a/src/modules/task/queue/task.ts b/src/modules/task/queue/task.ts deleted file mode 100644 index 57a713e..0000000 --- a/src/modules/task/queue/task.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { App, Inject } from '@midwayjs/decorator'; -import { BaseCoolQueue, CoolQueue } from '@cool-midway/task'; -import { TaskInfoService } from '../service/info'; -import { IMidwayApplication } from '@midwayjs/core'; - -/** - * 任务 - */ -@CoolQueue() -export abstract class TaskInfoQueue extends BaseCoolQueue { - @App() - app: IMidwayApplication; - - @Inject() - taskInfoService: TaskInfoService; - - async data(job, done: any): Promise { - try { - const result = await this.taskInfoService.invokeService(job.data.service); - this.taskInfoService.record(job.data, 1, JSON.stringify(result)); - } catch (error) { - this.taskInfoService.record(job.data, 0, error.message); - } - if (!job.data.isOnce) { - this.taskInfoService.updateNextRunTime(job.data.id); - this.taskInfoService.updateStatus(job.data.id); - } - done(); - } -} diff --git a/src/modules/task/service/demo.ts b/src/modules/task/service/demo.ts deleted file mode 100644 index 05ef055..0000000 --- a/src/modules/task/service/demo.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Logger, Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { ILogger } from '@midwayjs/logger'; - -/** - * 描述 - */ -@Provide() -export class TaskDemoService extends BaseService { - @Logger() - logger: ILogger; - /** - * 描述 - */ - async test(a, b) { - this.logger.info('我被调用了', a, b); - return '任务执行成功'; - } -} diff --git a/src/modules/task/service/info.ts b/src/modules/task/service/info.ts deleted file mode 100644 index 95504f4..0000000 --- a/src/modules/task/service/info.ts +++ /dev/null @@ -1,361 +0,0 @@ -import { - App, - Inject, - Logger, - Provide, - Scope, - ScopeEnum, -} from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; -import { TaskInfoEntity } from '../entity/info'; -import { TaskLogEntity } from '../entity/log'; -import { ILogger } from '@midwayjs/logger'; -import * as _ from 'lodash'; -import { Utils } from '../../../comm/utils'; -import { TaskInfoQueue } from '../queue/task'; -import { IMidwayApplication } from '@midwayjs/core'; - -/** - * 任务 - */ -@Provide() -@Scope(ScopeEnum.Request, { allowDowngrade: true }) -export class TaskInfoService extends BaseService { - @InjectEntityModel(TaskInfoEntity) - taskInfoEntity: Repository; - - @Logger() - logger: ILogger; - - @InjectEntityModel(TaskLogEntity) - taskLogEntity: Repository; - - @Inject() - taskInfoQueue: TaskInfoQueue; - - @App() - app: IMidwayApplication; - - @Inject() - utils: Utils; - - /** - * 停止任务 - * @param id - */ - async stop(id) { - const task = await this.taskInfoEntity.findOneBy({ id }); - if (task) { - const result = await this.taskInfoQueue.getRepeatableJobs(); - const job = _.find(result, { id: task.id + '' }); - if (job) { - await this.taskInfoQueue.removeRepeatableByKey(job.key); - } - task.status = 0; - await this.taskInfoEntity.update(task.id, task); - await this.updateNextRunTime(task.id); - } - } - - /** - * 移除任务 - * @param taskId - */ - async remove(taskId) { - const result = await this.taskInfoQueue.getRepeatableJobs(); - const job = _.find(result, { id: taskId + '' }); - await this.taskInfoQueue.removeRepeatableByKey(job.key); - } - - /** - * 开始任务 - * @param id - * @param type - */ - async start(id, type?) { - const task = await this.taskInfoEntity.findOneBy({ id }); - task.status = 1; - if (type || type == 0) { - task.type = type; - } - await this.addOrUpdate(task); - } - - /** - * 手动执行一次 - * @param id - */ - async once(id) { - const task = await this.taskInfoEntity.findOneBy({ id }); - if (task) { - await this.taskInfoQueue.add( - { - ...task, - isOnce: true, - }, - { - jobId: task.id.toString(), - removeOnComplete: true, - removeOnFail: true, - } - ); - } - } - - /** - * 检查任务是否存在 - * @param jobId - */ - async exist(jobId) { - const result = await this.taskInfoQueue.getRepeatableJobs(); - const ids = result.map(e => { - return e.id; - }); - return ids.includes(jobId.toString()); - } - - /** - * 新增或修改 - * @param params - */ - async addOrUpdate(params) { - delete params.repeatCount; - let repeatConf; - await this.getOrmManager().transaction(async transactionalEntityManager => { - if (params.taskType === 0) { - params.limit = null; - params.every = null; - } else { - params.cron = null; - } - await transactionalEntityManager.save(TaskInfoEntity, params); - - if (params.status === 1) { - const exist = await this.exist(params.id); - if (exist) { - await this.remove(params.id); - } - const { every, limit, startDate, endDate, cron } = params; - const repeat = { - every, - limit, - jobId: params.id, - startDate, - endDate, - cron, - }; - await this.utils.removeEmptyP(repeat); - const result = await this.taskInfoQueue.add(params, { - jobId: params.id, - removeOnComplete: true, - removeOnFail: true, - repeat, - }); - if (!result) { - throw new Error('任务添加失败,请检查任务配置'); - } - // await transactionalEntityManager.update(TaskInfoEntity, params.id, { - // jobId: params.id, - // type: params.type, - // }); - repeatConf = result.opts; - } - }); - if (params.status === 1) { - this.utils.sleep(1000); - await this.updateNextRunTime(params.id); - await this.nativeQuery( - 'update task_info a set a.repeatConf = ? where a.id = ?', - [JSON.stringify(repeatConf.repeat), params.id] - ); - } - } - - /** - * 删除 - * @param ids - */ - async delete(ids) { - let idArr; - if (ids instanceof Array) { - idArr = ids; - } else { - idArr = ids.split(','); - } - for (const id of idArr) { - const task = await this.taskInfoEntity.findOneBy({ id }); - const exist = await this.exist(task.id); - if (exist) { - this.stop(task.id); - } - await this.taskInfoEntity.delete({ id }); - await this.taskLogEntity.delete({ taskId: id }); - } - } - - /** - * 任务日志 - * @param query - */ - async log(query) { - const { id, status } = query; - return await this.sqlRenderPage( - ` - SELECT - a.*, - b.name AS taskName - FROM - task_log a - JOIN task_info b ON a.taskId = b.id - where 1=1 - ${this.setSql(id, 'and a.taskId = ?', [id])} - ${this.setSql(status, 'and a.status = ?', [status])} - `, - query - ); - } - - /** - * 保存任务记录,成功任务每个任务保留最新20条日志,失败日志不会删除 - * @param task - * @param status - * @param detail - */ - async record(task, status, detail?) { - await this.taskLogEntity.save({ - taskId: task.id, - status, - detail: detail || '', - }); - await this.nativeQuery( - `DELETE a - FROM - task_log a, - ( SELECT id FROM task_log where taskId = ? AND status = 1 ORDER BY id DESC LIMIT ?, 1 ) b - WHERE - a.taskId = ? AND - a.status = 1 AND - a.id < b.id`, - [task.id, 19, task.id] - ); // 日志保留最新的20条 - } - - /** - * 初始化任务 - */ - async initTask() { - try { - await this.utils.sleep(3000); - this.logger.info('init task....'); - const runningTasks = await this.taskInfoEntity.findBy({ status: 1 }); - if (!_.isEmpty(runningTasks)) { - for (const task of runningTasks) { - const job = await this.exist(task.id); // 任务已存在就不添加 - if (!job) { - this.logger.info(`init task ${task.name}`); - await this.addOrUpdate(task); - } - } - } - } catch (e) {} - } - - /** - * 任务ID - * @param jobId - */ - async getNextRunTime(jobId) { - let nextRunTime; - const result = await this.taskInfoQueue.getRepeatableJobs(); - const task = _.find(result, { id: jobId + '' }); - if (task) { - nextRunTime = new Date(task.next); - } - return nextRunTime; - } - - /** - * 更新下次执行时间 - * @param jobId - */ - async updateNextRunTime(jobId) { - await this.taskInfoEntity.update(jobId, { - nextRunTime: await this.getNextRunTime(jobId), - }); - } - - /** - * 详情 - * @param id - * @returns - */ - async info(id: any): Promise { - const info = await this.taskInfoEntity.findOneBy({ id }); - return { - ...info, - repeatCount: info.limit, - }; - } - - /** - * 刷新任务状态 - */ - async updateStatus(jobId) { - const result = await this.taskInfoQueue.getRepeatableJobs(); - const job = _.find(result, { id: jobId + '' }); - if (!job) { - return; - } - const task = await this.taskInfoEntity.findOneBy({ id: job.id }); - const nextTime = await this.getNextRunTime(task.id); - if (task) { - // if (task.nextRunTime.getTime() == nextTime.getTime()) { - // task.status = 0; - // task.nextRunTime = nextTime; - // this.taskInfoQueue.removeRepeatableByKey(job.key); - // } else { - task.nextRunTime = nextTime; - // } - await this.taskInfoEntity.update(task.id, task); - } - } - - /** - * 调用service - * @param serviceStr - */ - async invokeService(serviceStr) { - if (serviceStr) { - const arr = serviceStr.split('.'); - const service = await this.app - .getApplicationContext() - .getAsync(_.lowerFirst(arr[0])); - - for (let i = 1; i < arr.length; i++) { - const child = arr[i]; - if (child.includes('(')) { - const [methodName, paramsStr] = child.split('('); - const params = paramsStr - .replace(')', '') - .split(',') - .map(param => param.trim()); - - if (params.length === 1 && params[0] === '') { - return service[methodName](); - } else { - const parsedParams = params.map(param => { - try { - return JSON.parse(param); - } catch (e) { - return param; // 如果不是有效的JSON,则返回原始字符串 - } - }); - return service[methodName](...parsedParams); - } - } - } - } - } -} diff --git a/src/modules/user/config.ts b/src/modules/user/config.ts deleted file mode 100644 index f0e14f3..0000000 --- a/src/modules/user/config.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ModuleConfig } from '@cool-midway/core'; -import { UserMiddleware } from './middleware/app'; - -/** - * 模块配置 - */ -export default () => { - return { - // 模块名称 - name: '用户模块', - // 模块描述 - description: 'APP、小程序、公众号等用户', - // 中间件,只对本模块有效 - middlewares: [], - // 中间件,全局有效 - globalMiddlewares: [UserMiddleware], - // 模块加载顺序,默认为0,值越大越优先加载 - order: 0, - // 短信 - sms: { - // 验证码有效期,单位秒 - timeout: 60 * 3, - }, - // jwt - jwt: { - // token 过期时间,单位秒 - expire: 60 * 60 * 24, - // 刷新token 过期时间,单位秒 - refreshExpire: 60 * 60 * 24 * 30, - // jwt 秘钥 - secret: 'cool-app-xxxxxx', - }, - } as ModuleConfig; -}; diff --git a/src/modules/user/controller/admin/address.ts b/src/modules/user/controller/admin/address.ts deleted file mode 100644 index fa18ade..0000000 --- a/src/modules/user/controller/admin/address.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CoolController, BaseController } from '@cool-midway/core'; -import { UserAddressEntity } from '../../entity/address'; -import { UserAddressService } from '../../service/address'; - -/** - * 用户-地址 - */ -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: UserAddressEntity, - service: UserAddressService, -}) -export class AdminUserAddressesController extends BaseController {} diff --git a/src/modules/user/controller/admin/info.ts b/src/modules/user/controller/admin/info.ts deleted file mode 100644 index 12f1480..0000000 --- a/src/modules/user/controller/admin/info.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { CoolController, BaseController } from '@cool-midway/core'; -import { UserInfoEntity } from '../../entity/info'; - -/** - * 用户信息 - */ -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: UserInfoEntity, - pageQueryOp: { - fieldEq: ['status', 'gender', 'loginType'], - keyWordLikeFields: ['nickName', 'phone'], - }, -}) -export class AdminUserInfoController extends BaseController {} diff --git a/src/modules/user/controller/app/address.ts b/src/modules/user/controller/app/address.ts deleted file mode 100644 index a10a7fc..0000000 --- a/src/modules/user/controller/app/address.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Get, Inject, Provide } from '@midwayjs/decorator'; -import { CoolController, BaseController } from '@cool-midway/core'; -import { UserAddressEntity } from '../../entity/address'; -import { UserAddressService } from '../../service/address'; - -/** - * 地址 - */ -@Provide() -@CoolController({ - api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: UserAddressEntity, - service: UserAddressService, - insertParam: ctx => { - return { - userId: ctx.user.id, - }; - }, - pageQueryOp: { - where: async ctx => { - return [['userId =:userId', { userId: ctx.user.id }]]; - }, - addOrderBy: { - isDefault: 'DESC', - }, - }, -}) -export class AppUserAddressController extends BaseController { - @Inject() - userAddressService: UserAddressService; - - @Inject() - ctx; - - @Get('/default', { summary: '默认地址' }) - async default() { - return this.ok(await this.userAddressService.default(this.ctx.user.id)); - } -} diff --git a/src/modules/user/controller/app/comm.ts b/src/modules/user/controller/app/comm.ts deleted file mode 100644 index be06d6c..0000000 --- a/src/modules/user/controller/app/comm.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { - CoolController, - BaseController, - CoolUrlTag, - TagTypes, - CoolTag, -} from '@cool-midway/core'; -import { Body, Inject, Post } from '@midwayjs/core'; -import { UserWxService } from '../../service/wx'; - -/** - * 通用 - */ -@CoolUrlTag() -@CoolController() -export class UserCommController extends BaseController { - @Inject() - userWxService: UserWxService; - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/wxMpConfig', { summary: '获取微信公众号配置' }) - public async getWxMpConfig(@Body('url') url: string) { - return this.ok(await this.userWxService.getWxMpConfig(url)); - } -} diff --git a/src/modules/user/controller/app/info.ts b/src/modules/user/controller/app/info.ts deleted file mode 100644 index b1a94ab..0000000 --- a/src/modules/user/controller/app/info.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { CoolController, BaseController } from '@cool-midway/core'; -import { Body, Get, Inject, Post } from '@midwayjs/core'; -import { UserInfoService } from '../../service/info'; -import { UserInfoEntity } from '../../entity/info'; - -/** - * 用户信息 - */ -@CoolController({ - api: [], - entity: UserInfoEntity, -}) -export class AppUserInfoController extends BaseController { - @Inject() - ctx; - - @Inject() - userInfoService: UserInfoService; - - @Get('/person', { summary: '获取用户信息' }) - async person() { - return this.ok(await this.userInfoService.person(this.ctx.user.id)); - } - - @Post('/updatePerson', { summary: '更新用户信息' }) - async updatePerson(@Body() body) { - return this.ok( - await this.userInfoService.updatePerson(this.ctx.user.id, body) - ); - } - - @Post('/updatePassword', { summary: '更新用户密码' }) - async updatePassword( - @Body('password') password: string, - @Body('code') code: string - ) { - await this.userInfoService.updatePassword(this.ctx.user.id, password, code); - return this.ok(); - } - - @Post('/logoff', { summary: '注销' }) - async logoff() { - await this.userInfoService.logoff(this.ctx.user.id); - return this.ok(); - } - - @Post('/bindPhone', { summary: '绑定手机号' }) - async bindPhone(@Body('phone') phone: string, @Body('code') code: string) { - await this.userInfoService.bindPhone(this.ctx.user.id, phone, code); - return this.ok(); - } - - @Post('/miniPhone', { summary: '绑定小程序手机号' }) - async miniPhone(@Body() body) { - const { code, encryptedData, iv } = body; - return this.ok( - await this.userInfoService.miniPhone( - this.ctx.user.id, - code, - encryptedData, - iv - ) - ); - } -} diff --git a/src/modules/user/controller/app/login.ts b/src/modules/user/controller/app/login.ts deleted file mode 100644 index a64ce97..0000000 --- a/src/modules/user/controller/app/login.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { - CoolController, - BaseController, - CoolUrlTag, - TagTypes, - CoolTag, -} from '@cool-midway/core'; -import { Body, Get, Inject, Post, Query } from '@midwayjs/core'; -import { UserLoginService } from '../../service/login'; -import { BaseSysLoginService } from '../../../base/service/sys/login'; - -/** - * 登录 - */ -@CoolUrlTag() -@CoolController() -export class AppUserLoginController extends BaseController { - @Inject() - userLoginService: UserLoginService; - - @Inject() - baseSysLoginService: BaseSysLoginService; - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/mini', { summary: '小程序登录' }) - async mini(@Body() body) { - const { code, encryptedData, iv } = body; - return this.ok(await this.userLoginService.mini(code, encryptedData, iv)); - } - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/mp', { summary: '公众号登录' }) - async mp(@Body('code') code: string) { - return this.ok(await this.userLoginService.mp(code)); - } - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/wxApp', { summary: '微信APP授权登录' }) - async app(@Body('code') code: string) { - return this.ok(await this.userLoginService.wxApp(code)); - } - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/phone', { summary: '手机号登录' }) - async phone(@Body('phone') phone: string, @Body('smsCode') smsCode: string) { - return this.ok(await this.userLoginService.phoneVerifyCode(phone, smsCode)); - } - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/uniPhone', { summary: '一键手机号登录' }) - async uniPhone( - @Body('access_token') access_token: string, - @Body('openid') openid: string, - @Body('appId') appId: string - ) { - return this.ok( - await this.userLoginService.uniPhone(access_token, openid, appId) - ); - } - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/miniPhone', { summary: '绑定小程序手机号' }) - async miniPhone(@Body() body) { - const { code, encryptedData, iv } = body; - return this.ok( - await this.userLoginService.miniPhone(code, encryptedData, iv) - ); - } - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Get('/captcha', { summary: '图片验证码' }) - async captcha( - @Query('type') type: string, - @Query('width') width: number, - @Query('height') height: number, - @Query('color') color: string - ) { - return this.ok( - await this.baseSysLoginService.captcha(type, width, height, color) - ); - } - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/smsCode', { summary: '验证码' }) - async smsCode( - @Body('phone') phone: string, - @Body('captchaId') captchaId: string, - @Body('code') code: string - ) { - return this.ok(await this.userLoginService.smsCode(phone, captchaId, code)); - } - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/refreshToken', { summary: '刷新token' }) - public async refreshToken(@Body('refreshToken') refreshToken) { - return this.ok(await this.userLoginService.refreshToken(refreshToken)); - } - - @CoolTag(TagTypes.IGNORE_TOKEN) - @Post('/password', { summary: '密码登录' }) - async password( - @Body('phone') phone: string, - @Body('password') password: string - ) { - return this.ok(await this.userLoginService.password(phone, password)); - } -} diff --git a/src/modules/user/entity/address.ts b/src/modules/user/entity/address.ts deleted file mode 100644 index 6b93391..0000000 --- a/src/modules/user/entity/address.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Entity, Column, Index } from 'typeorm'; - -/** - * 用户模块-收货地址 - */ -@Entity('user_address') -export class UserAddressEntity extends BaseEntity { - @Index() - @Column({ comment: '用户ID' }) - userId: number; - - @Column({ comment: '联系人' }) - contact: string; - - @Index() - @Column({ comment: '手机号', length: 11 }) - phone: string; - - @Column({ comment: '省' }) - province: string; - - @Column({ comment: '市' }) - city: string; - - @Column({ comment: '区' }) - district: string; - - @Column({ comment: '地址' }) - address: string; - - @Column({ comment: '是否默认', default: false }) - isDefault: boolean; -} diff --git a/src/modules/user/entity/info.ts b/src/modules/user/entity/info.ts deleted file mode 100644 index d0bbac3..0000000 --- a/src/modules/user/entity/info.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity, Index } from 'typeorm'; - -/** - * 用户信息 - */ -@Entity('user_info') -export class UserInfoEntity extends BaseEntity { - @Index({ unique: true }) - @Column({ comment: '登录唯一ID', nullable: true }) - unionid: string; - - @Column({ comment: '头像', nullable: true }) - avatarUrl: string; - - @Column({ comment: '昵称', nullable: true }) - nickName: string; - - @Index({ unique: true }) - @Column({ comment: '手机号', nullable: true }) - phone: string; - - @Column({ comment: '性别 0-未知 1-男 2-女', default: 0 }) - gender: number; - - @Column({ comment: '状态 0-禁用 1-正常 2-已注销', default: 1 }) - status: number; - - @Column({ comment: '登录方式 0-小程序 1-公众号 2-H5', default: 0 }) - loginType: number; - - @Column({ comment: '密码', nullable: true }) - password: string; -} diff --git a/src/modules/user/entity/wx.ts b/src/modules/user/entity/wx.ts deleted file mode 100644 index ca0ae59..0000000 --- a/src/modules/user/entity/wx.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { BaseEntity } from '@cool-midway/core'; -import { Column, Entity, Index } from 'typeorm'; - -/** - * 微信用户 - */ -@Entity('user_wx') -export class UserWxEntity extends BaseEntity { - @Index() - @Column({ comment: '微信unionid', nullable: true }) - unionid: string; - - @Index() - @Column({ comment: '微信openid' }) - openid: string; - - @Column({ comment: '头像', nullable: true }) - avatarUrl: string; - - @Column({ comment: '昵称', nullable: true }) - nickName: string; - - @Column({ comment: '性别 0-未知 1-男 2-女', default: 0 }) - gender: number; - - @Column({ comment: '语言', nullable: true }) - language: string; - - @Column({ comment: '城市', nullable: true }) - city: string; - - @Column({ comment: '省份', nullable: true }) - province: string; - - @Column({ comment: '国家', nullable: true }) - country: string; - - @Column({ comment: '类型 0-小程序 1-公众号 2-H5 3-APP', default: 0 }) - type: number; -} diff --git a/src/modules/user/event/app.ts b/src/modules/user/event/app.ts deleted file mode 100644 index d7861f6..0000000 --- a/src/modules/user/event/app.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { CoolEvent, Event } from '@cool-midway/core'; -import { App, Config, ILogger, Logger } from '@midwayjs/core'; -import { IMidwayKoaApplication } from '@midwayjs/koa'; -import * as fs from 'fs'; -import * as path from 'path'; -import { v1 as uuid } from 'uuid'; - -/** - * 修改jwt.secret - */ -@CoolEvent() -export class UserAppEvent { - @Logger() - coreLogger: ILogger; - - @Config('module') - config; - - @App() - app: IMidwayKoaApplication; - - @Event('onMenuInit') - async onMenuInit() { - if (this.app.getEnv() != 'local') return; - this.checkConfig(); - } - - /** - * 检查配置 - */ - async checkConfig() { - if (this.config.user.jwt.secret == 'cool-app-xxxxxx') { - this.coreLogger.warn( - '\x1B[36m 检测到模块[user] jwt.secret 配置是默认值,请不要关闭!即将自动修改... \x1B[0m' - ); - setTimeout(() => { - const filePath = path.join( - this.app.getBaseDir(), - '..', - 'src', - 'modules', - 'user', - 'config.ts' - ); - // 替换文件内容 - let fileData = fs.readFileSync(filePath, 'utf8'); - const secret = uuid().replace(/-/g, ''); - this.config.user.jwt.secret = secret; - fs.writeFileSync(filePath, fileData.replace('cool-app-xxxxxx', secret)); - this.coreLogger.info( - '\x1B[36m [cool:module:user] midwayjs cool module user auto modify jwt.secret\x1B[0m' - ); - }, 6000); - } - } -} diff --git a/src/modules/user/middleware/app.ts b/src/modules/user/middleware/app.ts deleted file mode 100644 index 7fbba3a..0000000 --- a/src/modules/user/middleware/app.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { ALL, Config, Middleware } from '@midwayjs/decorator'; -import { NextFunction, Context } from '@midwayjs/koa'; -import { IMiddleware, Init, Inject } from '@midwayjs/core'; -import * as jwt from 'jsonwebtoken'; -import * as _ from 'lodash'; -import { CoolUrlTagData, RESCODE, TagTypes } from '@cool-midway/core'; - -/** - * 用户 - */ -@Middleware() -export class UserMiddleware implements IMiddleware { - @Config(ALL) - coolConfig; - - @Inject() - coolUrlTagData: CoolUrlTagData; - - @Config('module.user.jwt') - jwtConfig; - - ignoreUrls: string[] = []; - - @Config('koa.globalPrefix') - prefix; - - @Init() - async init() { - this.ignoreUrls = this.coolUrlTagData.byKey(TagTypes.IGNORE_TOKEN, 'app'); - } - - resolve() { - return async (ctx: Context, next: NextFunction) => { - let { url } = ctx; - url = url.replace(this.prefix, '').split('?')[0]; - if (_.startsWith(url, '/app/')) { - const token = ctx.get('Authorization'); - try { - ctx.user = jwt.verify(token, this.jwtConfig.secret); - if (ctx.user.isRefresh) { - ctx.status = 401; - ctx.body = { - code: RESCODE.COMMFAIL, - message: '登录失效~', - }; - return; - } - } catch (error) {} - // 使用matchUrl方法来检查URL是否应该被忽略 - const isIgnored = this.ignoreUrls.some(pattern => - this.matchUrl(pattern, url) - ); - if (isIgnored) { - await next(); - return; - } else { - if (!ctx.user) { - ctx.status = 401; - ctx.body = { - code: RESCODE.COMMFAIL, - message: '登录失效~', - }; - return; - } - } - } - await next(); - }; - } - - // 匹配URL的方法 - matchUrl(pattern, url) { - const patternSegments = pattern.split('/').filter(Boolean); - const urlSegments = url.split('/').filter(Boolean); - - // 如果段的数量不同,则无法匹配 - if (patternSegments.length !== urlSegments.length) { - return false; - } - - // 逐段进行匹配 - for (let i = 0; i < patternSegments.length; i++) { - if (patternSegments[i].startsWith(':')) { - // 如果模式段以':'开始,我们认为它是一个参数,可以匹配任何内容 - continue; - } - // 如果两个段不相同,则不匹配 - if (patternSegments[i] !== urlSegments[i]) { - return false; - } - } - - // 所有段都匹配 - return true; - } -} diff --git a/src/modules/user/service/address.ts b/src/modules/user/service/address.ts deleted file mode 100644 index 6a3a3a7..0000000 --- a/src/modules/user/service/address.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Init, Inject, Provide } from '@midwayjs/decorator'; -import { BaseService } from '@cool-midway/core'; -import { Equal, Repository } from 'typeorm'; -import { UserAddressEntity } from '../entity/address'; -import { InjectEntityModel } from '@midwayjs/typeorm'; - -/** - * 地址 - */ -@Provide() -export class UserAddressService extends BaseService { - @InjectEntityModel(UserAddressEntity) - userAddressEntity: Repository; - - @Inject() - ctx; - - @Init() - async init() { - await super.init(); - this.setEntity(this.userAddressEntity); - } - - /** - * 列表信息 - */ - async list() { - return this.userAddressEntity - .createQueryBuilder() - .where('userId = :userId ', { userId: this.ctx.user.id }) - .addOrderBy('isDefault', 'DESC') - .getMany(); - } - - /** - * 修改之后 - * @param data - * @param type - */ - async modifyAfter(data: any, type: 'add' | 'update' | 'delete') { - if (type == 'add' || type == 'update') { - if (data.isDefault) { - await this.userAddressEntity - .createQueryBuilder() - .update() - .set({ isDefault: false }) - .where('userId = :userId ', { userId: this.ctx.user.id }) - .andWhere('id != :id', { id: data.id }) - .execute(); - } - } - } - - /** - * 默认地址 - */ - async default(userId) { - return await this.userAddressEntity.findOneBy({ - userId: Equal(userId), - isDefault: true, - }); - } -} diff --git a/src/modules/user/service/info.ts b/src/modules/user/service/info.ts deleted file mode 100644 index 8a340d4..0000000 --- a/src/modules/user/service/info.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { BaseService, CoolCommException } from '@cool-midway/core'; -import { Inject, Provide } from '@midwayjs/decorator'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import * as md5 from 'md5'; -import { Equal, Repository } from 'typeorm'; -import { v1 as uuid } from 'uuid'; -import { PluginService } from '../../plugin/service/info'; -import { UserInfoEntity } from '../entity/info'; -import { UserSmsService } from './sms'; -import { UserWxService } from './wx'; - -/** - * 用户信息 - */ -@Provide() -export class UserInfoService extends BaseService { - @InjectEntityModel(UserInfoEntity) - userInfoEntity: Repository; - - @Inject() - pluginService: PluginService; - - @Inject() - userSmsService: UserSmsService; - - @Inject() - userWxService: UserWxService; - - /** - * 绑定小程序手机号 - * @param userId - * @param code - * @param encryptedData - * @param iv - */ - async miniPhone(userId: number, code: any, encryptedData: any, iv: any) { - const phone = await this.userWxService.miniPhone(code, encryptedData, iv); - await this.userInfoEntity.update({ id: Equal(userId) }, { phone }); - return phone; - } - - /** - * 获取用户信息 - * @param id - * @returns - */ - async person(id) { - const info = await this.userInfoEntity.findOneBy({ id: Equal(id) }); - delete info.password; - return info; - } - - /** - * 注销 - * @param userId - */ - async logoff(userId: number) { - await this.userInfoEntity.update( - { id: userId }, - { - status: 2, - phone: null, - unionid: null, - nickName: `已注销-00${userId}`, - avatarUrl: null, - } - ); - } - - /** - * 更新用户信息 - * @param id - * @param param - * @returns - */ - async updatePerson(id, param) { - const info = await this.person(id); - if (!info) throw new CoolCommException('用户不存在'); - try { - // 修改了头像要重新处理 - if (param.avatarUrl && info.avatarUrl != param.avatarUrl) { - const file = await this.pluginService.getInstance('upload'); - param.avatarUrl = await file.downAndUpload( - param.avatarUrl, - uuid() + '.png' - ); - } - } catch (err) {} - try { - return await this.userInfoEntity.update({ id }, param); - } catch (err) { - throw new CoolCommException('更新失败,参数错误或者手机号已存在'); - } - } - - /** - * 更新密码 - * @param userId - * @param password - * @param 验证码 - */ - async updatePassword(userId, password, code) { - const user = await this.userInfoEntity.findOneBy({ id: userId }); - const check = await this.userSmsService.checkCode(user.phone, code); - if (!check) { - throw new CoolCommException('验证码错误'); - } - await this.userInfoEntity.update(user.id, { password: md5(password) }); - } - - /** - * 绑定手机号 - * @param userId - * @param phone - * @param code - */ - async bindPhone(userId, phone, code) { - const check = await this.userSmsService.checkCode(phone, code); - if (!check) { - throw new CoolCommException('验证码错误'); - } - await this.userInfoEntity.update({ id: userId }, { phone }); - } -} diff --git a/src/modules/user/service/login.ts b/src/modules/user/service/login.ts deleted file mode 100644 index 6d32603..0000000 --- a/src/modules/user/service/login.ts +++ /dev/null @@ -1,307 +0,0 @@ -import { Config, Inject, Provide } from '@midwayjs/decorator'; -import { BaseService, CoolCommException } from '@cool-midway/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Equal, Repository } from 'typeorm'; -import { UserInfoEntity } from '../entity/info'; -import { UserWxService } from './wx'; -import * as jwt from 'jsonwebtoken'; -import { UserWxEntity } from '../entity/wx'; -import { BaseSysLoginService } from '../../base/service/sys/login'; -import { UserSmsService } from './sms'; -import { v1 as uuid } from 'uuid'; -import * as md5 from 'md5'; -import { PluginService } from '../../plugin/service/info'; - -/** - * 登录 - */ -@Provide() -export class UserLoginService extends BaseService { - @InjectEntityModel(UserInfoEntity) - userInfoEntity: Repository; - - @InjectEntityModel(UserWxEntity) - userWxEntity: Repository; - - @Inject() - userWxService: UserWxService; - - @Config('module.user.jwt') - jwtConfig; - - @Inject() - baseSysLoginService: BaseSysLoginService; - - @Inject() - pluginService: PluginService; - - @Inject() - userSmsService: UserSmsService; - - /** - * 发送手机验证码 - * @param phone - * @param captchaId - * @param code - */ - async smsCode(phone, captchaId, code) { - // 1、检查图片验证码 2、发送短信验证码 - const check = await this.baseSysLoginService.captchaCheck(captchaId, code); - if (!check) { - throw new CoolCommException('图片验证码错误'); - } - await this.userSmsService.sendSms(phone); - } - - /** - * 手机验证码登录 - * @param phone - * @param smsCode - */ - async phoneVerifyCode(phone, smsCode) { - // 1、检查短信验证码 2、登录 - const check = await this.userSmsService.checkCode(phone, smsCode); - if (check) { - return await this.phone(phone); - } else { - throw new CoolCommException('验证码错误'); - } - } - - /** - * 小程序手机号登录 - * @param code - * @param encryptedData - * @param iv - */ - async miniPhone(code, encryptedData, iv) { - const phone = await this.userWxService.miniPhone(code, encryptedData, iv); - if (phone) { - return await this.phone(phone); - } else { - throw new CoolCommException('获得手机号失败,请检查配置'); - } - } - - /** - * 手机号一键登录 - * @param access_token - * @param openid - */ - async uniPhone(access_token, openid, appId) { - const instance: any = await this.pluginService.getInstance('uniphone'); - const phone = await instance.getPhone(access_token, openid, appId); - if (phone) { - return await this.phone(phone); - } else { - throw new CoolCommException('获得手机号失败,请检查配置'); - } - } - - /** - * 手机登录 - * @param phone - * @returns - */ - async phone(phone: string) { - let user: any = await this.userInfoEntity.findOneBy({ - phone: Equal(phone), - }); - if (!user) { - user = { - phone, - unionid: phone, - loginType: 2, - nickName: phone.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2'), - }; - await this.userInfoEntity.insert(user); - } - return this.token({ id: user.id }); - } - - /** - * 公众号登录 - * @param code - */ - async mp(code: string) { - let wxUserInfo = await this.userWxService.mpUserInfo(code); - if (wxUserInfo) { - delete wxUserInfo.privilege; - wxUserInfo = await this.saveWxInfo( - { - openid: wxUserInfo.openid, - unionid: wxUserInfo.unionid, - avatarUrl: wxUserInfo.headimgurl, - nickName: wxUserInfo.nickname, - gender: wxUserInfo.sex, - city: wxUserInfo.city, - province: wxUserInfo.province, - country: wxUserInfo.country, - }, - 1 - ); - return this.wxLoginToken(wxUserInfo); - } else { - throw new Error('微信登录失败'); - } - } - - /** - * 微信APP授权登录 - * @param code - */ - async wxApp(code: string) { - let wxUserInfo = await this.userWxService.appUserInfo(code); - if (wxUserInfo) { - delete wxUserInfo.privilege; - wxUserInfo = await this.saveWxInfo( - { - openid: wxUserInfo.openid, - unionid: wxUserInfo.unionid, - avatarUrl: wxUserInfo.headimgurl, - nickName: wxUserInfo.nickname, - gender: wxUserInfo.sex, - city: wxUserInfo.city, - province: wxUserInfo.province, - country: wxUserInfo.country, - }, - 1 - ); - return this.wxLoginToken(wxUserInfo); - } else { - throw new Error('微信登录失败'); - } - } - - /** - * 保存微信信息 - * @param wxUserInfo - * @param type - * @returns - */ - async saveWxInfo(wxUserInfo, type) { - const find: any = { openid: wxUserInfo.openid }; - let wxInfo: any = await this.userWxEntity.findOneBy(find); - if (wxInfo) { - wxUserInfo.id = wxInfo.id; - } - await this.userWxEntity.save({ - ...wxUserInfo, - type, - }); - return wxUserInfo; - } - - /** - * 小程序登录 - * @param code - * @param encryptedData - * @param iv - */ - async mini(code, encryptedData, iv) { - let wxUserInfo = await this.userWxService.miniUserInfo( - code, - encryptedData, - iv - ); - if (wxUserInfo) { - // 保存 - wxUserInfo = await this.saveWxInfo(wxUserInfo, 0); - return await this.wxLoginToken(wxUserInfo); - } - } - - /** - * 微信登录 获得token - * @param wxUserInfo 微信用户信息 - * @returns - */ - async wxLoginToken(wxUserInfo) { - const unionid = wxUserInfo.unionid ? wxUserInfo.unionid : wxUserInfo.openid; - let userInfo: any = await this.userInfoEntity.findOneBy({ unionid }); - if (!userInfo) { - const file = await this.pluginService.getInstance('upload'); - const avatarUrl = await file.downAndUpload( - wxUserInfo.avatarUrl, - uuid() + '.png' - ); - userInfo = { - unionid, - nickName: wxUserInfo.nickName, - avatarUrl, - gender: wxUserInfo.gender, - }; - await this.userInfoEntity.insert(userInfo); - } - return this.token({ id: userInfo.id }); - } - - /** - * 刷新token - * @param refreshToken - */ - async refreshToken(refreshToken) { - try { - const info = jwt.verify(refreshToken, this.jwtConfig.secret); - if (!info['isRefresh']) { - throw new CoolCommException('token类型非refreshToken'); - } - const userInfo = await this.userInfoEntity.findOneBy({ - id: info['id'], - }); - return this.token({ id: userInfo.id }); - } catch (e) { - throw new CoolCommException( - '刷新token失败,请检查refreshToken是否正确或过期' - ); - } - } - - /** - * 密码登录 - * @param phone - * @param password - */ - async password(phone, password) { - const user = await this.userInfoEntity.findOneBy({ phone }); - - if (user && user.password == md5(password)) { - return this.token({ - id: user.id, - }); - } else { - throw new CoolCommException('账号或密码错误'); - } - } - - /** - * 获得token - * @param info - * @returns - */ - async token(info) { - const { expire, refreshExpire } = this.jwtConfig; - return { - expire, - token: await this.generateToken(info), - refreshExpire, - refreshToken: await this.generateToken(info, true), - }; - } - - /** - * 生成token - * @param tokenInfo 信息 - * @param roleIds 角色集合 - */ - async generateToken(info, isRefresh = false) { - const { expire, refreshExpire, secret } = this.jwtConfig; - const tokenInfo = { - isRefresh, - ...info, - }; - return jwt.sign(tokenInfo, secret, { - expiresIn: isRefresh ? refreshExpire : expire, - }); - } -} diff --git a/src/modules/user/service/sms.ts b/src/modules/user/service/sms.ts deleted file mode 100644 index 561d4ec..0000000 --- a/src/modules/user/service/sms.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { - Provide, - Config, - Inject, - Init, - InjectClient, -} from '@midwayjs/decorator'; -import { BaseService, CoolCommException } from '@cool-midway/core'; -import * as _ from 'lodash'; -import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; -import { PluginService } from '../../plugin/service/info'; - -/** - * 描述 - */ -@Provide() -export class UserSmsService extends BaseService { - // 获得模块的配置信息 - @Config('module.user.sms') - config; - - @InjectClient(CachingFactory, 'default') - midwayCache: MidwayCache; - - @Inject() - pluginService: PluginService; - - plugin; - - @Init() - async init() { - for (const key of ['sms-tx', 'sms-ali']) { - try { - this.plugin = await this.pluginService.getInstance(key); - if (this.plugin) { - this.config.pluginKey = key; - break; - } - } catch (e) { - continue; - } - } - } - - /** - * 发送验证码 - * @param phone - */ - async sendSms(phone) { - // 随机四位验证码 - const code = _.random(1000, 9999); - const pluginKey = this.config.pluginKey; - if (!this.plugin) - throw new CoolCommException( - '未配置短信插件,请到插件市场下载安装配置:https://cool-js.com/plugin?keyWord=短信' - ); - try { - if (pluginKey == 'sms-tx') { - await this.plugin.send([phone], [code]); - } - if (pluginKey == 'sms-ali') { - await this.plugin.send([phone], { - code, - }); - } - this.midwayCache.set(`sms:${phone}`, code, this.config.timeout * 1000); - } catch (error) { - throw new CoolCommException('发送过于频繁,请稍后再试'); - } - } - - /** - * 验证验证码 - * @param phone - * @param code - * @returns - */ - async checkCode(phone, code) { - const cacheCode = await this.midwayCache.get(`sms:${phone}`); - if (code && cacheCode == code) { - return true; - } - return false; - } -} diff --git a/src/modules/user/service/wx.ts b/src/modules/user/service/wx.ts deleted file mode 100644 index 7e126db..0000000 --- a/src/modules/user/service/wx.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { BaseService, CoolCommException } from '@cool-midway/core'; -import { Config, Inject, Provide } from '@midwayjs/decorator'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import axios from 'axios'; -import * as crypto from 'crypto'; -import * as moment from 'moment'; -import { Equal, Repository } from 'typeorm'; -import { v1 as uuid } from 'uuid'; -import { PluginService } from '../../plugin/service/info'; -import { UserInfoEntity } from '../entity/info'; -import { UserWxEntity } from '../entity/wx'; - -/** - * 微信 - */ -@Provide() -export class UserWxService extends BaseService { - @Config('module.user') - config; - - @InjectEntityModel(UserInfoEntity) - userInfoEntity: Repository; - - @InjectEntityModel(UserWxEntity) - userWxEntity: Repository; - - @Inject() - pluginService: PluginService; - - /** - * 获得插件实例 - * @returns - */ - async getPlugin() { - try { - const wxPlugin: any = await this.pluginService.getInstance('wx'); - return wxPlugin; - } catch (error) { - throw new CoolCommException( - '未配置微信插件,请到插件市场下载安装配置:https://cool-js.com/plugin/70' - ); - } - } - - /** - * 获得小程序实例 - * @returns - */ - async getMiniApp() { - const wxPlugin: any = await this.getPlugin(); - return wxPlugin.MiniApp(); - } - - /** - * 获得公众号实例 - * @returns - */ - async getOfficialAccount() { - const wxPlugin: any = await this.getPlugin(); - return wxPlugin.OfficialAccount(); - } - - /** - * 获得App实例 - * @returns - */ - async getOpenPlatform() { - const wxPlugin: any = await this.getPlugin(); - return wxPlugin.OpenPlatform(); - } - - /** - * 获得用户的openId - * @param userId - * @param type 0-小程序 1-公众号 2-App - */ - async getOpenid(userId: number, type = 0) { - const user = await this.userInfoEntity.findOneBy({ - id: Equal(userId), - status: 1, - }); - if (!user) { - throw new CoolCommException('用户不存在或已被禁用'); - } - const wx = await this.userWxEntity - .createQueryBuilder('a') - .where('a.type = :type', { type }) - .andWhere('(a.unionid = :unionid or a.openid =:openid )', { - unionid: user.unionid, - openid: user.unionid, - }) - .getOne(); - return wx ? wx.openid : null; - } - - /** - * 获得微信配置 - * @param appId - * @param appSecret - * @param url 当前网页的URL,不包含#及其后面部分(必须是调用JS接口页面的完整URL) - */ - public async getWxMpConfig(url: string) { - const token = await this.getWxToken(); - const ticket = await axios.get( - 'https://api.weixin.qq.com/cgi-bin/ticket/getticket', - { - params: { - access_token: token, - type: 'jsapi', - }, - } - ); - - const account = (await this.getOfficialAccount()).getAccount(); - const appid = account.getAppId(); - // 返回结果集 - const result = { - timestamp: parseInt(moment().valueOf() / 1000 + ''), - nonceStr: uuid(), - appId: appid, //appid - signature: '', - }; - const signArr = []; - signArr.push('jsapi_ticket=' + ticket.data.ticket); - signArr.push('noncestr=' + result.nonceStr); - signArr.push('timestamp=' + result.timestamp); - signArr.push('url=' + decodeURI(url)); - // 敏感信息加密处理 - result.signature = crypto - .createHash('sha1') - .update(signArr.join('&')) - .digest('hex') - .toUpperCase(); - return result; - } - - /** - * 获得公众号用户信息 - * @param code - */ - async mpUserInfo(code) { - const token = await this.openOrMpToken(code, 'mp'); - return await this.openOrMpUserInfo(token); - } - - /** - * 获得app用户信息 - * @param code - */ - async appUserInfo(code) { - const token = await this.openOrMpToken(code, 'open'); - return await this.openOrMpUserInfo(token); - } - - /** - * 获得微信token 不用code - * @param appid - * @param secret - */ - public async getWxToken(type = 'mp') { - let app; - if (type == 'mp') { - app = await this.getOfficialAccount(); - } else { - app = await this.getOpenPlatform(); - } - return await app.getAccessToken().getToken(); - } - - /** - * 获得用户信息 - * @param token - */ - async openOrMpUserInfo(token) { - return await axios - .get('https://api.weixin.qq.com/sns/userinfo', { - params: { - access_token: token.access_token, - openid: token.openid, - lang: 'zh_CN', - }, - }) - .then(res => { - return res.data; - }); - } - - /** - * 获得token嗯 - * @param code - * @param type - */ - async openOrMpToken(code, type = 'mp') { - const account = - type == 'mp' - ? (await this.getOfficialAccount()).getAccount() - : (await this.getMiniApp()).getAccount(); - const result = await axios.get( - 'https://api.weixin.qq.com/sns/oauth2/access_token', - { - params: { - appid: account.getAppId(), - secret: account.getSecret(), - code, - grant_type: 'authorization_code', - }, - } - ); - return result.data; - } - - /** - * 获得小程序session - * @param code 微信code - * @param conf 配置 - */ - async miniSession(code) { - const app = await this.getMiniApp(); - const utils = app.getUtils(); - const result = await utils.codeToSession(code); - return result; - } - - /** - * 获得小程序用户信息 - * @param code - * @param encryptedData - * @param iv - */ - async miniUserInfo(code, encryptedData, iv) { - const session = await this.miniSession(code); - if (session.errcode) { - throw new CoolCommException('登录失败,请重试'); - } - const info: any = await this.miniDecryptData( - encryptedData, - iv, - session.session_key - ); - if (info) { - delete info['watermark']; - return { - ...info, - openid: session['openid'], - unionid: session['unionid'], - }; - } - return null; - } - - /** - * 获得小程序手机 - * @param code - * @param encryptedData - * @param iv - */ - async miniPhone(code, encryptedData, iv) { - const session = await this.miniSession(code); - if (session.errcode) { - throw new CoolCommException('获取手机号失败,请刷新重试'); - } - const result = await this.miniDecryptData( - encryptedData, - iv, - session.session_key - ); - return result.phoneNumber; - } - - /** - * 小程序信息解密 - * @param encryptedData - * @param iv - * @param sessionKey - */ - async miniDecryptData(encryptedData, iv, sessionKey) { - const app = await this.getMiniApp(); - const utils = app.getUtils(); - return await utils.decryptSession(sessionKey, iv, encryptedData); - } -} diff --git a/src/welcome.ts b/src/welcome.ts deleted file mode 100644 index 0d937e8..0000000 --- a/src/welcome.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Controller, Get, Inject } from '@midwayjs/decorator'; -import { Context } from '@midwayjs/koa'; -import * as packageJson from '../package.json'; - -/** - * 欢迎界面 - */ -@Controller('/') -export class WelcomeController { - @Inject() - ctx: Context; - - @Get('/', { summary: '欢迎界面' }) - public async welcome() { - await this.ctx.render('welcome', { - text: `HELLO COOL-ADMIN v${packageJson.version} 全栈开发就用COOL!!!`, - }); - } -} diff --git a/test/README.md b/test/README.md deleted file mode 100644 index 7effc7e..0000000 --- a/test/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# 测试方式 - -考虑到cool-admin采用了自动化路由技术,它与官方集成的jest测试工具并不兼容。为确保测试环境与实际的开发环境保持一致,我们并不推荐使用jest进行测试。 - -# 自动化测试API工具 - -我们为您推荐以下的自动化API测试工具: - -- [Apifox](https://apifox.com/) -- [ApiPost](https://www.apipost.cn/) - -同时这些工具也方便写API接口文档,更加灵活有用 \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 9e88494..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "compileOnSave": true, - "compilerOptions": { - "target": "es2018", - "module": "commonjs", - "moduleResolution": "node", - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "inlineSourceMap": true, - "noImplicitThis": true, - "noUnusedLocals": false, - "stripInternal": true, - "skipLibCheck": true, - "resolveJsonModule": true, - "pretty": true, - "declaration": false, - "noImplicitAny": false, - "typeRoots": [ - "typings", - "./node_modules/@types" - ], - "outDir": "dist", - "rootDir": "src" - }, - "exclude": [ - "dist", - "node_modules", - "test" - ] -} \ No newline at end of file diff --git a/typings/plugin.d.ts b/typings/plugin.d.ts deleted file mode 100644 index e2ae5a0..0000000 --- a/typings/plugin.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { BaseUpload, MODETYPE } from './upload'; -type AnyString = string & {}; -/** - * 插件类型声明 - */ -interface PluginMap { - upload: BaseUpload; -} diff --git a/typings/upload.d.ts b/typings/upload.d.ts deleted file mode 100644 index 4f0cdfc..0000000 --- a/typings/upload.d.ts +++ /dev/null @@ -1,56 +0,0 @@ -// 模式 -export enum MODETYPE { - // 本地 - LOCAL = 'local', - // 云存储 - CLOUD = 'cloud', - // 其他 - OTHER = 'other', -} - -/** - * 上传模式 - */ -export interface Mode { - // 模式 - mode: MODETYPE; - // 类型 - type: string; -} - -/** - * 文件上传 - */ -export interface BaseUpload { - /** - * 获得上传模式 - */ - getMode(): Promise; - - /** - * 获得原始操作对象 - * @returns - */ - getMetaFileObj(): Promise; - - /** - * 下载并上传 - * @param url - * @param fileName 文件名 - */ - downAndUpload(url: string, fileName?: string): Promise; - - /** - * 指定Key(路径)上传,本地文件上传到存储服务 - * @param filePath 文件路径 - * @param key 路径一致会覆盖源文件 - */ - uploadWithKey(filePath, key): Promise; - - /** - * 上传文件 - * @param ctx - * @param key 文件路径 - */ - upload(ctx): Promise; -} diff --git a/view/welcome.html b/view/welcome.html deleted file mode 100644 index 923ac48..0000000 --- a/view/welcome.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - COOL-AMIND 一个很酷的后台权限管理系统 - - - - - - -
<%= text %>
- - - - - - - -