mirror of
https://github.com/cool-team-official/cool-admin-midway.git
synced 2026-01-28 19:28:13 +00:00
发布6.x
This commit is contained in:
parent
95545591f2
commit
375a93638b
9
.gitignore
vendored
Executable file → Normal file
9
.gitignore
vendored
Executable file → Normal file
@ -1,4 +1,5 @@
|
||||
logs/
|
||||
cache/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
node_modules/
|
||||
@ -9,11 +10,11 @@ dist/
|
||||
.idea/
|
||||
run/
|
||||
.DS_Store
|
||||
launch.json
|
||||
*.sw*
|
||||
*.un~
|
||||
.tsbuildinfo
|
||||
.tsbuildinfo.*
|
||||
.audit
|
||||
typings/
|
||||
public/uploads/
|
||||
cache/
|
||||
data/*
|
||||
pnpm-lock.yaml
|
||||
public/uploads/*
|
||||
|
||||
9
.hintrc
Normal file
9
.hintrc
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": [
|
||||
"development"
|
||||
],
|
||||
"hints": {
|
||||
"typescript-config/consistent-casing": "off",
|
||||
"typescript-config/strict": "off"
|
||||
}
|
||||
}
|
||||
1
.vscode/controller.code-snippets
vendored
1
.vscode/controller.code-snippets
vendored
@ -8,7 +8,6 @@
|
||||
"/**",
|
||||
" * 描述",
|
||||
" */",
|
||||
"@Provide()",
|
||||
"@CoolController({",
|
||||
" api: ['add', 'delete', 'update', 'info', 'list', 'page'],",
|
||||
" entity: 实体,",
|
||||
|
||||
5
.vscode/entity.code-snippets
vendored
5
.vscode/entity.code-snippets
vendored
@ -2,14 +2,13 @@
|
||||
"entity": {
|
||||
"prefix": "entity",
|
||||
"body": [
|
||||
"import { EntityModel } from '@midwayjs/orm';",
|
||||
"import { BaseEntity } from '@cool-midway/core';",
|
||||
"import { Column } from 'typeorm';",
|
||||
"import { Column, Entity } from 'typeorm';",
|
||||
"",
|
||||
"/**",
|
||||
" * 描述",
|
||||
" */",
|
||||
"@EntityModel('xxx_xxx_xxx')",
|
||||
"@Entity('xxx_xxx_xxx')",
|
||||
"export class XxxEntity extends BaseEntity {",
|
||||
" @Column({ comment: '描述' })",
|
||||
" xxx: string;",
|
||||
|
||||
1
.vscode/event.code-snippets
vendored
1
.vscode/event.code-snippets
vendored
@ -2,7 +2,6 @@
|
||||
"event": {
|
||||
"prefix": "event",
|
||||
"body": [
|
||||
"import { Provide, Scope, ScopeEnum } from '@midwayjs/decorator';",
|
||||
"import { CoolEvent, Event } from '@cool-midway/core';",
|
||||
"",
|
||||
"/**",
|
||||
|
||||
21
.vscode/launch.json
vendored
21
.vscode/launch.json
vendored
@ -1,21 +0,0 @@
|
||||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${workspaceFolder}/bootstrap.js",
|
||||
"preLaunchTask": "tsc: build - tsconfig.json",
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
2
.vscode/service.code-snippets
vendored
2
.vscode/service.code-snippets
vendored
@ -4,7 +4,7 @@
|
||||
"body": [
|
||||
"import { Provide } from '@midwayjs/decorator';",
|
||||
"import { BaseService } from '@cool-midway/core';",
|
||||
"import { InjectEntityModel } from '@midwayjs/orm';",
|
||||
"import { InjectEntityModel } from '@midwayjs/typeorm';",
|
||||
"import { Repository } from 'typeorm';",
|
||||
"",
|
||||
"/**",
|
||||
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,3 +0,0 @@
|
||||
{
|
||||
"liveServer.settings.port": 5501
|
||||
}
|
||||
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 cool-team-official
|
||||
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
|
||||
|
||||
36
docker-compose.yml
Normal file
36
docker-compose.yml
Normal file
@ -0,0 +1,36 @@
|
||||
# 本地数据库环境
|
||||
# 数据存放在当前目录下的 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" # 业务库密码
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
||||
coolRedis:
|
||||
image: redis
|
||||
#command: --requirepass "12345678" # redis库密码,不需要密码注释本行
|
||||
restart: always
|
||||
environment:
|
||||
TZ: Asia/Shanghai # 指定时区
|
||||
volumes:
|
||||
- ./data/redis/:/data/
|
||||
ports:
|
||||
- 6379:6379
|
||||
83
package.json
Executable file → Normal file
83
package.json
Executable file → Normal file
@ -1,61 +1,68 @@
|
||||
{
|
||||
"name": "cool-admin",
|
||||
"version": "5.0.0",
|
||||
"description": "",
|
||||
"version": "6.0.0",
|
||||
"description": "一个项目用COOL就够了",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@cool-midway/core": "^5.1.7",
|
||||
"@cool-midway/es": "^5.0.2",
|
||||
"@cool-midway/file": "^5.0.7",
|
||||
"@cool-midway/pay": "^5.0.0",
|
||||
"@cool-midway/rpc": "^5.0.1",
|
||||
"@cool-midway/task": "^5.0.1",
|
||||
"@midwayjs/bootstrap": "^3.2.0",
|
||||
"@midwayjs/core": "^3.2.0",
|
||||
"@midwayjs/decorator": "^3.1.6",
|
||||
"@midwayjs/info": "^3.2.0",
|
||||
"@midwayjs/koa": "^3.2.0",
|
||||
"@midwayjs/logger": "^2.16.3",
|
||||
"@midwayjs/orm": "^3.2.0",
|
||||
"@midwayjs/socketio": "^3.2.0",
|
||||
"@midwayjs/static-file": "^3.2.0",
|
||||
"@midwayjs/task": "^3.2.2",
|
||||
"@midwayjs/validate": "^3.2.0",
|
||||
"@midwayjs/view-ejs": "^3.2.0",
|
||||
"cfork": "^1.8.0",
|
||||
"@cool-midway/cloud": "^6.0.0",
|
||||
"@cool-midway/core": "^6.0.0",
|
||||
"@cool-midway/file": "^6.0.0",
|
||||
"@cool-midway/iot": "^6.0.0",
|
||||
"@cool-midway/pay": "^6.0.0",
|
||||
"@cool-midway/rpc": "^6.0.1",
|
||||
"@cool-midway/task": "^6.0.0",
|
||||
"@midwayjs/bootstrap": "^3.10.7",
|
||||
"@midwayjs/cache": "^3.10.9",
|
||||
"@midwayjs/core": "^3.10.7",
|
||||
"@midwayjs/cross-domain": "^3.10.8",
|
||||
"@midwayjs/decorator": "^3.10.7",
|
||||
"@midwayjs/info": "^3.10.7",
|
||||
"@midwayjs/koa": "^3.10.7",
|
||||
"@midwayjs/logger": "^2.17.0",
|
||||
"@midwayjs/static-file": "^3.10.8",
|
||||
"@midwayjs/task": "^3.6.0",
|
||||
"@midwayjs/typeorm": "^3.10.7",
|
||||
"@midwayjs/validate": "^3.10.7",
|
||||
"@midwayjs/view-ejs": "^3.10.7",
|
||||
"cache-manager-fs-hash": "^1.0.0",
|
||||
"ipip-ipdb": "^0.6.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"md5": "^2.3.0",
|
||||
"mini-svg-data-uri": "^1.4.4",
|
||||
"mysql2": "^2.3.3",
|
||||
"moment": "^2.29.4",
|
||||
"mysql2": "^3.1.2",
|
||||
"svg-captcha": "^1.4.0",
|
||||
"typeorm": "0.2.45"
|
||||
"typeorm": "^0.3.12",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@midwayjs/cli": "1.3.12-beta.1",
|
||||
"@midwayjs/mock": "^3.2.0",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/koa": "^2.13.4",
|
||||
"@types/node": "17",
|
||||
"@midwayjs/cli": "^2.0.11",
|
||||
"@midwayjs/mock": "^3.10.7",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/koa": "^2.13.5",
|
||||
"@types/node": "18",
|
||||
"cross-env": "^7.0.3",
|
||||
"jest": "^27.5.1",
|
||||
"jest": "^29.4.2",
|
||||
"mwts": "^1.3.0",
|
||||
"swagger-ui-dist": "^4.9.1",
|
||||
"ts-jest": "^27.1.4",
|
||||
"typescript": "^4.6.3"
|
||||
"ts-jest": "^29.0.5",
|
||||
"typescript": "~4.9.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start_single": "NODE_ENV=prod node ./bootstrap.js",
|
||||
"start": "NODE_ENV=prod node ./server.js",
|
||||
"start": "NODE_ENV=production node ./bootstrap.js",
|
||||
"dev": "cross-env && cross-env NODE_ENV=local TS_NODE_TYPE_CHECK=false TS_NODE_TRANSPILE_ONLY=true midway-bin dev --ts",
|
||||
"test": "midway-bin test --ts",
|
||||
"cov": "midway-bin cov --ts",
|
||||
"lint": "mwts check",
|
||||
"lint:fix": "mwts fix",
|
||||
"ci": "npm run cov",
|
||||
"build": "midway-bin build -c"
|
||||
"build": "midway-bin build -c",
|
||||
"pm2:start": "pm2 start ./bootstrap.js -i max --name cool-admin",
|
||||
"pm2:stop": "pm2 stop cool-admin & pm2 delete cool-admin",
|
||||
"pm2:debug": "pm2-runtime start ./bootstrap.js -i max --name cool-admin"
|
||||
},
|
||||
"midway-bin-clean": [
|
||||
".vscode/.tsbuildinfo",
|
||||
@ -63,8 +70,8 @@
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": ""
|
||||
"url": "https://cool-js.com"
|
||||
},
|
||||
"author": "anonymous",
|
||||
"author": "COOL",
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 5.7 KiB |
51
server.js
51
server.js
@ -1,51 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const cfork = require('cfork');
|
||||
const util = require('util');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
|
||||
// 获取 cpu 核数
|
||||
const cpuNumbers = os.cpus().length;
|
||||
|
||||
cfork({
|
||||
exec: path.join(__dirname, './bootstrap.js'),
|
||||
count: cpuNumbers,
|
||||
})
|
||||
.on('fork', worker => {
|
||||
console.warn(
|
||||
'[%s] [worker:%d] new worker start',
|
||||
Date(),
|
||||
worker.process.pid
|
||||
);
|
||||
})
|
||||
.on('disconnect', worker => {
|
||||
console.warn(
|
||||
'[%s] [master:%s] wroker:%s disconnect, exitedAfterDisconnect: %s, state: %s.',
|
||||
Date(),
|
||||
process.pid,
|
||||
worker.process.pid,
|
||||
worker.exitedAfterDisconnect,
|
||||
worker.state
|
||||
);
|
||||
})
|
||||
.on('exit', (worker, code, signal) => {
|
||||
const exitCode = worker.process.exitCode;
|
||||
const err = new Error(
|
||||
util.format(
|
||||
'worker %s died (code: %s, signal: %s, exitedAfterDisconnect: %s, state: %s)',
|
||||
worker.process.pid,
|
||||
exitCode,
|
||||
signal,
|
||||
worker.exitedAfterDisconnect,
|
||||
worker.state
|
||||
)
|
||||
);
|
||||
err.name = 'WorkerDiedError';
|
||||
console.error(
|
||||
'[%s] [master:%s] wroker exit: %s',
|
||||
Date(),
|
||||
process.pid,
|
||||
err.stack
|
||||
);
|
||||
});
|
||||
@ -1,27 +1,25 @@
|
||||
import { CoolConfig } from '@cool-midway/core';
|
||||
import { MODETYPE } from '@cool-midway/file';
|
||||
import { CoolConfig, MODETYPE } from '@cool-midway/core';
|
||||
import { MidwayConfig } from '@midwayjs/core';
|
||||
// import * as redisStore from 'cache-manager-ioredis';
|
||||
import * as fsStore from 'cache-manager-fs-hash';
|
||||
|
||||
export default {
|
||||
// 修改成你自己独有的key
|
||||
// use for cookie sign key, should change to your own and keep security
|
||||
keys: 'cool-admin for node',
|
||||
koa: {
|
||||
port: 8001,
|
||||
},
|
||||
// 文件上传
|
||||
upload: {
|
||||
fileSize: '200mb',
|
||||
whitelist: null,
|
||||
},
|
||||
// 模板渲染
|
||||
view: {
|
||||
mapping: {
|
||||
'.html': 'ejs',
|
||||
},
|
||||
},
|
||||
// 本地缓存
|
||||
// 文件上传
|
||||
upload: {
|
||||
fileSize: '200mb',
|
||||
whitelist: null,
|
||||
},
|
||||
// 缓存 可切换成其他缓存如:redis http://midwayjs.org/docs/extensions/cache
|
||||
cache: {
|
||||
store: fsStore,
|
||||
options: {
|
||||
@ -29,34 +27,12 @@ export default {
|
||||
ttl: -1,
|
||||
},
|
||||
},
|
||||
// redis缓存
|
||||
// cache: {
|
||||
// store: redisStore,
|
||||
// options: {
|
||||
// host: '127.0.0.1',
|
||||
// port: 6379,
|
||||
// password: '',
|
||||
// db: 1,
|
||||
// ttl: null,
|
||||
// },
|
||||
// },
|
||||
// cool配置
|
||||
cool: {
|
||||
// redis: {
|
||||
// host: '127.0.0.1',
|
||||
// port: 6379,
|
||||
// db: 0,
|
||||
// },
|
||||
// 是否自动导入数据库
|
||||
file: {
|
||||
// 上传模式 本地上传或云存储
|
||||
mode: MODETYPE.LOCAL,
|
||||
// 本地上传 文件地址前缀,当且仅当mode为LOCAL时生效
|
||||
// 本地上传 文件地址前缀
|
||||
domain: 'http://127.0.0.1:8001',
|
||||
},
|
||||
} as CoolConfig,
|
||||
} as
|
||||
| MidwayConfig
|
||||
| {
|
||||
cache: any;
|
||||
};
|
||||
} as MidwayConfig;
|
||||
|
||||
@ -5,22 +5,35 @@ import { MidwayConfig } from '@midwayjs/core';
|
||||
* 本地开发 npm run dev 读取的配置文件
|
||||
*/
|
||||
export default {
|
||||
orm: {
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: '123456',
|
||||
database: 'cool',
|
||||
// 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失
|
||||
synchronize: true,
|
||||
// 打印日志
|
||||
logging: true,
|
||||
// 字符集
|
||||
charset: 'utf8mb4',
|
||||
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: {
|
||||
// 是否自动导入数据库
|
||||
initDB: true,
|
||||
// crud配置
|
||||
crud: {
|
||||
// 软删除
|
||||
softDelete: true,
|
||||
},
|
||||
} as CoolConfig,
|
||||
} as MidwayConfig;
|
||||
|
||||
@ -5,22 +5,30 @@ import { MidwayConfig } from '@midwayjs/core';
|
||||
* 本地开发 npm run dev 读取的配置文件
|
||||
*/
|
||||
export default {
|
||||
orm: {
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: '123456',
|
||||
database: 'cool',
|
||||
// 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失
|
||||
synchronize: false,
|
||||
// 打印日志
|
||||
logging: false,
|
||||
// 字符集
|
||||
charset: 'utf8mb4',
|
||||
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;
|
||||
|
||||
@ -1,48 +1,51 @@
|
||||
import * as orm from '@midwayjs/typeorm';
|
||||
import { Configuration, App } 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 staticFile from '@midwayjs/static-file';
|
||||
import * as view from '@midwayjs/view-ejs';
|
||||
import * as orm from '@midwayjs/orm';
|
||||
import * as cool from '@cool-midway/core';
|
||||
import * as file from '@cool-midway/file';
|
||||
import * as staticFile from '@midwayjs/static-file';
|
||||
import * as localTask from '@midwayjs/task';
|
||||
// import * as socketio from '@midwayjs/socketio';
|
||||
// import * as crossDomain from '@midwayjs/cross-domain';
|
||||
import * as cool from '@cool-midway/core';
|
||||
import * as cloud from '@cool-midway/cloud';
|
||||
import * as file from '@cool-midway/file';
|
||||
// import * as rpc from '@cool-midway/rpc';
|
||||
// import * as task from '@cool-midway/task';
|
||||
// import * as pay from '@cool-midway/pay';
|
||||
// import * as es from '@cool-midway/es';
|
||||
// import * as rpc from '@cool-midway/rpc';
|
||||
// import * as iot from '@cool-midway/iot';
|
||||
|
||||
@Configuration({
|
||||
imports: [
|
||||
// http://koajs.cn/
|
||||
// https://koajs.com/
|
||||
koa,
|
||||
// 参数验证 http://midwayjs.org/docs/extensions/validate
|
||||
validate,
|
||||
// 本地任务 http://midwayjs.org/docs/extensions/task
|
||||
localTask,
|
||||
// 模板渲染 http://midwayjs.org/docs/extensions/render
|
||||
// 是否开启跨域(注:顺序不能乱放!!!) http://www.midwayjs.org/docs/extensions/cross_domain
|
||||
// crossDomain,
|
||||
// 模板渲染 https://midwayjs.org/docs/extensions/render
|
||||
view,
|
||||
// 静态文件托管 http://midwayjs.org/docs/extensions/static_file
|
||||
// 静态文件托管 https://midwayjs.org/docs/extensions/static_file
|
||||
staticFile,
|
||||
// typeorm https://typeorm.io 打不开? https://typeorm.biunav.com/zh/
|
||||
// orm https://midwayjs.org/docs/extensions/orm
|
||||
orm,
|
||||
// socketio http://www.midwayjs.org/docs/extensions/socketio
|
||||
// socketio,
|
||||
// cool-admin 官方组件 https://www.cool-js.com
|
||||
// 参数验证 https://midwayjs.org/docs/extensions/validate
|
||||
validate,
|
||||
// 本地任务 http://midwayjs.org/docs/legacy/task
|
||||
localTask,
|
||||
// cool-admin 官方组件 https://cool-js.com
|
||||
cool,
|
||||
// 文件上传 阿里云存储 腾讯云存储 七牛云存储
|
||||
// 文件上传 本地 阿里云存储 腾讯云存储 七牛云存储
|
||||
file,
|
||||
// 任务与队列
|
||||
// task,
|
||||
// 支付 微信与支付宝
|
||||
// pay,
|
||||
// elasticsearch
|
||||
// es,
|
||||
// rpc 微服务 远程调用
|
||||
// rpc,
|
||||
// 任务与队列
|
||||
// task,
|
||||
// cool-admin 云开发组件
|
||||
cloud,
|
||||
// 支付(微信、支付宝) https://cool-js.com/admin/node/core/pay.html
|
||||
// pay,
|
||||
// 物联网开发,如MQTT支持等
|
||||
// iot,
|
||||
{
|
||||
component: info,
|
||||
enabledEnvironment: ['local'],
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
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';
|
||||
@ -15,4 +15,21 @@ import { BaseSysMenuService } from '../../../service/sys/menu';
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { Column, Index } from 'typeorm';
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { Column, Index, Entity } from 'typeorm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 系统配置
|
||||
*/
|
||||
@EntityModel('base_sys_conf')
|
||||
@Entity('base_sys_conf')
|
||||
export class BaseSysConfEntity extends BaseEntity {
|
||||
@Index({ unique: true })
|
||||
@Column({ comment: '配置键' })
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column } from 'typeorm';
|
||||
import { Column, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 部门
|
||||
*/
|
||||
@EntityModel('base_sys_department')
|
||||
@Entity('base_sys_department')
|
||||
export class BaseSysDepartmentEntity extends BaseEntity {
|
||||
@Column({ comment: '部门名称' })
|
||||
name: string;
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column, Index } from 'typeorm';
|
||||
import { Column, Index, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 系统日志
|
||||
*/
|
||||
@EntityModel('base_sys_log')
|
||||
@Entity('base_sys_log')
|
||||
export class BaseSysLogEntity extends BaseEntity {
|
||||
@Index()
|
||||
@Column({ comment: '用户ID', nullable: true, type: 'bigint' })
|
||||
@ -16,13 +15,13 @@ export class BaseSysLogEntity extends BaseEntity {
|
||||
action: string;
|
||||
|
||||
@Index()
|
||||
@Column({ comment: 'ip', nullable: true, length: 50 })
|
||||
@Column({ comment: 'ip', nullable: true })
|
||||
ip: string;
|
||||
|
||||
@Index()
|
||||
@Column({ comment: 'ip地址', nullable: true, length: 50 })
|
||||
ipAddr: string;
|
||||
|
||||
@Column({ comment: '参数', nullable: true, type: 'text' })
|
||||
@Column({ comment: '参数', nullable: true, type: 'json' })
|
||||
params: string;
|
||||
}
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column } from 'typeorm';
|
||||
import { Column, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 菜单
|
||||
*/
|
||||
@EntityModel('base_sys_menu')
|
||||
@Entity('base_sys_menu')
|
||||
export class BaseSysMenuEntity extends BaseEntity {
|
||||
@Column({ comment: '父菜单ID', type: 'bigint', nullable: true })
|
||||
parentId: number;
|
||||
@ -20,7 +19,7 @@ export class BaseSysMenuEntity extends BaseEntity {
|
||||
perms: string;
|
||||
|
||||
@Column({
|
||||
comment: '类型 0:目录 1:菜单 2:按钮',
|
||||
comment: '类型 0-目录 1-菜单 2-按钮',
|
||||
default: 0,
|
||||
type: 'tinyint',
|
||||
})
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column, Index } from 'typeorm';
|
||||
import { Column, Index, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 参数配置
|
||||
*/
|
||||
@EntityModel('base_sys_param')
|
||||
@Entity('base_sys_param')
|
||||
export class BaseSysParamEntity extends BaseEntity {
|
||||
@Index()
|
||||
@Column({ comment: '键位' })
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column, Index } from 'typeorm';
|
||||
import { Column, Index, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
@EntityModel('base_sys_role')
|
||||
@Entity('base_sys_role')
|
||||
export class BaseSysRoleEntity extends BaseEntity {
|
||||
@Column({ comment: '用户ID' })
|
||||
userId: string;
|
||||
@ -23,4 +22,10 @@ export class BaseSysRoleEntity extends BaseEntity {
|
||||
|
||||
@Column({ comment: '数据权限是否关联上下级', default: 1 })
|
||||
relevance: number;
|
||||
|
||||
@Column({ comment: '菜单权限', type: 'json' })
|
||||
menuIdList: number[];
|
||||
|
||||
@Column({ comment: '部门权限', type: 'json' })
|
||||
departmentIdList: number[];
|
||||
}
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column } from 'typeorm';
|
||||
import { Column, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 角色部门
|
||||
*/
|
||||
@EntityModel('base_sys_role_department')
|
||||
@Entity('base_sys_role_department')
|
||||
export class BaseSysRoleDepartmentEntity extends BaseEntity {
|
||||
@Column({ comment: '角色ID', type: 'bigint' })
|
||||
roleId: number;
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column } from 'typeorm';
|
||||
import { Column, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 角色菜单
|
||||
*/
|
||||
@EntityModel('base_sys_role_menu')
|
||||
@Entity('base_sys_role_menu')
|
||||
export class BaseSysRoleMenuEntity extends BaseEntity {
|
||||
@Column({ comment: '角色ID', type: 'bigint' })
|
||||
roleId: number;
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column, Index } from 'typeorm';
|
||||
import { Column, Index, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
@EntityModel('base_sys_user')
|
||||
@Entity('base_sys_user')
|
||||
export class BaseSysUserEntity extends BaseEntity {
|
||||
@Index()
|
||||
@Column({ comment: '部门ID', type: 'bigint', nullable: true })
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column } from 'typeorm';
|
||||
import { Column, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 用户角色
|
||||
*/
|
||||
@EntityModel('base_sys_user_role')
|
||||
@Entity('base_sys_user_role')
|
||||
export class BaseSysUserRoleEntity extends BaseEntity {
|
||||
@Column({ comment: '用户ID', type: 'bigint' })
|
||||
userId: number;
|
||||
|
||||
@ -17,6 +17,45 @@
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for base_app_space_info
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `base_app_space_info`;
|
||||
CREATE TABLE `base_app_space_info` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`createTime` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
|
||||
`updateTime` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
|
||||
`url` varchar(255) NOT NULL COMMENT '地址',
|
||||
`type` varchar(255) NOT NULL COMMENT '类型',
|
||||
`classifyId` bigint(20) DEFAULT NULL COMMENT '分类ID',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `IDX_4aed04cbfa2ecdc01485b86e51` (`createTime`),
|
||||
KEY `IDX_abd5de4a4895eb253a5cabb20f` (`updateTime`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for base_app_space_type
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `base_app_space_type`;
|
||||
CREATE TABLE `base_app_space_type` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`createTime` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
|
||||
`updateTime` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
|
||||
`name` varchar(255) NOT NULL COMMENT '类别名称',
|
||||
`parentId` tinyint(4) DEFAULT NULL COMMENT '父分类ID',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `IDX_5e8376603f89fdf3e7bb05103a` (`createTime`),
|
||||
KEY `IDX_500ea9e8b2c5c08c9b86a0667e` (`updateTime`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of base_app_space_type
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `base_app_space_type` VALUES (1, '2021-02-26 14:07:48.867045', '2021-02-26 14:07:48.867045', 'a', NULL);
|
||||
INSERT INTO `base_app_space_type` VALUES (2, '2021-02-26 14:07:52.285531', '2021-02-26 14:07:52.285531', 'b', NULL);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for base_sys_conf
|
||||
-- ----------------------------
|
||||
@ -133,7 +172,7 @@ INSERT INTO `base_sys_menu` VALUES (30, '2019-09-12 17:37:03.000000', '2021-03-0
|
||||
INSERT INTO `base_sys_menu` VALUES (43, '2019-11-07 14:22:34.000000', '2021-03-08 23:02:51.000000', 45, 'crud 示例', '/crud', NULL, 1, 'icon-favor', 1, 'cool/modules/demo/views/crud.vue', 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (45, '2019-11-07 22:36:57.000000', '2019-11-11 15:21:10.000000', 1, '组件库', '/ui-lib', NULL, 0, 'icon-common', 2, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (47, '2019-11-08 09:35:08.000000', '2021-02-27 17:16:35.000000', NULL, '框架教程', '/tutorial', NULL, 0, 'icon-task', 4, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (48, '2019-11-08 09:35:53.000000', '2021-03-03 11:03:21.000000', 47, '文档', '/tutorial/doc', NULL, 1, 'icon-log', 0, 'https://cool-js.com', 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (48, '2019-11-08 09:35:53.000000', '2021-03-03 11:03:21.000000', 47, '文档', '/tutorial/doc', NULL, 1, 'icon-log', 0, 'https://admin.cool-js.com', 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (49, '2019-11-09 22:11:13.000000', '2021-03-09 09:50:46.000000', 45, 'quill 富文本编辑器', '/editor-quill', NULL, 1, 'icon-favor', 2, 'cool/modules/demo/views/editor-quill.vue', 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (59, '2019-11-18 16:50:27.000000', '2019-11-18 16:50:27.000000', 97, '部门列表', NULL, 'base:sys:department:list', 2, NULL, 0, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (60, '2019-11-18 16:50:45.000000', '2019-11-18 16:50:45.000000', 97, '新增部门', NULL, 'base:sys:department:add', 2, NULL, 0, NULL, 1, 1);
|
||||
@ -158,6 +197,14 @@ INSERT INTO `base_sys_menu` VALUES (99, '1900-01-20 14:14:22.823000', '1900-01-2
|
||||
INSERT INTO `base_sys_menu` VALUES (100, '1900-01-20 14:14:33.973000', '1900-01-20 14:14:33.973000', 97, '修改', NULL, 'base:sys:user:delete,base:sys:user:update', 2, NULL, 0, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (101, '2021-01-12 14:14:51.000000', '2021-01-12 14:14:51.000000', 97, '查询', NULL, 'base:sys:user:page,base:sys:user:list,base:sys:user:info', 2, NULL, 0, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (105, '2021-01-21 10:42:55.000000', '2021-01-21 10:42:55.000000', 2, '监控管理', NULL, NULL, 0, 'icon-rank', 6, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (109, '2021-02-27 14:13:56.000000', '2021-02-27 17:09:19.000000', NULL, '插件管理', NULL, NULL, 0, 'icon-menu', 3, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (110, '2021-02-27 14:14:13.000000', '2021-03-08 23:01:30.000000', 109, '插件列表', '/plugin', NULL, 1, 'icon-menu', 0, 'cool/modules/base/views/plugin.vue', 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (111, '2021-02-27 14:24:41.877000', '2021-02-27 14:24:41.877000', 110, '编辑', NULL, 'base:plugin:info:info,base:plugin:info:update', 2, NULL, 0, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (112, '2021-02-27 14:24:52.159000', '2021-02-27 14:24:52.159000', 110, '列表', NULL, 'base:plugin:info:list', 2, NULL, 0, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (113, '2021-02-27 14:25:02.066000', '2021-02-27 14:25:02.066000', 110, '删除', NULL, 'base:plugin:info:delete', 2, NULL, 0, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (114, '2021-02-27 16:36:59.322000', '2021-02-27 16:36:59.322000', 110, '保存配置', NULL, 'base:plugin:info:config', 2, NULL, 0, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (115, '2021-02-27 16:38:21.000000', '2021-02-27 18:18:22.000000', 110, '获取配置', NULL, 'base:plugin:info:getConfig', 2, NULL, 0, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (116, '2021-02-27 17:57:42.000000', '2021-02-27 18:19:35.000000', 110, '开启、关闭', NULL, 'base:plugin:info:enable', 2, NULL, 0, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (117, '2021-03-05 10:58:25.000000', '2021-03-05 10:58:25.000000', NULL, '任务管理', NULL, NULL, 0, 'icon-activity', 5, NULL, 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (118, '2021-03-05 10:59:42.000000', '2021-03-05 10:59:42.000000', 117, '任务列表', '/task', NULL, 1, 'icon-menu', 0, 'cool/modules/task/views/task.vue', 1, 1);
|
||||
INSERT INTO `base_sys_menu` VALUES (119, '2021-03-05 11:00:00.000000', '2021-03-05 11:00:00.000000', 118, '权限', NULL, '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', 2, NULL, 0, NULL, 1, 1);
|
||||
|
||||
@ -16,7 +16,7 @@ export class BaseLogMiddleware implements IMiddleware<Context, NextFunction> {
|
||||
);
|
||||
baseSysLogService.record(
|
||||
ctx,
|
||||
ctx.url.split('?')[0],
|
||||
ctx.url,
|
||||
ctx.req.method === 'GET' ? ctx.request.query : ctx.request.body,
|
||||
ctx.admin ? ctx.admin.userId : null
|
||||
);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/orm';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseSysConfEntity } from '../../entity/sys/conf';
|
||||
|
||||
@ -17,7 +17,7 @@ export class BaseSysConfService extends BaseService {
|
||||
* @param key
|
||||
*/
|
||||
async getValue(key) {
|
||||
const conf = await this.baseSysConfEntity.findOne({ cKey: key });
|
||||
const conf = await this.baseSysConfEntity.findOneBy({ cKey: key });
|
||||
if (conf) {
|
||||
return conf.cValue;
|
||||
}
|
||||
|
||||
10
src/modules/base/service/sys/data.ts
Normal file
10
src/modules/base/service/sys/data.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
export class TempDataSource extends DataSource {
|
||||
/**
|
||||
* 重新构造元数据
|
||||
*/
|
||||
async buildMetadatas() {
|
||||
await super.buildMetadatas();
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/orm';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseSysDepartmentEntity } from '../../entity/sys/department';
|
||||
import * as _ from 'lodash';
|
||||
@ -101,7 +101,7 @@ export class BaseSysDepartmentService extends BaseService {
|
||||
*/
|
||||
async delete(ids: number[]) {
|
||||
const { deleteUser } = this.ctx.request.body;
|
||||
await this.baseSysDepartmentEntity.delete(ids);
|
||||
await super.delete(ids);
|
||||
if (deleteUser) {
|
||||
await this.nativeQuery(
|
||||
'delete from base_sys_user where departmentId in (?)',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/orm';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import * as _ from 'lodash';
|
||||
import { BaseSysLogEntity } from '../../entity/sys/log';
|
||||
@ -41,10 +41,8 @@ export class BaseSysLogService extends BaseService {
|
||||
for (const e of sysLog.ip.split(','))
|
||||
ipAddrArr.push(await await this.utils.getIpAddr(context, e));
|
||||
sysLog.ipAddr = ipAddrArr.join(',');
|
||||
sysLog.action = url;
|
||||
if (!_.isEmpty(params)) {
|
||||
sysLog.params = JSON.stringify(params);
|
||||
}
|
||||
sysLog.action = url.split('?')[0];
|
||||
sysLog.params = params;
|
||||
await this.baseSysLogEntity.insert(sysLog);
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ 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/orm';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import * as md5 from 'md5';
|
||||
import { BaseSysRoleService } from './role';
|
||||
import * as _ from 'lodash';
|
||||
@ -51,7 +51,7 @@ export class BaseSysLoginService extends BaseService {
|
||||
// 校验验证码
|
||||
const checkV = await this.captchaCheck(captchaId, verifyCode);
|
||||
if (checkV) {
|
||||
const user = await this.baseSysUserEntity.findOne({ username });
|
||||
const user = await this.baseSysUserEntity.findOneBy({ username });
|
||||
// 校验用户
|
||||
if (user) {
|
||||
// 校验用户状态及密码
|
||||
|
||||
@ -1,11 +1,17 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/orm';
|
||||
import { App, IMidwayApplication } from '@midwayjs/core';
|
||||
import { ALL, Config, Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService, CoolCommException } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { 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';
|
||||
|
||||
/**
|
||||
* 菜单
|
||||
@ -21,6 +27,12 @@ export class BaseSysMenuService extends BaseService {
|
||||
@Inject()
|
||||
baseSysPermsService: BaseSysPermsService;
|
||||
|
||||
@Config(ALL)
|
||||
config;
|
||||
|
||||
@App()
|
||||
app: IMidwayApplication;
|
||||
|
||||
/**
|
||||
* 获得所有菜单
|
||||
*/
|
||||
@ -131,7 +143,7 @@ export class BaseSysMenuService extends BaseService {
|
||||
*/
|
||||
private async delChildMenu(id) {
|
||||
await this.refreshPerms(id);
|
||||
const delMenu = await this.baseSysMenuEntity.find({ parentId: id });
|
||||
const delMenu = await this.baseSysMenuEntity.findBy({ parentId: id });
|
||||
if (_.isEmpty(delMenu)) {
|
||||
return;
|
||||
}
|
||||
@ -162,4 +174,139 @@ export class BaseSysMenuService extends BaseService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析实体和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 } = 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,
|
||||
}
|
||||
);
|
||||
eval(code);
|
||||
await tempDataSource.buildMetadatas();
|
||||
const columns = tempDataSource.getMetadata(className).columns;
|
||||
await tempDataSource.destroy();
|
||||
const fileName = await this.fileName(controller);
|
||||
return {
|
||||
columns: columns.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,
|
||||
};
|
||||
}),
|
||||
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}`,
|
||||
};
|
||||
} catch (err) {
|
||||
throw new CoolCommException('代码结构不正确,请检查');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建代码
|
||||
* @param body body
|
||||
*/
|
||||
async create(body) {
|
||||
const { module, entity, controller } = body;
|
||||
const basePath = this.app.getBaseDir();
|
||||
const fileName = await this.fileName(controller);
|
||||
// 生成Entity
|
||||
const entityPath = pathUtil.join(
|
||||
basePath,
|
||||
'modules',
|
||||
module,
|
||||
'entity',
|
||||
`${fileName}.ts`
|
||||
);
|
||||
this.createFile(entityPath, entity);
|
||||
// // 生成Controller
|
||||
const controllerPath = pathUtil.join(
|
||||
basePath,
|
||||
'modules',
|
||||
module,
|
||||
'controller',
|
||||
'admin',
|
||||
`${fileName}.ts`
|
||||
);
|
||||
this.createFile(controllerPath, controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* 找到文件名
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/orm';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseSysParamEntity } from '../../entity/sys/param';
|
||||
import { CacheManager } from '@midwayjs/cache';
|
||||
@ -23,7 +23,7 @@ export class BaseSysParamService extends BaseService {
|
||||
async dataByKey(key) {
|
||||
let result: any = await this.cacheManager.get(`param:${key}`);
|
||||
if (!result) {
|
||||
result = await this.baseSysParamEntity.findOne({ keyName: key });
|
||||
result = await this.baseSysParamEntity.findOneBy({ keyName: key });
|
||||
}
|
||||
if (result) {
|
||||
if (typeof result == 'string') {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/orm';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseSysRoleEntity } from '../../entity/sys/role';
|
||||
import { BaseSysUserRoleEntity } from '../../entity/sys/user_role';
|
||||
@ -38,7 +38,7 @@ export class BaseSysRoleService extends BaseService {
|
||||
* @param userId
|
||||
*/
|
||||
async getByUser(userId: number): Promise<number[]> {
|
||||
const userRole = await this.baseSysUserRoleEntity.find({ userId });
|
||||
const userRole = await this.baseSysUserRoleEntity.findBy({ userId });
|
||||
if (!_.isEmpty(userRole)) {
|
||||
return userRole.map(e => {
|
||||
return e.roleId;
|
||||
@ -75,7 +75,7 @@ export class BaseSysRoleService extends BaseService {
|
||||
await this.baseSysRoleDepartmentEntity.save({ roleId, departmentId });
|
||||
}
|
||||
// 刷新权限
|
||||
const userRoles = await this.baseSysUserRoleEntity.find({ roleId });
|
||||
const userRoles = await this.baseSysUserRoleEntity.findBy({ roleId });
|
||||
for (const userRole of userRoles) {
|
||||
await this.baseSysPermsService.refreshPerms(userRole.userId);
|
||||
}
|
||||
@ -86,15 +86,15 @@ export class BaseSysRoleService extends BaseService {
|
||||
* @param id
|
||||
*/
|
||||
async info(id) {
|
||||
const info = await this.baseSysRoleEntity.findOne({ id });
|
||||
const info = await this.baseSysRoleEntity.findOneBy({ id });
|
||||
if (info) {
|
||||
const menus = await this.baseSysRoleMenuEntity.find(
|
||||
const menus = await this.baseSysRoleMenuEntity.findBy(
|
||||
id !== 1 ? { roleId: id } : {}
|
||||
);
|
||||
const menuIdList = menus.map(e => {
|
||||
return parseInt(e.menuId + '');
|
||||
});
|
||||
const departments = await this.baseSysRoleDepartmentEntity.find(
|
||||
const departments = await this.baseSysRoleDepartmentEntity.findBy(
|
||||
id !== 1 ? { roleId: id } : {}
|
||||
);
|
||||
const departmentIdList = departments.map(e => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService, CoolCommException } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/orm';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseSysUserEntity } from '../../entity/sys/user';
|
||||
import { BaseSysPermsService } from './perms';
|
||||
@ -92,7 +92,7 @@ export class BaseSysUserService extends BaseService {
|
||||
* 获得个人信息
|
||||
*/
|
||||
async person() {
|
||||
const info = await this.baseSysUserEntity.findOne({
|
||||
const info = await this.baseSysUserEntity.findOneBy({
|
||||
id: this.ctx.admin?.userId,
|
||||
});
|
||||
delete info?.password;
|
||||
@ -124,7 +124,7 @@ export class BaseSysUserService extends BaseService {
|
||||
* @param param
|
||||
*/
|
||||
async add(param) {
|
||||
const exists = await this.baseSysUserEntity.findOne({
|
||||
const exists = await this.baseSysUserEntity.findOneBy({
|
||||
username: param.username,
|
||||
});
|
||||
if (!_.isEmpty(exists)) {
|
||||
@ -141,12 +141,12 @@ export class BaseSysUserService extends BaseService {
|
||||
* @param id
|
||||
*/
|
||||
public async info(id) {
|
||||
const info = await this.baseSysUserEntity.findOne({ 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.findOne({
|
||||
const department = await this.baseSysDepartmentEntity.findOneBy({
|
||||
id: info.departmentId,
|
||||
});
|
||||
if (info) {
|
||||
@ -172,7 +172,7 @@ export class BaseSysUserService extends BaseService {
|
||||
param.id = this.ctx.admin.userId;
|
||||
if (!_.isEmpty(param.password)) {
|
||||
param.password = md5(param.password);
|
||||
const userInfo = await this.baseSysUserEntity.findOne({ id: param.id });
|
||||
const userInfo = await this.baseSysUserEntity.findOneBy({ id: param.id });
|
||||
if (!userInfo) {
|
||||
throw new CoolCommException('用户不存在');
|
||||
}
|
||||
@ -197,7 +197,7 @@ export class BaseSysUserService extends BaseService {
|
||||
}
|
||||
if (!_.isEmpty(param.password)) {
|
||||
param.password = md5(param.password);
|
||||
const userInfo = await this.baseSysUserEntity.findOne({ id: param.id });
|
||||
const userInfo = await this.baseSysUserEntity.findOneBy({ id: param.id });
|
||||
if (!userInfo) {
|
||||
throw new CoolCommException('用户不存在');
|
||||
}
|
||||
|
||||
19
src/modules/cloud/config.ts
Normal file
19
src/modules/cloud/config.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { ModuleConfig } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 模块配置
|
||||
*/
|
||||
export default () => {
|
||||
return {
|
||||
// 模块名称
|
||||
name: '云服务',
|
||||
// 模块描述
|
||||
description: '云函数、云数据库、云存储等',
|
||||
// 中间件,只对本模块有效
|
||||
middlewares: [],
|
||||
// 中间件,全局有效
|
||||
globalMiddlewares: [],
|
||||
// 模块加载顺序,默认为0,值越大越优先加载
|
||||
order: 0,
|
||||
} as ModuleConfig;
|
||||
};
|
||||
34
src/modules/cloud/controller/admin/db.ts
Normal file
34
src/modules/cloud/controller/admin/db.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { CloudDBService } from './../../service/db';
|
||||
import { CloudDBEntity } from './../../entity/db';
|
||||
import { Body, Inject, Post, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 云数据库
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||
entity: CloudDBEntity,
|
||||
service: CloudDBService,
|
||||
pageQueryOp: {
|
||||
fieldEq: ['status'],
|
||||
keyWordLikeFields: ['name'],
|
||||
},
|
||||
})
|
||||
export class CloudDBController extends BaseController {
|
||||
@Inject()
|
||||
cloudDBService: CloudDBService;
|
||||
|
||||
@Post('/initEntity', { summary: '初始化Entity' })
|
||||
async initEntity() {
|
||||
await this.cloudDBService.initEntity();
|
||||
return this.ok();
|
||||
}
|
||||
|
||||
@Post('/data', { summary: '数据操作' })
|
||||
async data(@Body() body) {
|
||||
const { id, method, params } = body;
|
||||
return this.ok(await this.cloudDBService.data(id, method, params));
|
||||
}
|
||||
}
|
||||
31
src/modules/cloud/controller/admin/func/info.ts
Normal file
31
src/modules/cloud/controller/admin/func/info.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { CloudFuncService } from './../../../service/func';
|
||||
import { CloudFuncInfoEntity } from '../../../entity/func/info';
|
||||
import { Body, Inject, Post, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { CloudReq } from '@cool-midway/cloud';
|
||||
|
||||
/**
|
||||
* 云函数
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||
entity: CloudFuncInfoEntity,
|
||||
pageQueryOp: {
|
||||
keyWordLikeFields: ['name'],
|
||||
fieldEq: ['status'],
|
||||
},
|
||||
})
|
||||
export class AdminCloudFuncInfoController extends BaseController {
|
||||
@Inject()
|
||||
cloudFuncService: CloudFuncService;
|
||||
|
||||
@Post('/invoke', { summary: '调用云函数' })
|
||||
async invoke(
|
||||
@Body() req: CloudReq,
|
||||
@Body('id') id: number,
|
||||
@Body('content') content: string
|
||||
) {
|
||||
return this.ok(await this.cloudFuncService.invoke(req, id, content));
|
||||
}
|
||||
}
|
||||
16
src/modules/cloud/controller/admin/func/log.ts
Normal file
16
src/modules/cloud/controller/admin/func/log.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { CloudFuncLogEntity } from './../../../entity/func/log';
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 日志
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||
entity: CloudFuncLogEntity,
|
||||
pageQueryOp: {
|
||||
fieldEq: ['infoId'],
|
||||
},
|
||||
})
|
||||
export class AdminCloudFuncLogController extends BaseController {}
|
||||
12
src/modules/cloud/controller/app/func.ts
Normal file
12
src/modules/cloud/controller/app/func.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Body, Post, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 云函数
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController()
|
||||
export class AppCloudFuncController extends BaseController {
|
||||
@Post('/invoke', { summary: '调用云函数' })
|
||||
async invoke(@Body() body) {}
|
||||
}
|
||||
28
src/modules/cloud/entity/db.ts
Normal file
28
src/modules/cloud/entity/db.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column, Entity, Index } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 云数据库
|
||||
*/
|
||||
@Entity('cloud_db')
|
||||
export class CloudDBEntity extends BaseEntity {
|
||||
@Column({ comment: '名称' })
|
||||
name: string;
|
||||
|
||||
@Column({ comment: '说明', nullable: true })
|
||||
readme: string;
|
||||
|
||||
@Column({ comment: '内容', type: 'text' })
|
||||
content: string;
|
||||
|
||||
@Index({ unique: true })
|
||||
@Column({ comment: '类名', nullable: true })
|
||||
className: string;
|
||||
|
||||
@Index({ unique: true })
|
||||
@Column({ comment: '表名', nullable: true })
|
||||
tableName: string;
|
||||
|
||||
@Column({ comment: '状态 0-禁用 1-启用', default: 1 })
|
||||
status: number;
|
||||
}
|
||||
20
src/modules/cloud/entity/func/info.ts
Normal file
20
src/modules/cloud/entity/func/info.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 云函数
|
||||
*/
|
||||
@Entity('cloud_func_info')
|
||||
export class CloudFuncInfoEntity extends BaseEntity {
|
||||
@Column({ comment: '名称' })
|
||||
name: string;
|
||||
|
||||
@Column({ comment: '说明', nullable: true })
|
||||
readme: string;
|
||||
|
||||
@Column({ comment: '内容', type: 'text' })
|
||||
content: string;
|
||||
|
||||
@Column({ comment: '状态 0-禁用 1-启用', default: 1 })
|
||||
status: number;
|
||||
}
|
||||
28
src/modules/cloud/entity/func/log.ts
Normal file
28
src/modules/cloud/entity/func/log.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { CloudReq } from '@cool-midway/cloud';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column, Entity, Index } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 云函数日志
|
||||
*/
|
||||
@Entity('cloud_func_log')
|
||||
export class CloudFuncLogEntity extends BaseEntity {
|
||||
@Index()
|
||||
@Column({ comment: '云函数ID' })
|
||||
infoId: number;
|
||||
|
||||
@Column({ comment: '请求', type: 'json', nullable: true })
|
||||
request: CloudReq;
|
||||
|
||||
@Column({ comment: '结果', type: 'json', nullable: true })
|
||||
result: string;
|
||||
|
||||
@Column({ comment: '类型 0-失败 1-成功', default: 1, type: 'tinyint' })
|
||||
type: number;
|
||||
|
||||
@Column({ comment: '异常信息', nullable: true, type: 'text' })
|
||||
error: string;
|
||||
|
||||
@Column({ comment: '耗时(毫秒)', default: 0 })
|
||||
time: number;
|
||||
}
|
||||
21
src/modules/cloud/event/app.ts
Normal file
21
src/modules/cloud/event/app.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { IMidwayApplication } from '@midwayjs/core';
|
||||
import { CoolEvent, Event } from '@cool-midway/core';
|
||||
import { App } from '@midwayjs/decorator';
|
||||
import { CloudDBService } from '../service/db';
|
||||
|
||||
/**
|
||||
* 应用事件
|
||||
*/
|
||||
@CoolEvent()
|
||||
export class AppEvent {
|
||||
@App()
|
||||
app: IMidwayApplication;
|
||||
|
||||
@Event('onServerReady')
|
||||
async onServerReady() {
|
||||
const cloudDBService = await this.app
|
||||
.getApplicationContext()
|
||||
.getAsync(CloudDBService);
|
||||
cloudDBService.initEntity();
|
||||
}
|
||||
}
|
||||
151
src/modules/cloud/service/db.ts
Normal file
151
src/modules/cloud/service/db.ts
Normal file
@ -0,0 +1,151 @@
|
||||
import { Config, Singleton } from '@midwayjs/core';
|
||||
import { CloudDBEntity } from './../entity/db';
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService, CoolCommException, CoolConfig } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { CoolCloudDb } from '@cool-midway/cloud';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
/**
|
||||
* 云数据库
|
||||
*/
|
||||
@Provide()
|
||||
@Singleton()
|
||||
export class CloudDBService extends BaseService {
|
||||
@InjectEntityModel(CloudDBEntity)
|
||||
cloudDBEntity: Repository<CloudDBEntity>;
|
||||
|
||||
@Inject()
|
||||
coolCloudDb: CoolCloudDb;
|
||||
|
||||
@Config('cool')
|
||||
coolConfig: CoolConfig;
|
||||
|
||||
/**
|
||||
* 数据
|
||||
* @param id
|
||||
* @param method
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
async data(id, method, params: any = {}) {
|
||||
const db = await this.cloudDBEntity.findOneBy({ id });
|
||||
const repository = await this.getRepository(db?.className);
|
||||
if (method == 'add' || method == 'update') {
|
||||
await repository.save(params);
|
||||
return {
|
||||
id: params.id,
|
||||
};
|
||||
}
|
||||
if (method == 'delete') {
|
||||
await repository.delete(params.ids);
|
||||
}
|
||||
if (method == 'clear') {
|
||||
await repository.clear();
|
||||
}
|
||||
if (method == 'page') {
|
||||
const { page = 1, size = this.coolConfig.crud.pageSize } = params;
|
||||
const find = repository
|
||||
.createQueryBuilder()
|
||||
.offset((page - 1) * size)
|
||||
.limit(size)
|
||||
.orderBy('createTime', 'DESC');
|
||||
return {
|
||||
list: await find.getMany(),
|
||||
pagination: {
|
||||
page: parseInt(page),
|
||||
size: parseInt(size),
|
||||
total: await find.getCount(),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得数据操作实例
|
||||
* @param className
|
||||
*/
|
||||
async getRepository(className: string): Promise<Repository<any>> {
|
||||
const info = await this.cloudDBEntity.findOneBy({
|
||||
className,
|
||||
});
|
||||
if (!info) {
|
||||
throw new CoolCommException('云数据表不存在');
|
||||
}
|
||||
return await this.coolCloudDb.getRepository(info.className);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增
|
||||
* @param param
|
||||
* @returns
|
||||
*/
|
||||
async addOrUpdate(param) {
|
||||
const { tableName, className } = this.coolCloudDb.parseCode(param.content);
|
||||
// 更新
|
||||
if (param.id) {
|
||||
const old = await this.cloudDBEntity.findOneBy({ id: param.id });
|
||||
if (tableName != old.tableName) {
|
||||
const check = await this.cloudDBEntity.findOneBy({ tableName });
|
||||
if (check) {
|
||||
throw new CoolCommException('已存在相同的表名');
|
||||
}
|
||||
}
|
||||
if (className != old.className) {
|
||||
const checkClass = await this.cloudDBEntity.findOneBy({ className });
|
||||
if (checkClass) {
|
||||
throw new CoolCommException('已存在相同的类名');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const check = await this.cloudDBEntity.findOneBy({ tableName });
|
||||
if (check) {
|
||||
throw new CoolCommException('已存在相同的表名');
|
||||
}
|
||||
const checkClass = await this.cloudDBEntity.findOneBy({ className });
|
||||
if (checkClass) {
|
||||
throw new CoolCommException('已存在相同的类名');
|
||||
}
|
||||
}
|
||||
await super.addOrUpdate({
|
||||
...param,
|
||||
tableName,
|
||||
className: className.replace('CLOUD', ''),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
async initEntity() {
|
||||
const tables = await this.cloudDBEntity.findBy({ status: 1 });
|
||||
const tableNames = [];
|
||||
for (const table of tables) {
|
||||
const parseData = this.coolCloudDb.parseCode(table.content);
|
||||
tableNames.push(parseData.tableName);
|
||||
await this.coolCloudDb.createTable(table.content, true);
|
||||
}
|
||||
// 所有云函数表
|
||||
const allTables = (
|
||||
await this.coolCloudDb.coolDataSource.query(
|
||||
"SELECT table_name from information_schema.columns where table_name like 'func_%' group by table_name"
|
||||
)
|
||||
).map(e => {
|
||||
return e.TABLE_NAME;
|
||||
});
|
||||
// 需要删除的云函数表
|
||||
const deleteTables = allTables.filter(e => {
|
||||
return !tableNames.includes(e);
|
||||
});
|
||||
if (!_.isEmpty(deleteTables)) {
|
||||
await this.coolCloudDb.coolDataSource.query(
|
||||
`drop table ${deleteTables.join(',')}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async modifyAfter() {
|
||||
await this.initEntity();
|
||||
}
|
||||
}
|
||||
130
src/modules/cloud/service/func.ts
Normal file
130
src/modules/cloud/service/func.ts
Normal file
@ -0,0 +1,130 @@
|
||||
import { CloudFuncLogEntity } from './../entity/func/log';
|
||||
import { Config, IMidwayApplication } from '@midwayjs/core';
|
||||
import { CloudFuncInfoEntity } from './../entity/func/info';
|
||||
import { App, Provide, Inject } from '@midwayjs/decorator';
|
||||
import { BaseService, CoolConfig, CoolCommException } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import * as moment from 'moment';
|
||||
|
||||
// eslint-disable-next-line node/no-unpublished-import
|
||||
import * as ts from 'typescript';
|
||||
import { Context } from '@midwayjs/koa';
|
||||
import {
|
||||
CloudCrud,
|
||||
CloudReq,
|
||||
CoolCloudDb,
|
||||
CoolCloudFunc,
|
||||
} from '@cool-midway/cloud';
|
||||
|
||||
/**
|
||||
* 云函数
|
||||
*/
|
||||
@Provide()
|
||||
export class CloudFuncService extends BaseService {
|
||||
@InjectEntityModel(CloudFuncInfoEntity)
|
||||
cloudFuncInfoEntity: Repository<CloudFuncInfoEntity>;
|
||||
|
||||
@InjectEntityModel(CloudFuncLogEntity)
|
||||
cloudFuncLogEntity: Repository<CloudFuncLogEntity>;
|
||||
|
||||
@App()
|
||||
app: IMidwayApplication;
|
||||
|
||||
@Inject()
|
||||
ctx: Context;
|
||||
|
||||
@Inject()
|
||||
coolCloudDb: CoolCloudDb;
|
||||
|
||||
@Inject()
|
||||
coolCloudFunc: CoolCloudFunc;
|
||||
|
||||
@Config('cool')
|
||||
coolConfig: CoolConfig;
|
||||
|
||||
/**
|
||||
* 调用云函数
|
||||
* @param req
|
||||
* @param id
|
||||
* @param content 内容 调试的时候传过来
|
||||
* @returns
|
||||
*/
|
||||
async invoke(req: CloudReq, id: number, content?: string) {
|
||||
const start = moment().valueOf();
|
||||
let funcInfo: CloudFuncInfoEntity;
|
||||
if (id) {
|
||||
funcInfo = await this.cloudFuncInfoEntity
|
||||
.createQueryBuilder()
|
||||
.cache(true)
|
||||
.where({ id, status: 1 })
|
||||
.getOne();
|
||||
req.name = funcInfo?.name;
|
||||
} else {
|
||||
funcInfo = await this.cloudFuncInfoEntity
|
||||
.createQueryBuilder()
|
||||
.cache(true)
|
||||
.where({ name: req.name, status: 1 })
|
||||
.getOne();
|
||||
}
|
||||
if (!funcInfo) {
|
||||
throw new CoolCommException('云函数不存在或被禁用');
|
||||
}
|
||||
if (!req.method) {
|
||||
throw new CoolCommException('调用方法不能为空');
|
||||
}
|
||||
let result;
|
||||
let func: CloudCrud;
|
||||
const code = content ? content : funcInfo.content;
|
||||
const className = this.coolCloudFunc.getClassName(code);
|
||||
const newCode = ts.transpile(
|
||||
`${code}
|
||||
func = new ${className}();
|
||||
`,
|
||||
{
|
||||
emitDecoratorMetadata: true,
|
||||
module: ts.ModuleKind.CommonJS,
|
||||
target: ts.ScriptTarget.ES2018,
|
||||
removeComments: true,
|
||||
}
|
||||
);
|
||||
const log = new CloudFuncLogEntity();
|
||||
try {
|
||||
eval(newCode);
|
||||
|
||||
func.ctx = this.ctx;
|
||||
func.app = this.app;
|
||||
func.coolCloudDb = this.coolCloudDb;
|
||||
func.coolConfig = this.coolConfig;
|
||||
await func.init(req);
|
||||
const apis: string[] = func.curdOption.api || [];
|
||||
// 判断是否可以执行6个通用方法
|
||||
if (
|
||||
['add', 'delete', 'update', 'info', 'list', 'page'].includes(
|
||||
req.method
|
||||
) &&
|
||||
!apis.includes(req.method)
|
||||
) {
|
||||
throw new CoolCommException(
|
||||
`${req.method} 方法未在curdOption.api 中配置`
|
||||
);
|
||||
}
|
||||
// result = func.add({ name: 'aa', age: 22, test2: 1 });
|
||||
result = await func[req.method](req.params);
|
||||
} catch (error) {
|
||||
log.error = error.message;
|
||||
}
|
||||
log.infoId = funcInfo.id;
|
||||
log.request = req;
|
||||
log.result = result;
|
||||
log.type = log.error ? 0 : 1;
|
||||
const end = moment().valueOf();
|
||||
log.time = end - start;
|
||||
this.cloudFuncLogEntity.insert(log);
|
||||
if (id) {
|
||||
return log;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
import { ModuleConfig } from '@cool-midway/core';
|
||||
import { DemoMiddleware } from './middleware/demo';
|
||||
|
||||
/**
|
||||
* 模块配置
|
||||
@ -7,16 +6,14 @@ import { DemoMiddleware } from './middleware/demo';
|
||||
export default () => {
|
||||
return {
|
||||
// 模块名称
|
||||
name: 'xxx',
|
||||
name: 'demo模块',
|
||||
// 模块描述
|
||||
description: 'xxx',
|
||||
description: '演示用',
|
||||
// 中间件,只对本模块有效
|
||||
middlewares: [DemoMiddleware],
|
||||
middlewares: [],
|
||||
// 中间件,全局有效
|
||||
globalMiddlewares: [],
|
||||
// 模块加载顺序,默认为0,值越大越优先加载
|
||||
order: 0,
|
||||
// 其他配置
|
||||
a: 1,
|
||||
} as ModuleConfig;
|
||||
};
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { DemoGoodsEntity } from '../../entity/goods';
|
||||
import { BaseController, CoolController } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 测试
|
||||
* 商品模块-商品信息
|
||||
*/
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'info', 'page', 'list'],
|
||||
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||
entity: DemoGoodsEntity,
|
||||
})
|
||||
export class CoolGoodsController extends BaseController {}
|
||||
export class AdminDemoGoodsController extends BaseController {}
|
||||
|
||||
@ -24,7 +24,7 @@ export class AppDemoCacheController extends BaseController {
|
||||
await this.cacheManager.set('a', 1);
|
||||
// 缓存10秒
|
||||
await this.cacheManager.set('a', 1, {
|
||||
ttl: 10,
|
||||
ttl: 30,
|
||||
});
|
||||
return this.ok(await this.cacheManager.get('a'));
|
||||
}
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
import { Config, Get, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 配置
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController()
|
||||
export class DemoConfigController extends BaseController {
|
||||
//获得模块配置,格式: module.模块名,模块文件夹名称,如demo
|
||||
@Config('module.demo')
|
||||
demoConfig;
|
||||
|
||||
@Get('/get')
|
||||
async get() {
|
||||
return this.ok(this.demoConfig);
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
import { Inject, Post, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { TestEsIndex } from '../../es/test';
|
||||
import { CoolElasticSearch } from '@cool-midway/es';
|
||||
|
||||
/**
|
||||
* elasticsearch
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController()
|
||||
export class AppDemoEsController extends BaseController {
|
||||
@Inject()
|
||||
testEsIndex: TestEsIndex;
|
||||
|
||||
@Inject()
|
||||
es: CoolElasticSearch;
|
||||
|
||||
@Post('/test')
|
||||
async test() {
|
||||
// es 客户端实例
|
||||
this.es.client;
|
||||
// 新增与修改
|
||||
await this.testEsIndex.upsert({
|
||||
name: '你好啊你是谁',
|
||||
age: 18,
|
||||
});
|
||||
return this.ok(await this.testEsIndex.find());
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import { Inject, Post, Provide } from '@midwayjs/decorator';
|
||||
import { Inject, Post } from '@midwayjs/decorator';
|
||||
import {
|
||||
CoolController,
|
||||
BaseController,
|
||||
@ -8,7 +8,6 @@ import {
|
||||
/**
|
||||
* 事件
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController()
|
||||
export class AppDemoEventController extends BaseController {
|
||||
@Inject()
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
import { Get, Inject, Post, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { Context } from 'koa';
|
||||
import { CoolFile } from '@cool-midway/file';
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController()
|
||||
export class AppDemoFileController extends BaseController {
|
||||
@Inject()
|
||||
ctx: Context;
|
||||
|
||||
@Inject()
|
||||
file: CoolFile;
|
||||
|
||||
@Post('/upload', { summary: '文件上传' })
|
||||
async uplod() {
|
||||
return this.ok(await this.file.upload(this.ctx));
|
||||
}
|
||||
|
||||
@Get('/uploadMode', { summary: '获得上传模式' })
|
||||
async uploadMode() {
|
||||
return this.ok(await this.file.getMode());
|
||||
}
|
||||
|
||||
@Post('/downAndUpload', { summary: '下载并上传' })
|
||||
async downAndUpload() {
|
||||
return this.ok(
|
||||
await this.file.downAndUpload('https://cool-js.com/admin/show.png')
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,33 @@
|
||||
import { DemoGoodsEntity } from '../../entity/goods';
|
||||
import { BaseController, CoolController } from '@cool-midway/core';
|
||||
import { DemoGoodsService } from '../../service/goods';
|
||||
import { DemoGoodsEntity } from '../../entity/goods';
|
||||
import { Body, Inject, Post, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 测试
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'info', 'page', 'list'],
|
||||
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||
entity: DemoGoodsEntity,
|
||||
service: DemoGoodsService,
|
||||
})
|
||||
export class CoolGoodsController extends BaseController {}
|
||||
export class AppDemoGoodsController extends BaseController {
|
||||
@InjectEntityModel(DemoGoodsEntity)
|
||||
demoGoodsEntity: Repository<DemoGoodsEntity>;
|
||||
|
||||
@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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
import { ALL, App, Body, Inject, Post, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { CoolWxPay, CoolAliPay } from '@cool-midway/pay';
|
||||
import { parseString } from 'xml2js';
|
||||
import { Context } from '@midwayjs/koa';
|
||||
import { IMidwayApplication } from '@midwayjs/core';
|
||||
import { Body, Config, Inject, Post, Provide } from '@midwayjs/decorator';
|
||||
import {
|
||||
CoolController,
|
||||
BaseController,
|
||||
CoolWxPayConfig,
|
||||
CoolAliPayConfig,
|
||||
} from '@cool-midway/core';
|
||||
import { CoolAliPay, CoolWxPay } from '@cool-midway/pay';
|
||||
import AlipayFormData from 'alipay-sdk/lib/form';
|
||||
import { sign } from 'alipay-sdk/lib/util';
|
||||
|
||||
/**
|
||||
* 支付示例
|
||||
* 微信支付
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController()
|
||||
export class DemoPayController extends BaseController {
|
||||
export class AppDemoPayController extends BaseController {
|
||||
// 微信支付
|
||||
@Inject()
|
||||
wxPay: CoolWxPay;
|
||||
@ -20,10 +24,13 @@ export class DemoPayController extends BaseController {
|
||||
aliPay: CoolAliPay;
|
||||
|
||||
@Inject()
|
||||
ctx: Context;
|
||||
ctx;
|
||||
|
||||
@App()
|
||||
app: IMidwayApplication;
|
||||
@Config('cool.pay.wx')
|
||||
wxPayConfig: CoolWxPayConfig;
|
||||
|
||||
@Config('cool.pay.ali')
|
||||
aliPayConfig: CoolAliPayConfig;
|
||||
|
||||
/**
|
||||
* 微信扫码支付
|
||||
@ -31,78 +38,92 @@ export class DemoPayController extends BaseController {
|
||||
@Post('/wx')
|
||||
async wx() {
|
||||
const orderNum = await this.wxPay.createOrderNum();
|
||||
const data = await this.wxPay.getInstance().unifiedOrder({
|
||||
const params = {
|
||||
description: '测试',
|
||||
out_trade_no: orderNum,
|
||||
body: '测试微信支付',
|
||||
total_fee: 1,
|
||||
trade_type: 'NATIVE',
|
||||
product_id: 'test001',
|
||||
});
|
||||
return this.ok(data);
|
||||
notify_url: this.wxPayConfig.notify_url,
|
||||
amount: {
|
||||
total: 1,
|
||||
},
|
||||
scene_info: {
|
||||
payer_client_ip: 'ip',
|
||||
},
|
||||
};
|
||||
const result = await this.wxPay.getInstance().transactions_native(params);
|
||||
return this.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付通知回调
|
||||
* 微信支付回调通知
|
||||
*/
|
||||
@Post('/wxNotify')
|
||||
async wxNotify() {
|
||||
let data = '';
|
||||
this.ctx.req.setEncoding('utf8');
|
||||
this.ctx.req.on('data', chunk => {
|
||||
data += chunk;
|
||||
});
|
||||
const results = await new Promise((resolve, reject) => {
|
||||
this.ctx.req.on('end', () => {
|
||||
parseString(data, { explicitArray: false }, async (err, json) => {
|
||||
if (err) {
|
||||
return reject('success');
|
||||
}
|
||||
const checkSign = await this.wxPay.signVerify(json.xml);
|
||||
if (checkSign && json.xml.result_code === 'SUCCESS') {
|
||||
// 处理业务逻辑
|
||||
console.log('微信支付成功', json.xml);
|
||||
return resolve(true);
|
||||
}
|
||||
return resolve(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
if (results) {
|
||||
this.ctx.body =
|
||||
'<xml><return_msg>OK</return_msg><return_code>SUCCESS</return_code></xml>';
|
||||
async wxNotify(@Body() body) {
|
||||
const check = await this.wxPay.signVerify(this.ctx);
|
||||
// 验签通过,处理业务逻辑
|
||||
if (check) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝app支付
|
||||
* 支付宝PC网站支付
|
||||
* @returns
|
||||
*/
|
||||
@Post('/alipay')
|
||||
async alipay() {
|
||||
@Post('/aliPc')
|
||||
async aliPc() {
|
||||
const orderNum = await this.aliPay.createOrderNum();
|
||||
// app支付
|
||||
const params = await this.aliPay.getInstance().appPay({
|
||||
subject: '测试商品',
|
||||
body: '测试商品描述',
|
||||
outTradeId: orderNum,
|
||||
timeout: '10m',
|
||||
amount: '10.00',
|
||||
goodsType: '0',
|
||||
const formData = new AlipayFormData();
|
||||
// 调用 setMethod 并传入 get,会返回可以跳转到支付页面的 url
|
||||
formData.setMethod('get');
|
||||
formData.addField('notifyUrl', this.aliPayConfig.notifyUrl);
|
||||
formData.addField('bizContent', {
|
||||
outTradeNo: orderNum,
|
||||
productCode: 'FAST_INSTANT_TRADE_PAY',
|
||||
totalAmount: '0.01',
|
||||
subject: '商品',
|
||||
body: '商品详情',
|
||||
});
|
||||
return this.ok(params);
|
||||
// 返回支付链接
|
||||
const result = await this.aliPay
|
||||
.getInstance()
|
||||
.exec('alipay.trade.page.pay', {}, { formData });
|
||||
return this.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝支付回调
|
||||
* 支付宝APP支付
|
||||
* @returns
|
||||
*/
|
||||
@Post('/aliApp')
|
||||
async aliApp() {
|
||||
const orderNum = await this.aliPay.createOrderNum();
|
||||
|
||||
// 返回支付链接
|
||||
const data = sign(
|
||||
'alipay.trade.app.pay',
|
||||
{
|
||||
notifyUrl: this.aliPayConfig.notifyUrl,
|
||||
bizContent: {
|
||||
subject: '商品标题',
|
||||
totalAmount: '0.01',
|
||||
outTradeNo: orderNum,
|
||||
productCode: 'QUICK_MSECURITY_PAY',
|
||||
},
|
||||
},
|
||||
this.aliPay.getInstance().config
|
||||
);
|
||||
const payInfo = new URLSearchParams(data).toString();
|
||||
return this.ok(payInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付回调通知
|
||||
*/
|
||||
@Post('/aliNotify')
|
||||
async aliNotify(@Body(ALL) body: any) {
|
||||
const { trade_status, out_trade_no } = body;
|
||||
async aliNotify(@Body() body) {
|
||||
const check = await this.aliPay.signVerify(body);
|
||||
if (check && trade_status === 'TRADE_SUCCESS') {
|
||||
// 处理逻辑
|
||||
console.log('支付宝支付成功', out_trade_no);
|
||||
// 验签通过,处理业务逻辑
|
||||
if (check) {
|
||||
}
|
||||
this.ctx.body = 'success';
|
||||
return 'success';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,34 +1,28 @@
|
||||
import { Inject, Post, Provide } from '@midwayjs/decorator';
|
||||
import { Inject, Provide, Get } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { CoolRpc } from '@cool-midway/rpc';
|
||||
import { DemoRpcService } from '../../service/rpc';
|
||||
|
||||
/**
|
||||
* 微服务
|
||||
* 远程RPC调用
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController()
|
||||
export class DemoRpcController extends BaseController {
|
||||
@Inject()
|
||||
rpc: CoolRpc;
|
||||
|
||||
export class AppDemoRpcController extends BaseController {
|
||||
@Inject()
|
||||
demoRpcService: DemoRpcService;
|
||||
|
||||
@Post('/call', { summary: '远程调用' })
|
||||
@Get('/call', { summary: '远程调用' })
|
||||
async call() {
|
||||
return this.ok(
|
||||
await this.rpc.call('goods', 'demoGoodsService', 'test', { a: 1 })
|
||||
);
|
||||
return this.ok(await this.demoRpcService.call());
|
||||
}
|
||||
|
||||
@Post('/event', { summary: '集群事件' })
|
||||
@Get('/event', { summary: '集群事件' })
|
||||
async event() {
|
||||
this.rpc.broadcastEvent('test', { a: 1 });
|
||||
await this.demoRpcService.event();
|
||||
return this.ok();
|
||||
}
|
||||
|
||||
@Post('/transaction', { summary: '分布式事务' })
|
||||
@Get('/transaction', { summary: '分布式事务' })
|
||||
async transaction() {
|
||||
await this.demoRpcService.transaction({ a: 1 });
|
||||
return this.ok();
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
import { Param, Post, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* swagger 文档
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController(null, {
|
||||
tagName: 'swagger demo',
|
||||
})
|
||||
export class AppSwaggerController extends BaseController {
|
||||
@Post('/create', { summary: '创建' })
|
||||
async create(@Param('id') id: number) {
|
||||
return this.ok(id);
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
import { Get, Inject, Provide } from '@midwayjs/decorator';
|
||||
import {
|
||||
CoolController,
|
||||
BaseController,
|
||||
CoolUrlTag,
|
||||
TagTypes,
|
||||
CoolUrlTagData,
|
||||
} from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 测试给URL打标签
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController({
|
||||
api: [],
|
||||
entity: '',
|
||||
pageQueryOp: () => {},
|
||||
})
|
||||
@CoolUrlTag({
|
||||
key: TagTypes.IGNORE_TOKEN,
|
||||
value: ['add'],
|
||||
})
|
||||
export class DemoAppTagController extends BaseController {
|
||||
@Inject()
|
||||
tag: CoolUrlTagData;
|
||||
|
||||
/**
|
||||
* 获得标签数据, 如可以标记忽略token的url,然后在中间件判断
|
||||
* @returns
|
||||
*/
|
||||
@Get('/data')
|
||||
async data() {
|
||||
return this.ok(this.tag.byKey(TagTypes.IGNORE_TOKEN));
|
||||
}
|
||||
}
|
||||
15
src/modules/demo/controller/app/transaction.ts
Normal file
15
src/modules/demo/controller/app/transaction.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { DemoGoodsEntity } from './../../entity/goods';
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { DemoTransactionService } from '../../service/transaction';
|
||||
|
||||
/**
|
||||
* 事务
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||
entity: DemoGoodsEntity,
|
||||
service: DemoTransactionService,
|
||||
})
|
||||
export class AppDemoTransactionController extends BaseController {}
|
||||
@ -1,23 +0,0 @@
|
||||
// import { EntityModel } from '@midwayjs/orm';
|
||||
// import { BaseEntity } from '@cool-midway/core';
|
||||
// import { Column } from 'typeorm';
|
||||
|
||||
// /**
|
||||
// * 商品(多数据库连接)
|
||||
// */
|
||||
// @EntityModel('demo_goods_1', {
|
||||
// connectionName: 'test',
|
||||
// })
|
||||
// export class DemoGoodsTestEntity extends BaseEntity {
|
||||
// @Column({ comment: '标题' })
|
||||
// title: string;
|
||||
|
||||
// @Column({ comment: '图片' })
|
||||
// pic: string;
|
||||
|
||||
// @Column({ comment: '价格', type: 'decimal', precision: 5, scale: 2 })
|
||||
// price: number;
|
||||
|
||||
// @Column({ comment: '分类', type: 'tinyint', default: 0 })
|
||||
// type: number;
|
||||
// }
|
||||
@ -1,21 +1,32 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column } from 'typeorm';
|
||||
import { Column, Entity, Index } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 商品
|
||||
* 商品模块-商品信息
|
||||
*/
|
||||
@EntityModel('demo_goods')
|
||||
@Entity('demo_goods')
|
||||
export class DemoGoodsEntity extends BaseEntity {
|
||||
@Column({ comment: '标题' })
|
||||
@Index()
|
||||
@Column({ comment: '标题', length: 50 })
|
||||
title: string;
|
||||
|
||||
@Column({ comment: '图片' })
|
||||
pic: string;
|
||||
|
||||
@Column({ comment: '价格', type: 'decimal', precision: 5, scale: 2 })
|
||||
@Column({
|
||||
comment: '价格',
|
||||
type: 'decimal',
|
||||
precision: 5,
|
||||
scale: 2,
|
||||
})
|
||||
price: number;
|
||||
|
||||
@Column({ comment: '分类 0-衣服 1-鞋子 2-裤子', type: 'tinyint', default: 0 })
|
||||
type: 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;
|
||||
}
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
import { CoolEsIndex, ICoolEs, BaseEsIndex } from '@cool-midway/es';
|
||||
|
||||
/**
|
||||
* 测试索引
|
||||
*/
|
||||
@CoolEsIndex({ name: 'test', replicas: 0 })
|
||||
export class TestEsIndex extends BaseEsIndex implements ICoolEs {
|
||||
indexInfo() {
|
||||
return {
|
||||
// 需要安装ik分词器 https://github.com/medcl/elasticsearch-analysis-ik
|
||||
name: {
|
||||
type: 'text',
|
||||
analyzer: 'ik_max_word',
|
||||
search_analyzer: 'ik_max_word',
|
||||
fields: {
|
||||
raw: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
age: {
|
||||
type: 'long',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,11 @@
|
||||
import { Provide, Scope, ScopeEnum } from '@midwayjs/decorator';
|
||||
import { CoolEvent, Event } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 接收事件
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@CoolEvent()
|
||||
export class DemoEvent {
|
||||
/**
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
import { CoolUrlTagData, TagTypes } from '@cool-midway/core';
|
||||
import { IMiddleware } from '@midwayjs/core';
|
||||
import { Inject, Middleware } from '@midwayjs/decorator';
|
||||
import { NextFunction, Context } from '@midwayjs/koa';
|
||||
|
||||
@Middleware()
|
||||
export class DemoMiddleware implements IMiddleware<Context, NextFunction> {
|
||||
@Inject()
|
||||
tag: CoolUrlTagData;
|
||||
|
||||
resolve() {
|
||||
return async (ctx: Context, next: NextFunction) => {
|
||||
const urls = this.tag.byKey(TagTypes.IGNORE_TOKEN);
|
||||
|
||||
console.log('忽略token的URL数组', urls);
|
||||
|
||||
// 控制器前执行的逻辑
|
||||
const startTime = Date.now();
|
||||
// 执行下一个 Web 中间件,最后执行到控制器
|
||||
// 这里可以拿到下一个中间件或者控制器的返回值
|
||||
const result = await next();
|
||||
// 控制器之后执行的逻辑
|
||||
console.log(Date.now() - startTime);
|
||||
// 返回给上一个中间件的结果
|
||||
return result;
|
||||
};
|
||||
}
|
||||
}
|
||||
20
src/modules/demo/queue/single.ts
Normal file
20
src/modules/demo/queue/single.ts
Normal file
@ -0,0 +1,20 @@
|
||||
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<void> {
|
||||
// 这边可以执行定时任务具体的业务或队列的业务
|
||||
console.log('数据', job.data);
|
||||
// 抛出错误 可以让队列重试,默认重试5次
|
||||
//throw new Error('错误');
|
||||
done();
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,33 @@
|
||||
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 {
|
||||
async test() {
|
||||
console.log('调用');
|
||||
@InjectEntityModel(DemoGoodsEntity)
|
||||
demoGoodsEntity: Repository<DemoGoodsEntity>;
|
||||
|
||||
/**
|
||||
* 执行sql分页
|
||||
*/
|
||||
async sqlPage(query) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { App, Inject, Provide } from '@midwayjs/decorator';
|
||||
import { App, Provide } from '@midwayjs/decorator';
|
||||
import { DemoGoodsEntity } from '../entity/goods';
|
||||
import { IMidwayApplication } from '@midwayjs/core';
|
||||
import { IMidwayApplication, Inject } from '@midwayjs/core';
|
||||
import {
|
||||
BaseRpcService,
|
||||
CoolRpc,
|
||||
@ -22,12 +22,34 @@ export class DemoRpcService extends BaseRpcService {
|
||||
rpc: CoolRpc;
|
||||
|
||||
/**
|
||||
* 分布式事务
|
||||
* @param params 方法参数
|
||||
* @param rpcTransactionId 无需调用者传参, 本次事务的ID,ID会自动注入无需调用者传参
|
||||
* @param queryRunner 无需调用者传参,操作数据库,需要用queryRunner操作数据库,才能统一提交或回滚事务
|
||||
* 远程调用
|
||||
* @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);
|
||||
@ -42,18 +64,7 @@ export class DemoRpcService extends BaseRpcService {
|
||||
// 将事务id传给调用的远程服务方法
|
||||
await this.rpc.call('goods', 'demoGoodsService', 'transaction', {
|
||||
rpcTransactionId,
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
async info(params) {
|
||||
return params;
|
||||
}
|
||||
async getUser() {
|
||||
return {
|
||||
uid: '123',
|
||||
username: 'mockedName',
|
||||
phone: '12345678901',
|
||||
email: 'xxx.xxx@xxx.com',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
23
src/modules/demo/service/transaction.ts
Normal file
23
src/modules/demo/service/transaction.ts
Normal file
@ -0,0 +1,23 @@
|
||||
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>(DemoGoodsEntity, param);
|
||||
return {
|
||||
id: param.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
import {
|
||||
WSController,
|
||||
OnWSConnection,
|
||||
Inject,
|
||||
OnWSMessage,
|
||||
} from '@midwayjs/decorator';
|
||||
import { Context } from '@midwayjs/socketio';
|
||||
/**
|
||||
* 测试
|
||||
*/
|
||||
@WSController('/')
|
||||
export class HelloController {
|
||||
@Inject()
|
||||
ctx: Context;
|
||||
|
||||
@OnWSConnection()
|
||||
async onConnectionMethod() {
|
||||
console.log('on client connect', this.ctx.id);
|
||||
console.log('参数', this.ctx.handshake.query);
|
||||
this.ctx.emit('data', '连接成功');
|
||||
}
|
||||
|
||||
@OnWSMessage('myEvent')
|
||||
async gotMessage(data) {
|
||||
console.log('on data got', this.ctx.id, data);
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column } from 'typeorm';
|
||||
import { Column, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 字典信息
|
||||
*/
|
||||
@EntityModel('dict_info')
|
||||
@Entity('dict_info')
|
||||
export class DictInfoEntity extends BaseEntity {
|
||||
@Column({ comment: '类型ID' })
|
||||
typeId: number;
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { EntityModel } from '@midwayjs/orm';
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column } from 'typeorm';
|
||||
import { Column, Entity } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 字典类别
|
||||
*/
|
||||
@EntityModel('dict_type')
|
||||
@Entity('dict_type')
|
||||
export class DictTypeEntity extends BaseEntity {
|
||||
@Column({ comment: '名称' })
|
||||
name: string;
|
||||
|
||||
@ -2,7 +2,7 @@ import { DictTypeEntity } from './../entity/type';
|
||||
import { DictInfoEntity } from './../entity/info';
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/orm';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository, In } from 'typeorm';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@ -33,7 +33,7 @@ export class DictInfoService extends BaseService {
|
||||
}
|
||||
const data = await this.dictInfoEntity
|
||||
.createQueryBuilder('a')
|
||||
.select(['a.id', 'a.name', 'a.typeId', 'a.parentId'])
|
||||
.select(['a.id', 'a.name', 'a.typeId', 'a.parentId', 'a.orderNum'])
|
||||
.where('typeId in(:typeIds)', {
|
||||
typeIds: typeData.map(e => {
|
||||
return e.id;
|
||||
@ -54,7 +54,7 @@ export class DictInfoService extends BaseService {
|
||||
* @returns
|
||||
*/
|
||||
async value(infoId: number) {
|
||||
const info = await this.dictInfoEntity.findOne({ id: infoId });
|
||||
const info = await this.dictInfoEntity.findOneBy({ id: infoId });
|
||||
return info?.name;
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ export class DictInfoService extends BaseService {
|
||||
* @returns
|
||||
*/
|
||||
async values(infoIds: number[]) {
|
||||
const infos = await this.dictInfoEntity.find({ id: In(infoIds) });
|
||||
const infos = await this.dictInfoEntity.findBy({ id: In(infoIds) });
|
||||
return infos.map(e => {
|
||||
return e.name;
|
||||
});
|
||||
@ -88,7 +88,7 @@ export class DictInfoService extends BaseService {
|
||||
* @param id
|
||||
*/
|
||||
private async delChildDict(id) {
|
||||
const delDict = await this.dictInfoEntity.find({ parentId: id });
|
||||
const delDict = await this.dictInfoEntity.findBy({ parentId: id });
|
||||
if (_.isEmpty(delDict)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { DictInfoEntity } from './../entity/info';
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/orm';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository, In } from 'typeorm';
|
||||
|
||||
/**
|
||||
|
||||
19
src/modules/iot/config.ts
Normal file
19
src/modules/iot/config.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { ModuleConfig } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 模块配置
|
||||
*/
|
||||
export default () => {
|
||||
return {
|
||||
// 模块名称
|
||||
name: '物联网',
|
||||
// 模块描述
|
||||
description: '物联网模块,主要提供物联交互,状态监测等',
|
||||
// 中间件,只对本模块有效
|
||||
middlewares: [],
|
||||
// 中间件,全局有效
|
||||
globalMiddlewares: [],
|
||||
// 模块加载顺序,默认为0,值越大越优先加载
|
||||
order: 0,
|
||||
} as ModuleConfig;
|
||||
};
|
||||
17
src/modules/iot/controller/admin/device.ts
Normal file
17
src/modules/iot/controller/admin/device.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { IotDeviceEntity } from './../../entity/device';
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 设备信息
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||
entity: IotDeviceEntity,
|
||||
pageQueryOp: {
|
||||
keyWordLikeFields: ['label', 'uniqueId'],
|
||||
fieldEq: ['status'],
|
||||
},
|
||||
})
|
||||
export class AdminIotDeviceController extends BaseController {}
|
||||
16
src/modules/iot/controller/admin/message.ts
Normal file
16
src/modules/iot/controller/admin/message.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { IotMessageEntity } from './../../entity/message';
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 设备消息
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController({
|
||||
api: ['page'],
|
||||
entity: IotMessageEntity,
|
||||
pageQueryOp: {
|
||||
fieldEq: ['deviceId'],
|
||||
},
|
||||
})
|
||||
export class AdminIotMessageController extends BaseController {}
|
||||
27
src/modules/iot/controller/admin/mqtt.ts
Normal file
27
src/modules/iot/controller/admin/mqtt.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { IotMqttService } from './../../service/mqtt';
|
||||
import { Provide, Get, Post, Body, Inject } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* MQTT相关
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController()
|
||||
export class AdminIotMqttController extends BaseController {
|
||||
@Inject()
|
||||
iotMqttService: IotMqttService;
|
||||
|
||||
@Get('/config', { summary: 'MQTT配置信息' })
|
||||
async config() {
|
||||
return this.ok(await this.iotMqttService.config());
|
||||
}
|
||||
|
||||
@Post('/publish', { summary: '推送消息' })
|
||||
async publish(
|
||||
@Body('uniqueId') uniqueId: string,
|
||||
@Body('data') data: string
|
||||
) {
|
||||
await this.iotMqttService.publish(uniqueId, data);
|
||||
return this.ok();
|
||||
}
|
||||
}
|
||||
19
src/modules/iot/controller/mqtt.ts
Normal file
19
src/modules/iot/controller/mqtt.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Get, Inject, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { CoolMqttServe } from '@cool-midway/iot';
|
||||
|
||||
/**
|
||||
* MQTT
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController()
|
||||
export class IotMqttController extends BaseController {
|
||||
@Inject()
|
||||
coolMqttServe: CoolMqttServe;
|
||||
|
||||
@Get('/publish')
|
||||
async publish() {
|
||||
await this.coolMqttServe.publish('presence', 'hello');
|
||||
return this.ok();
|
||||
}
|
||||
}
|
||||
25
src/modules/iot/entity/device.ts
Normal file
25
src/modules/iot/entity/device.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column, Entity, Index } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 设备
|
||||
*/
|
||||
@Entity('iot_device')
|
||||
export class IotDeviceEntity extends BaseEntity {
|
||||
@Column({ comment: '图标', nullable: true })
|
||||
icon: string;
|
||||
|
||||
@Column({ comment: '名称' })
|
||||
name: string;
|
||||
|
||||
@Index({ unique: true })
|
||||
@Column({ comment: '设备唯一ID' })
|
||||
uniqueId: string;
|
||||
|
||||
@Index()
|
||||
@Column({ comment: '状态 0-离线 1-在线', type: 'tinyint', default: 0 })
|
||||
status: number;
|
||||
|
||||
@Column({ comment: '客户端ID', nullable: true })
|
||||
clientId: string;
|
||||
}
|
||||
19
src/modules/iot/entity/message.ts
Normal file
19
src/modules/iot/entity/message.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { BaseEntity } from '@cool-midway/core';
|
||||
import { Column, Entity, Index } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 设备消息
|
||||
*/
|
||||
@Entity('iot_message')
|
||||
export class IotMessageEntity extends BaseEntity {
|
||||
@Index()
|
||||
@Column({ comment: '设备ID' })
|
||||
deviceId: number;
|
||||
|
||||
@Column({ comment: '数据' })
|
||||
data: string;
|
||||
|
||||
@Index()
|
||||
@Column({ comment: '类型 0-推送 1-接收', type: 'tinyint', default: 1 })
|
||||
type: number;
|
||||
}
|
||||
18
src/modules/iot/event/app.ts
Normal file
18
src/modules/iot/event/app.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { Inject } from '@midwayjs/core';
|
||||
import { CoolEvent, Event } from '@cool-midway/core';
|
||||
import { IotDeviceService } from '../service/device';
|
||||
|
||||
/**
|
||||
* 应用事件
|
||||
*/
|
||||
@CoolEvent()
|
||||
export class AppEvent {
|
||||
@Inject()
|
||||
iotDeviceService: IotDeviceService;
|
||||
|
||||
@Event('onServerReady')
|
||||
async onServerReady() {
|
||||
// 重置设备状态
|
||||
await this.iotDeviceService.resetStatus();
|
||||
}
|
||||
}
|
||||
86
src/modules/iot/event/mqtt.ts
Normal file
86
src/modules/iot/event/mqtt.ts
Normal file
@ -0,0 +1,86 @@
|
||||
import { IotMessageService } from './../service/message';
|
||||
import { IotDeviceService } from './../service/device';
|
||||
import { ILogger, Inject } from '@midwayjs/core';
|
||||
import { CoolMqtt, CoolMqttEvent, CoolMqttServe } from '@cool-midway/iot';
|
||||
|
||||
/**
|
||||
* 应用事件
|
||||
*/
|
||||
@CoolMqtt()
|
||||
export class IotMQTTEvent {
|
||||
@Inject()
|
||||
iotDeviceService: IotDeviceService;
|
||||
|
||||
@Inject()
|
||||
iotMessageService: IotMessageService;
|
||||
|
||||
@Inject()
|
||||
logger: ILogger;
|
||||
|
||||
@Inject()
|
||||
coolMqttServe: CoolMqttServe;
|
||||
|
||||
/**
|
||||
* 客户端连接
|
||||
* @param client
|
||||
*/
|
||||
@CoolMqttEvent('client')
|
||||
async client(client) {
|
||||
this.logger.info('mqtt client event clientId:', client.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
* @param packet
|
||||
* @param client
|
||||
*/
|
||||
@CoolMqttEvent('publish')
|
||||
async publish(packet, client) {
|
||||
if (packet.cmd) {
|
||||
// console.log(11);
|
||||
await this.iotMessageService.record(
|
||||
packet.topic,
|
||||
packet.payload.toString(),
|
||||
packet.properties?.contentType == 'push' ? 0 : 1
|
||||
);
|
||||
if (
|
||||
!packet.topic.includes('@admin') &&
|
||||
packet.properties?.contentType != 'push'
|
||||
) {
|
||||
this.coolMqttServe.publish(
|
||||
`${packet.topic}@admin`,
|
||||
packet.payload.toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅事件 注册设备
|
||||
* @param subscriptions
|
||||
* @param client
|
||||
*/
|
||||
@CoolMqttEvent('subscribe')
|
||||
async subscribe(subscriptions, client) {
|
||||
await this.iotDeviceService.register(subscriptions[0].topic, client.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订阅
|
||||
* @param subscriptions
|
||||
* @param client
|
||||
*/
|
||||
@CoolMqttEvent('unsubscribe')
|
||||
async unsubscribe(subscriptions, client) {
|
||||
await this.iotDeviceService.changeStatus(subscriptions[0], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开连接
|
||||
* @param client
|
||||
*/
|
||||
@CoolMqttEvent('clientDisconnect')
|
||||
async clientDisconnect(client) {
|
||||
this.logger.info('mqtt clientDisconnect event clientId:', client.id);
|
||||
}
|
||||
}
|
||||
49
src/modules/iot/service/device.ts
Normal file
49
src/modules/iot/service/device.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { IotDeviceEntity } from './../entity/device';
|
||||
import { Provide, Scope, ScopeEnum } from '@midwayjs/decorator';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 设备
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class IotDeviceService extends BaseService {
|
||||
@InjectEntityModel(IotDeviceEntity)
|
||||
iotDeviceEntity: Repository<IotDeviceEntity>;
|
||||
|
||||
/**
|
||||
* 注册设备
|
||||
* @param uniqueId
|
||||
* @param clientId
|
||||
*/
|
||||
async register(uniqueId: string, clientId: string) {
|
||||
const info = await this.iotDeviceEntity.findOneBy({ uniqueId });
|
||||
if (info) {
|
||||
await this.iotDeviceEntity.update({ uniqueId }, { status: 1, clientId });
|
||||
} else {
|
||||
// await this.iotDeviceEntity.insert({ uniqueId, clientId, status: 1 });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置所有设备状态
|
||||
*/
|
||||
async resetStatus() {
|
||||
await this.iotDeviceEntity
|
||||
.createQueryBuilder()
|
||||
.update()
|
||||
.set({ status: 0 })
|
||||
.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变设备状态
|
||||
* @param uniqueId
|
||||
* @param status
|
||||
*/
|
||||
async changeStatus(uniqueId: string, status: number) {
|
||||
await this.iotDeviceEntity.update({ uniqueId }, { status });
|
||||
}
|
||||
}
|
||||
32
src/modules/iot/service/message.ts
Normal file
32
src/modules/iot/service/message.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { IotMessageEntity } from './../entity/message';
|
||||
import { IotDeviceEntity } from './../entity/device';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Provide, Singleton } from '@midwayjs/core';
|
||||
|
||||
/**
|
||||
* 消息
|
||||
*/
|
||||
@Provide()
|
||||
@Singleton()
|
||||
export class IotMessageService extends BaseService {
|
||||
@InjectEntityModel(IotDeviceEntity)
|
||||
iotDeviceEntity: Repository<IotDeviceEntity>;
|
||||
|
||||
@InjectEntityModel(IotMessageEntity)
|
||||
iotMessageEntity: Repository<IotMessageEntity>;
|
||||
|
||||
/**
|
||||
* 记录消息
|
||||
* @param uniqueId 设备唯一ID
|
||||
* @param data 数据
|
||||
* @param type 类型 0-推送 1-接收
|
||||
*/
|
||||
async record(uniqueId: string, data: string, type: number) {
|
||||
const device = await this.iotDeviceEntity.findOneBy({ uniqueId });
|
||||
if (device) {
|
||||
await this.iotMessageEntity.insert({ deviceId: device.id, data, type });
|
||||
}
|
||||
}
|
||||
}
|
||||
43
src/modules/iot/service/mqtt.ts
Normal file
43
src/modules/iot/service/mqtt.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { CoolMqttServe } from '@cool-midway/iot';
|
||||
import { IotMessageEntity } from './../entity/message';
|
||||
import { Config, Inject, Provide } from '@midwayjs/decorator';
|
||||
import { BaseService, CoolIotConfig } from '@cool-midway/core';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
/**
|
||||
* MQTT
|
||||
*/
|
||||
@Provide()
|
||||
export class IotMqttService extends BaseService {
|
||||
@InjectEntityModel(IotMessageEntity)
|
||||
iotMessageEntity: Repository<IotMessageEntity>;
|
||||
|
||||
@Config('cool.iot')
|
||||
coolIotConfig: CoolIotConfig;
|
||||
|
||||
@Inject()
|
||||
coolMqttServe: CoolMqttServe;
|
||||
|
||||
/**
|
||||
* 配置信息
|
||||
*/
|
||||
async config() {
|
||||
return {
|
||||
port: this.coolIotConfig.port,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送消息
|
||||
* @param uniqueId 设备唯一ID
|
||||
* @param data 推送数据
|
||||
*/
|
||||
async publish(uniqueId: string, data: string) {
|
||||
await this.coolMqttServe.publish(uniqueId, data, {
|
||||
properties: {
|
||||
contentType: 'push',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
19
src/modules/recycle/config.ts
Normal file
19
src/modules/recycle/config.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { ModuleConfig } from '@cool-midway/core';
|
||||
|
||||
/**
|
||||
* 模块配置
|
||||
*/
|
||||
export default () => {
|
||||
return {
|
||||
// 模块名称
|
||||
name: '数据回收',
|
||||
// 模块描述
|
||||
description: '收集被删除的数据,管理和恢复',
|
||||
// 中间件,只对本模块有效
|
||||
middlewares: [],
|
||||
// 中间件,全局有效
|
||||
globalMiddlewares: [],
|
||||
// 模块加载顺序,默认为0,值越大越优先加载
|
||||
order: 0,
|
||||
} as ModuleConfig;
|
||||
};
|
||||
34
src/modules/recycle/controller/admin/data.ts
Normal file
34
src/modules/recycle/controller/admin/data.ts
Normal file
@ -0,0 +1,34 @@
|
||||
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: {
|
||||
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();
|
||||
}
|
||||
}
|
||||
32
src/modules/recycle/entity/data.ts
Normal file
32
src/modules/recycle/entity/data.ts
Normal file
@ -0,0 +1,32 @@
|
||||
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: string;
|
||||
|
||||
@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;
|
||||
}
|
||||
21
src/modules/recycle/event/data.ts
Normal file
21
src/modules/recycle/event/data.ts
Normal file
@ -0,0 +1,21 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
3
src/modules/recycle/init.sql
Normal file
3
src/modules/recycle/init.sql
Normal file
@ -0,0 +1,3 @@
|
||||
BEGIN;
|
||||
INSERT INTO `base_sys_conf` VALUES (2, '2021-02-25 14:23:26.810981', '2021-02-25 14:23:26.810981', 'recycleKeep', '31');
|
||||
COMMIT;
|
||||
32
src/modules/recycle/schedule/data.ts
Normal file
32
src/modules/recycle/schedule/data.ts
Normal file
@ -0,0 +1,32 @@
|
||||
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`
|
||||
);
|
||||
}
|
||||
}
|
||||
89
src/modules/recycle/service/data.ts
Normal file
89
src/modules/recycle/service/data.ts
Normal file
@ -0,0 +1,89 @@
|
||||
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 { 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<RecycleDataEntity>;
|
||||
|
||||
@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;
|
||||
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')
|
||||
.format('YYYY-MM-DD')} 00:00:00`;
|
||||
await this.recycleDataEntity
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.where('createTime < :createTime', { createTime: beforeDate })
|
||||
.execute();
|
||||
} else {
|
||||
await this.recycleDataEntity.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,5 +15,10 @@ export default () => {
|
||||
globalMiddlewares: [],
|
||||
// 模块加载顺序,默认为0,值越大越优先加载
|
||||
order: 0,
|
||||
// wps的配置
|
||||
wps: {
|
||||
// 这是个测试的appId,会有水印
|
||||
appId: 'SX20230111NDUAGQ',
|
||||
},
|
||||
} as ModuleConfig;
|
||||
};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { Config, Get, Provide } from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { SpaceInfoEntity } from '../../entity/info';
|
||||
import { SpaceInfoService } from '../../service/info';
|
||||
|
||||
/**
|
||||
* 图片空间信息
|
||||
@ -9,8 +10,17 @@ import { SpaceInfoEntity } from '../../entity/info';
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||
entity: SpaceInfoEntity,
|
||||
service: SpaceInfoService,
|
||||
pageQueryOp: {
|
||||
fieldEq: ['type', 'classifyId'],
|
||||
},
|
||||
})
|
||||
export class BaseAppSpaceInfoController extends BaseController {}
|
||||
export class BaseAppSpaceInfoController extends BaseController {
|
||||
@Config('module.space.wps')
|
||||
config;
|
||||
|
||||
@Get('/getConfig', { summary: '获得WPS配置' })
|
||||
async getConfig() {
|
||||
return this.ok({ appId: this.config.appId });
|
||||
}
|
||||
}
|
||||
|
||||
65
src/modules/space/controller/app/wps.ts
Normal file
65
src/modules/space/controller/app/wps.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import {
|
||||
ALL,
|
||||
Body,
|
||||
Files,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
Post,
|
||||
Provide,
|
||||
Query,
|
||||
} from '@midwayjs/decorator';
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { SpaceWpsService } from '../../service/wps';
|
||||
|
||||
/**
|
||||
* wps回调
|
||||
*/
|
||||
@Provide()
|
||||
@CoolController('/wps')
|
||||
export class AppSpaceWpsController extends BaseController {
|
||||
@Inject()
|
||||
spaceWpsService: SpaceWpsService;
|
||||
|
||||
@Get('/v3/3rd/files/:file_id', { summary: '获取文件信息' })
|
||||
async files(@Param('file_id') file_id: string) {
|
||||
return await this.spaceWpsService.getFiles(file_id);
|
||||
}
|
||||
|
||||
@Get('/v3/3rd/files/:file_id/download', { summary: '获取文件下载地址' })
|
||||
async download(@Param('file_id') file_id: string) {
|
||||
return await this.spaceWpsService.download(file_id);
|
||||
}
|
||||
|
||||
@Get('/v3/3rd/files/:file_id/permission', { summary: '获取文档用户权限' })
|
||||
async permission(@Param('file_id') file_id: string) {
|
||||
return await this.spaceWpsService.permission(file_id);
|
||||
}
|
||||
|
||||
@Post('/v3/3rd/files/:file_id/upload', { summary: '文件上传' })
|
||||
async upload(@Param('file_id') file_id: string, @Files() files) {
|
||||
return await this.spaceWpsService.upload(file_id, files);
|
||||
}
|
||||
|
||||
@Get('/v3/3rd/files/:file_id/upload/prepare', { summary: '准备上传阶段' })
|
||||
async uploadPrepare(@Param('file_id') file_id: string) {
|
||||
return await this.spaceWpsService.uploadPrepare(file_id);
|
||||
}
|
||||
|
||||
@Post('/v3/3rd/files/:file_id/upload/address', { summary: '获取上传地址' })
|
||||
async uploadAddress(@Param('file_id') file_id: string, @Body(ALL) body) {
|
||||
return await this.spaceWpsService.uploadAddress(file_id, body);
|
||||
}
|
||||
|
||||
@Post('/v3/3rd/files/:file_id/upload/complete', {
|
||||
summary: '上传完成后,回调通知上传结果',
|
||||
})
|
||||
async uploadComplete(@Param('file_id') file_id: string, @Body(ALL) body) {
|
||||
return await this.spaceWpsService.uploadComplete(file_id, body);
|
||||
}
|
||||
|
||||
@Get('/v3/3rd/users', { summary: '用户信息' })
|
||||
async users(@Query('user_ids') user_ids: string[]) {
|
||||
return await this.spaceWpsService.users(user_ids);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user