发布6.x

This commit is contained in:
小鹏 2023-03-08 15:36:37 +08:00
parent 95545591f2
commit 375a93638b
116 changed files with 2362 additions and 688 deletions

9
.gitignore vendored Executable file → Normal file
View 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
View File

@ -0,0 +1,9 @@
{
"extends": [
"development"
],
"hints": {
"typescript-config/consistent-casing": "off",
"typescript-config/strict": "off"
}
}

View File

@ -8,7 +8,6 @@
"/**",
" * 描述",
" */",
"@Provide()",
"@CoolController({",
" api: ['add', 'delete', 'update', 'info', 'list', 'page'],",
" entity: 实体,",

View File

@ -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;",

View File

@ -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
View File

@ -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"
]
}
]
}

View File

@ -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';",
"",
"/**",

View File

@ -1,3 +0,0 @@
{
"liveServer.settings.port": 5501
}

View File

@ -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

0
README.md Executable file → Normal file
View File

36
docker-compose.yml Normal file
View 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
View 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

View File

@ -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
);
});

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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'],

View File

@ -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();
}
}

View File

@ -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: '配置键' })

View File

@ -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;

View File

@ -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;
}

View File

@ -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',
})

View File

@ -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: '键位' })

View File

@ -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[];
}

View File

@ -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;

View File

@ -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;

View File

@ -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 })

View File

@ -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;

View File

@ -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);

View File

@ -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
);

View File

@ -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;
}

View File

@ -0,0 +1,10 @@
import { DataSource } from 'typeorm';
export class TempDataSource extends DataSource {
/**
*
*/
async buildMetadatas() {
await super.buildMetadatas();
}
}

View File

@ -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 (?)',

View File

@ -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);
}

View File

@ -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) {
// 校验用户状态及密码

View File

@ -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);
}
}

View File

@ -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') {

View File

@ -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 => {

View File

@ -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('用户不存在');
}

View File

@ -0,0 +1,19 @@
import { ModuleConfig } from '@cool-midway/core';
/**
*
*/
export default () => {
return {
// 模块名称
name: '云服务',
// 模块描述
description: '云函数、云数据库、云存储等',
// 中间件,只对本模块有效
middlewares: [],
// 中间件,全局有效
globalMiddlewares: [],
// 模块加载顺序默认为0值越大越优先加载
order: 0,
} as ModuleConfig;
};

View 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));
}
}

View 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));
}
}

View 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 {}

View 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) {}
}

View 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;
}

View 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;
}

View 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;
}

View 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();
}
}

View 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();
}
}

View 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;
}
}
}

View File

@ -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;
};

View File

@ -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 {}

View File

@ -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'));
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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()

View File

@ -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')
);
}
}

View File

@ -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));
}
}

View File

@ -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';
}
}

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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));
}
}

View 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 {}

View File

@ -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;
// }

View File

@ -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;
}

View File

@ -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',
},
};
}
}

View File

@ -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 {
/**

View File

@ -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;
};
}
}

View 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();
}
}

View File

@ -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);
}
}

View File

@ -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 IDID会自动注入无需调用者传参
* @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',
};
}
}

View 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,
};
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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
View File

@ -0,0 +1,19 @@
import { ModuleConfig } from '@cool-midway/core';
/**
*
*/
export default () => {
return {
// 模块名称
name: '物联网',
// 模块描述
description: '物联网模块,主要提供物联交互,状态监测等',
// 中间件,只对本模块有效
middlewares: [],
// 中间件,全局有效
globalMiddlewares: [],
// 模块加载顺序默认为0值越大越优先加载
order: 0,
} as ModuleConfig;
};

View 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 {}

View 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 {}

View 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();
}
}

View 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();
}
}

View 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;
}

View 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;
}

View 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();
}
}

View 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);
}
}

View 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 });
}
}

View 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 });
}
}
}

View 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',
},
});
}
}

View File

@ -0,0 +1,19 @@
import { ModuleConfig } from '@cool-midway/core';
/**
*
*/
export default () => {
return {
// 模块名称
name: '数据回收',
// 模块描述
description: '收集被删除的数据,管理和恢复',
// 中间件,只对本模块有效
middlewares: [],
// 中间件,全局有效
globalMiddlewares: [],
// 模块加载顺序默认为0值越大越优先加载
order: 0,
} as ModuleConfig;
};

View 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();
}
}

View 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;
}

View 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);
}
}

View 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;

View 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`
);
}
}

View 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();
}
}
}

View File

@ -15,5 +15,10 @@ export default () => {
globalMiddlewares: [],
// 模块加载顺序默认为0值越大越优先加载
order: 0,
// wps的配置
wps: {
// 这是个测试的appId会有水印
appId: 'SX20230111NDUAGQ',
},
} as ModuleConfig;
};

View File

@ -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 });
}
}

View 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