新增插件管理

This commit is contained in:
cool 2024-01-25 17:50:25 +08:00
parent 5b599c4a20
commit 56a5b7a620
25 changed files with 1455 additions and 803 deletions

View File

@ -1,12 +1,12 @@
{
"name": "cool-admin",
"version": "7.0.0",
"version": "7.1.0",
"description": "一个项目用COOL就够了",
"private": true,
"dependencies": {
"@cool-midway/cache-manager-fs-hash": "^7.0.0",
"@cool-midway/cloud": "^7.0.0",
"@cool-midway/core": "^7.1.0",
"@cool-midway/core": "^7.1.1",
"@cool-midway/file": "^7.0.5",
"@cool-midway/iot": "^7.0.0",
"@cool-midway/pay": "^7.0.0",
@ -24,20 +24,12 @@
"@midwayjs/static-file": "^3.14.0",
"@midwayjs/task": "^3.6.0",
"@midwayjs/typeorm": "^3.14.0",
"@midwayjs/upload": "^3.14.3",
"@midwayjs/validate": "^3.14.0",
"@midwayjs/view-ejs": "^3.14.0",
"axios": "^1.6.5",
"ipip-ipdb": "^0.6.0",
"jsonwebtoken": "^9.0.2",
"lodash": "^4.17.21",
"md5": "^2.3.0",
"mini-svg-data-uri": "^1.4.4",
"moment": "^2.30.1",
"mysql2": "^3.7.0",
"svg-captcha": "^1.4.0",
"svg2png-wasm": "^1.4.1",
"typeorm": "^0.3.19",
"uuid": "^9.0.1"
"typeorm": "^0.3.19"
},
"devDependencies": {
"@midwayjs/cli": "^2.1.1",

View File

@ -1,6 +1,5 @@
import { CoolConfig } from '@cool-midway/core';
import { MidwayConfig } from '@midwayjs/core';
// import * as path from 'path';
/**
* npm run dev

View File

@ -1,5 +1,5 @@
import * as orm from '@midwayjs/typeorm';
import { Configuration, App, Config, Inject } from '@midwayjs/decorator';
import { Configuration, App, Inject } from '@midwayjs/decorator';
import * as koa from '@midwayjs/koa';
import * as validate from '@midwayjs/validate';
import * as info from '@midwayjs/info';
@ -13,8 +13,7 @@ import * as cloud from '@cool-midway/cloud';
import * as file from '@cool-midway/file';
import * as sms from '@cool-midway/sms';
import { ILogger } from '@midwayjs/logger';
import { Repository } from 'typeorm';
import { BaseSysRoleMenuEntity } from './modules/base/entity/sys/role_menu';
import { IMidwayApplication } from '@midwayjs/core';
// import * as swagger from '@midwayjs/swagger';
// import * as rpc from '@cool-midway/rpc';
// import * as task from '@cool-midway/task';
@ -64,16 +63,10 @@ import { BaseSysRoleMenuEntity } from './modules/base/entity/sys/role_menu';
})
export class ContainerLifeCycle {
@App()
app: koa.Application;
app: IMidwayApplication;
@Inject()
logger: ILogger;
@Config('module')
config;
@orm.InjectEntityModel(BaseSysRoleMenuEntity)
baseSysRoleMenuEntity: Repository<BaseSysRoleMenuEntity>;
async onReady() {}
}

View File

@ -401,6 +401,44 @@
]
}
]
},
{
"name": "任务管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-activity",
"orderNum": 9,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "任务列表",
"router": "/task/list",
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 0,
"viewPath": "modules/task/views/list.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "权限",
"router": null,
"perms": "task:info:page,task:info:list,task:info:info,task:info:add,task:info:delete,task:info:update,task:info:stop,task:info:start,task:info:once,task:info:log",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
}
]
},
@ -416,7 +454,7 @@
"isShow": true,
"childMenus": [
{
"name": "文档",
"name": "文档官网",
"router": "/tutorial/doc",
"perms": null,
"type": 1,
@ -428,16 +466,65 @@
"childMenus": []
},
{
"name": "插件市场",
"router": "/tutorial/plugin",
"name": "示例组件",
"router": null,
"perms": null,
"type": 1,
"icon": "icon-app",
"type": 0,
"icon": "icon-workbench",
"orderNum": 1,
"viewPath": "https://cool-js.com/plugin/list.html",
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
"childMenus": [
{
"name": "组件预览",
"router": "/demo",
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 1,
"viewPath": "modules/demo/views/demo.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "crud 示例",
"router": "/demo/crud",
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 1,
"viewPath": "modules/demo/views/crud/index.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "编辑器",
"router": "/demo/editor",
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 4,
"viewPath": "modules/demo/views/editor.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "文件上传",
"router": "/demo/upload",
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 3,
"viewPath": "modules/demo/views/upload.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
},
@ -466,79 +553,6 @@
}
]
},
{
"name": "页面设计",
"router": "/design/page",
"perms": null,
"type": 1,
"icon": "icon-design",
"orderNum": 7,
"viewPath": "modules/design/views/page.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "工作台",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-workbench",
"orderNum": 1,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "组件预览",
"router": "/demo",
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 1,
"viewPath": "modules/demo/views/demo.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "crud 示例",
"router": "/demo/crud",
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 1,
"viewPath": "modules/demo/views/crud.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "编辑器",
"router": "/demo/editor",
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 4,
"viewPath": "modules/demo/views/editor.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "文件上传",
"router": "/demo/upload",
"perms": null,
"type": 1,
"icon": "icon-favor",
"orderNum": 3,
"viewPath": "modules/demo/views/upload.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
},
{
"name": "首页",
"router": "/",
@ -550,5 +564,690 @@
"keepAlive": true,
"isShow": false,
"childMenus": []
},
{
"name": "函数开发",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-fx",
"orderNum": 12,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "云数据库",
"router": "/cloud/db",
"perms": null,
"type": 1,
"icon": "icon-db",
"orderNum": 1,
"viewPath": "modules/cloud/views/db.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "初始化Entity",
"router": null,
"perms": "cloud:db:initEntity",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "删除",
"router": null,
"perms": "cloud:db:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "cloud:db:update,cloud:db:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "数据操作测试",
"router": null,
"perms": "cloud:db:data",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "cloud:db:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "cloud:db:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "cloud:db:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "cloud:db:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
},
{
"name": "云函数",
"router": "/cloud/func/info",
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 2,
"viewPath": "modules/cloud/views/func/info.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "调用云函数",
"router": null,
"perms": "cloud:func:info:invoke",
"type": 2,
"icon": null,
"orderNum": 98,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "删除",
"router": null,
"perms": "cloud:func:info:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "cloud:func:info:update,cloud:func:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "cloud:func:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "cloud:func:info:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "cloud:func:info:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "cloud:func:info:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "云函数开发",
"router": null,
"perms": "cloud:func:info:info,cloud:func:info:update,cloud:func:info:invoke",
"type": 2,
"icon": null,
"orderNum": 99,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "查看日志",
"router": null,
"perms": "cloud:func:log:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
},
{
"name": "物联管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-iot",
"orderNum": 12,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "MQTT",
"router": "/iot/device",
"perms": null,
"type": 1,
"icon": "icon-device",
"orderNum": 1,
"viewPath": "modules/iot/views/device.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "删除",
"router": null,
"perms": "iot:device:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "iot:device:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "iot:device:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "iot:device:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "iot:device:info,iot:device:update",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "iot:device:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
},
{
"name": "数据管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-data",
"orderNum": 7,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "字典管理",
"router": "/dict/list",
"perms": null,
"type": 1,
"icon": "icon-dict",
"orderNum": 3,
"viewPath": "modules/dict/views/list.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "删除",
"router": null,
"perms": "dict:info:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "dict:info:update,dict:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "获得字典数据",
"router": null,
"perms": "dict:info:data",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "dict:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "dict:info:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "dict:info:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "dict:info:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "组权限",
"router": null,
"perms": "dict:type:list,dict:type:update,dict:type:delete,dict:type:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
},
{
"name": "数据回收站",
"router": "/recycle/data",
"perms": null,
"type": 1,
"icon": "icon-delete",
"orderNum": 6,
"viewPath": "modules/recycle/views/data.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "恢复数据",
"router": null,
"perms": "recycle:data:restore",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "recycle:data:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "recycle:data:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
},
{
"name": "文件管理",
"router": "/upload/list",
"perms": null,
"type": 1,
"icon": "icon-log",
"orderNum": 5,
"viewPath": "modules/space/views/list.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "权限",
"router": null,
"perms": "space:type:delete,space:type:update,space:type:info,space:type:list,space:type:page,space:type:add,space:info:getConfig,space:info:delete,space:info:update,space:info:info,space:info:list,space:info:page,space:info:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
},
{
"name": "用户管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-user",
"orderNum": 11,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "用户列表",
"router": "/user/list",
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 1,
"viewPath": "modules/user/views/list.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "删除",
"router": null,
"perms": "user:info:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "user:info:update,user:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "user:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "user:info:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "user:info:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "user:info:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
},
{
"name": "扩展管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-favor",
"orderNum": 8,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "页面设计",
"router": "/design/page",
"perms": null,
"type": 1,
"icon": "icon-design",
"orderNum": 95,
"viewPath": "modules/design/views/page.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "插件管理",
"router": "/helper/plugin",
"perms": null,
"type": 1,
"icon": "icon-component",
"orderNum": 4,
"viewPath": "modules/helper/views/plugin.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "权限",
"router": null,
"perms": "plugin:info:install,plugin:info:delete,plugin:info:update,plugin:info:page,plugin:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
}
]

View File

@ -11,11 +11,7 @@ export class AppEvent {
@App()
app: IMidwayApplication;
@Event('onDBInit')
async onDBInit() {
this.initEntity();
}
@Event('onServerReady')
async initEntity() {
const cloudDBService = await this.app
.getApplicationContext()

View File

@ -1,245 +0,0 @@
[
{
"name": "函数开发",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-fx",
"orderNum": 6,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "云数据库",
"router": "/cloud/db",
"perms": null,
"type": 1,
"icon": "icon-db",
"orderNum": 1,
"viewPath": "modules/cloud/views/db.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "初始化Entity",
"router": null,
"perms": "cloud:db:initEntity",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "删除",
"router": null,
"perms": "cloud:db:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "cloud:db:update,cloud:db:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "数据操作测试",
"router": null,
"perms": "cloud:db:data",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "cloud:db:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "cloud:db:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "cloud:db:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "cloud:db:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
},
{
"name": "云函数",
"router": "/cloud/func/info",
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 2,
"viewPath": "modules/cloud/views/func/info.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "调用云函数",
"router": null,
"perms": "cloud:func:info:invoke",
"type": 2,
"icon": null,
"orderNum": 98,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "删除",
"router": null,
"perms": "cloud:func:info:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "cloud:func:info:update,cloud:func:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "cloud:func:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "cloud:func:info:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "cloud:func:info:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "cloud:func:info:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "云函数开发",
"router": null,
"perms": "cloud:func:info:info,cloud:func:info:update,cloud:func:info:invoke",
"type": 2,
"icon": null,
"orderNum": 99,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "查看日志",
"router": null,
"perms": "cloud:func:log:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
}
]

View File

@ -29,10 +29,4 @@ export class DemoGoodsEntity extends BaseEntity {
@Column({ comment: '库存', default: 0 })
stock: number;
@BeforeRemove()
async beforeRemove() {
// await this.service.beforeRemove(this);
console.log('数据被删除11');
}
}

View File

@ -1,124 +0,0 @@
[
{
"name": "字典管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-dict",
"orderNum": 3,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "字典列表",
"router": "/dict/list",
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 1,
"viewPath": "modules/dict/views/list.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "删除",
"router": null,
"perms": "dict:info:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "dict:info:update,dict:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "获得字典数据",
"router": null,
"perms": "dict:info:data",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "dict:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "dict:info:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "dict:info:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "dict:info:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "组权限",
"router": null,
"perms": "dict:type:list,dict:type:update,dict:type:delete,dict:type:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
}
]

View File

@ -1,100 +0,0 @@
[
{
"name": "物联管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-iot",
"orderNum": 4,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "MQTT",
"router": "/iot/device",
"perms": null,
"type": 1,
"icon": "icon-device",
"orderNum": 1,
"viewPath": "modules/iot/views/device.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "删除",
"router": null,
"perms": "iot:device:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "iot:device:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "iot:device:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "iot:device:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "iot:device:info,iot:device:update",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "iot:device:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
}
]

View File

@ -0,0 +1,27 @@
import { ModuleConfig } from '@cool-midway/core';
/**
*
*/
export default options => {
return {
// 模块名称
name: '插件模块',
// 模块描述
description: '插件查看、安装、卸载、配置等',
// 中间件,只对本模块有效
middlewares: [],
// 中间件,全局有效
globalMiddlewares: [],
// 模块加载顺序默认为0值越大越优先加载
order: 0,
// 基础插件配置
hooks: {
// 文件上传
upload: {
// 地址前缀
domain: `http://127.0.0.1:${options?.app?.getConfig('koa.port')}`,
},
},
} as ModuleConfig;
};

View File

@ -0,0 +1,35 @@
import {
CoolController,
BaseController,
CoolTag,
CoolUrlTag,
TagTypes,
} from '@cool-midway/core';
import { PluginInfoEntity } from '../../entity/info';
import { Body, Fields, Files, Inject, Post } from '@midwayjs/core';
import { PluginService } from '../../service/info';
/**
*
*/
@CoolUrlTag({
key: TagTypes.IGNORE_TOKEN,
value: [],
})
@CoolController({
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
entity: PluginInfoEntity,
service: PluginService,
})
export class AdminPluginInfoController extends BaseController {
@Inject()
pluginService: PluginService;
@CoolTag(TagTypes.IGNORE_TOKEN)
@Post('/install', { summary: '安装插件' })
async install(@Files() files, @Fields() fields) {
return this.ok(
await this.pluginService.install(files[0].data, fields.force)
);
}
}

View File

@ -0,0 +1,49 @@
import { BaseEntity } from '@cool-midway/core';
import { Column, Entity, DataSource } from 'typeorm';
console.log(DataSource);
/**
*
*/
@Entity('plugin_info')
export class PluginInfoEntity extends BaseEntity {
@Column({ comment: '名称' })
name: string;
@Column({ comment: '简介' })
description: string;
@Column({ comment: 'Key名' })
keyName: string;
@Column({ comment: 'Hook' })
hook: string;
@Column({ comment: '描述', type: 'text' })
readme: string;
@Column({ comment: '版本' })
version: string;
@Column({ comment: 'Logo(base64)', type: 'text', nullable: true })
logo: string;
@Column({ comment: '作者' })
author: string;
@Column({ comment: '状态 0-禁用 1-启用', default: 0 })
status: number;
@Column({ comment: '内容', type: 'json' })
content: {
type: 'comm' | 'module';
data: string;
};
@Column({ comment: '插件的plugin.json', type: 'json', nullable: true })
pluginJson: any;
@Column({ comment: '配置', type: 'json', nullable: true })
config: any;
}

View File

@ -0,0 +1,24 @@
import { CoolEvent, Event } from '@cool-midway/core';
import { App, Config, ILogger, Logger } from '@midwayjs/core';
import { IMidwayKoaApplication } from '@midwayjs/koa';
import { PluginCenterService } from '../service/center';
/**
* jwt.secret
*/
@CoolEvent()
export class BaseAppEvent {
@Logger()
coreLogger: ILogger;
@Config('module')
config;
@App()
app: IMidwayKoaApplication;
@Event('onServerReady')
async onServerReady() {
await this.app.getApplicationContext().getAsync(PluginCenterService);
}
}

View File

@ -0,0 +1,26 @@
import { IMidwayContext, IMidwayApplication } from '@midwayjs/core';
import { PluginInfo } from '../interface';
/**
* hook基类
*/
export class BasePluginHook {
/** 请求上下文用到此项无法本地调试需安装到cool-admin中才能调试 */
ctx: IMidwayContext;
/** 应用实例用到此项无法本地调试需安装到cool-admin中才能调试 */
app: IMidwayApplication;
/** 插件信息 */
pluginInfo: PluginInfo;
/**
*
*/
async init(
pluginInfo: PluginInfo,
ctx?: IMidwayContext,
app?: IMidwayApplication
) {
this.pluginInfo = pluginInfo;
this.ctx = ctx;
this.app = app;
}
}

View File

@ -0,0 +1,114 @@
import { BaseUpload, MODETYPE } from './interface';
import { BasePluginHook } from '../base';
import * as fs from 'fs';
import * as download from 'download';
import * as path from 'path';
import * as moment from 'moment';
import { v1 as uuid } from 'uuid';
import { CoolCommException } from '@cool-midway/core';
import * as _ from 'lodash';
/**
*
*/
export class PluginUpload extends BasePluginHook implements BaseUpload {
/**
*
* @returns
*/
async getMode() {
return {
mode: MODETYPE.LOCAL,
type: MODETYPE.LOCAL,
};
}
/**
*
* @returns
*/
async getMetaFileObj() {
return;
}
/**
*
* @param url
* @param fileName
*/
async downAndUpload(url: string, fileName?: string) {
const { domain } = this.pluginInfo.config;
// 从url获取扩展名
const extend = path.extname(url);
// 数据
const data = url.includes('http')
? await download(url)
: fs.readFileSync(url);
// 创建文件夹
const dirPath = path.join(
this.app.getBaseDir(),
'..',
`public/uploads/${moment().format('YYYYMMDD')}`
);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
fs.writeFileSync(
`${dirPath}/${fileName ? fileName : uuid() + extend}`,
data
);
return `${domain}/public/${name}`;
}
/**
* Key()
* @param filePath
* @param key
*/
async uploadWithKey(filePath: any, key: any) {
const { domain } = this.pluginInfo.config;
const data = fs.readFileSync(filePath);
fs.writeFileSync(path.join(this.app.getBaseDir(), '..', key), data);
return domain + key;
}
/**
*
* @param ctx
* @param key
*/
async upload(ctx: any) {
const { domain } = this.pluginInfo.config;
try {
const { key } = ctx.fields;
if (_.isEmpty(ctx.files)) {
throw new CoolCommException('上传文件为空');
}
const file = ctx.files[0];
const extension = file.filename.split('.').pop();
const name =
moment().format('YYYYMMDD') + '/' + (key || `${uuid()}.${extension}`);
const target = path.join(
this.app.getBaseDir(),
'..',
`public/uploads/${name}`
);
const dirPath = path.join(
this.app.getBaseDir(),
'..',
`public/uploads/${moment().format('YYYYMMDD')}`
);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath);
}
const data = fs.readFileSync(file.data);
fs.writeFileSync(target, data);
return domain + '/public/uploads/' + name;
} catch (err) {
throw new CoolCommException('上传失败');
}
}
}
// 导出插件实例, Plugin名称不可修改
export const Plugin = PluginUpload;

View File

@ -0,0 +1,56 @@
// 模式
export enum MODETYPE {
// 本地
LOCAL = 'local',
// 云存储
CLOUD = 'cloud',
// 其他
OTHER = 'other',
}
/**
*
*/
export interface Mode {
// 模式
mode: MODETYPE;
// 类型
type: string;
}
/**
*
*/
export interface BaseUpload {
/**
*
*/
getMode(): Promise<Mode>;
/**
*
* @returns
*/
getMetaFileObj(): Promise<any>;
/**
*
* @param url
* @param fileName
*/
downAndUpload(url: string, fileName?: string): Promise<string>;
/**
* Key()
* @param filePath
* @param key
*/
uploadWithKey(filePath, key): Promise<string>;
/**
*
* @param ctx
* @param key
*/
upload(ctx): Promise<string>;
}

View File

@ -0,0 +1,23 @@
/**
*
*/
export interface PluginInfo {
/** 名称 */
name?: string;
/** 唯一标识 */
key?: string;
/** 钩子 */
hook?: string;
/** 版本 */
version?: string;
/** 描述 */
description?: string;
/** 作者 */
author?: string;
/** logo */
logo?: string;
/** README 使用说明 */
readme?: string;
/** 配置 */
config?: any;
}

View File

@ -0,0 +1,106 @@
import { Provide } from '@midwayjs/decorator';
import {
App,
IMidwayApplication,
Init,
Scope,
ScopeEnum,
} from '@midwayjs/core';
import * as fs from 'fs';
import * as path from 'path';
import { PluginInfoEntity } from '../entity/info';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { PluginInfo } from '../interface';
/**
*
*/
@Provide()
@Scope(ScopeEnum.Singleton)
export class PluginCenterService {
// 插件列表
plugins: Map<string, any> = new Map();
// 插件配置
pluginInfos: Map<string, PluginInfo> = new Map();
@App()
app: IMidwayApplication;
@InjectEntityModel(PluginInfoEntity)
pluginInfoEntity: Repository<PluginInfoEntity>;
@Init()
async init() {
this.plugins.clear();
await this.initHooks();
await this.initPlugin();
}
/**
*
* @param key
* @param cls
*/
async register(key: string, cls: any) {
this.plugins.set(key, cls);
}
/**
*
*/
async initHooks() {
const hooksPath = path.join(
this.app.getBaseDir(),
'modules',
'plugin',
'hooks'
);
for (const key of fs.readdirSync(hooksPath)) {
const stat = fs.statSync(path.join(hooksPath, key));
if (!stat.isDirectory()) {
continue;
}
const { Plugin } = await import(path.join(hooksPath, key, 'index'));
await this.register(key, Plugin);
this.pluginInfos.set(key, {
name: key,
config: this.app.getConfig('module.plugin.hooks.' + key),
});
}
}
/**
*
*/
async initPlugin() {
const plugins = await this.pluginInfoEntity.findBy({ status: 1 });
for (const plugin of plugins) {
const instance = await this.getInstance(plugin.content.data);
this.pluginInfos.set(plugin.keyName, {
...plugin.pluginJson,
config: plugin.config,
});
if (plugin.hook) {
await this.register(plugin.hook, instance);
} else {
await this.register(plugin.keyName, instance);
}
}
}
/**
*
* @param content
* @returns
*/
async getInstance(content: string) {
let _instance;
eval(`
${content}
_instance = Plugin;
`);
return _instance;
}
}

View File

@ -0,0 +1,204 @@
import { App, Inject, Provide } from '@midwayjs/decorator';
import { BaseService, CoolCommException } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Not, Repository } from 'typeorm';
import { PluginInfoEntity } from '../entity/info';
import { IMidwayApplication, IMidwayContext } from '@midwayjs/core';
import * as decompress from 'decompress';
import * as _ from 'lodash';
import { PluginInfo } from '../interface';
import { PluginCenterService } from './center';
import * as fs from 'fs';
/**
*
*/
@Provide()
export class PluginService extends BaseService {
@InjectEntityModel(PluginInfoEntity)
pluginInfoEntity: Repository<PluginInfoEntity>;
@Inject()
ctx: IMidwayContext;
@App()
app: IMidwayApplication;
@Inject()
pluginCenterService: PluginCenterService;
/**
*
* @param data
* @param type
*/
async modifyAfter() {
await this.pluginCenterService.init();
}
/**
*
* @param param
*/
async update(param: any) {
const old = await this.pluginInfoEntity.findOneBy({ id: param.id });
// 启用插件,禁用同名插件
if (old.hook && param.status == 1 && old.status != param.status) {
await this.pluginInfoEntity.update(
{ hook: old.hook, status: 1, id: Not(old.id) },
{ status: 0 }
);
}
await super.update(param);
}
/**
*
* @param key key
* @param method
* @param params
* @returns
*/
async invoke(key: string, method: string, ...params) {
// 实例化
const instance = new (await this.pluginCenterService.plugins.get(key))();
await instance.init(
this.pluginCenterService.pluginInfos.get(key),
this.ctx,
this.app
);
return await instance[method](...params);
}
/**
*
* @param filePath
*/
async check(filePath: string) {
let data;
try {
data = await this.data(filePath);
} catch (e) {
return {
type: 0,
message: `插件信息不完整,请检查${data.errorData}`,
};
}
const check = await this.pluginInfoEntity.findOneBy({
keyName: data.pluginJson.key,
});
if (check && !check.hook) {
return {
type: 1,
message: '插件已存在,继续安装将覆盖',
};
}
if (check && check.hook && check.status == 1) {
return {
type: 2,
message:
'已存在同名Hook插件你可以继续安装但是多个相同的Hook插件只能同时开启一个',
};
}
return {
type: 3,
message: '检查通过',
};
}
/**
*
* @param filePath
*/
async data(filePath: string): Promise<{
pluginJson: any;
readme: string;
logo: string;
content: string;
errorData: string;
}> {
// const plugin = await download(encodeURI(url));
const files = await decompress(filePath);
let errorData;
let pluginJson: PluginInfo, readme: string, logo: string, content: string;
try {
errorData = 'plugin.json';
pluginJson = JSON.parse(
_.find(files, { path: 'plugin.json', type: 'file' }).data.toString()
);
errorData = 'readme';
readme = _.find(files, {
path: pluginJson.readme,
type: 'file',
}).data.toString();
errorData = 'logo';
logo = _.find(files, {
path: pluginJson.logo,
type: 'file',
}).data.toString('base64');
content = _.find(files, {
path: 'src/index.js',
type: 'file',
}).data.toString();
} catch (e) {
throw new CoolCommException('插件信息不完整');
}
return {
pluginJson,
readme,
logo,
content,
errorData,
};
}
/**
*
* @param file
* @param force
*/
async install(filePath: string, force = false) {
const forceBool = typeof force === 'string' ? force === 'true' : force;
const checkResult = await this.check(filePath);
if (checkResult.type != 3 && !forceBool) {
return checkResult;
}
const { pluginJson, readme, logo, content } = await this.data(filePath);
const check = await this.pluginInfoEntity.findOneBy({
keyName: pluginJson.key,
});
const data = {
name: pluginJson.name,
keyName: pluginJson.key,
version: pluginJson.version,
author: pluginJson.author,
hook: pluginJson.hook,
readme,
logo,
content: {
type: 'comm',
data: content,
},
description: pluginJson.description,
pluginJson,
config: pluginJson.config,
status: 1,
} as PluginInfoEntity;
// 存在同名插件,更新,保留配置
if (check) {
await this.pluginInfoEntity.update(check.id, {
...data,
status: check.status,
config: {
...pluginJson.config,
...check.config,
},
});
} else {
// 全新安装
await this.pluginInfoEntity.insert(data);
}
// 初始化插件
await this.pluginCenterService.init();
}
}

View File

@ -1,64 +0,0 @@
[
{
"name": "数据管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-data",
"orderNum": 3,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "数据回收站",
"router": "/recycle/data",
"perms": null,
"type": 1,
"icon": "icon-delete",
"orderNum": 1,
"viewPath": "modules/recycle/views/data.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "恢复数据",
"router": null,
"perms": "recycle:data:restore",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "recycle:data:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "recycle:data:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
}
]

View File

@ -1,14 +0,0 @@
[
{
"name": "文件管理",
"router": "/upload/list",
"perms": null,
"type": 1,
"icon": "icon-log",
"orderNum": 97,
"viewPath": "modules/upload/views/list.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]

View File

@ -1,40 +0,0 @@
[
{
"name": "任务管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-activity",
"orderNum": 97,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "任务列表",
"router": "/task/list",
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 0,
"viewPath": "modules/task/views/list.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "权限",
"router": null,
"perms": "task:info:page,task:info:list,task:info:info,task:info:add,task:info:delete,task:info:update,task:info:stop,task:info:start,task:info:once,task:info:log",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
}
]

View File

@ -1,100 +0,0 @@
[
{
"name": "用户管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-user",
"orderNum": 8,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "用户列表",
"router": "/user/list",
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 1,
"viewPath": "modules/user/views/list.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "删除",
"router": null,
"perms": "user:info:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "user:info:update,user:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "user:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "user:info:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "user:info:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "user:info:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
}
]

View File

@ -1,5 +1,6 @@
import { Controller, Get, Inject } from '@midwayjs/decorator';
import { Context } from '@midwayjs/koa';
import * as packageJson from '../package.json';
/**
*
@ -12,7 +13,7 @@ export class WelcomeController {
@Get('/', { summary: '欢迎界面' })
public async welcome() {
await this.ctx.render('welcome', {
text: 'HELLO COOL-ADMIN v7.0 一个项目用COOL就够了',
text: `HELLO COOL-ADMIN v${packageJson.version} 一个项目用COOL就够了`,
});
}
}

View File

@ -8,9 +8,10 @@
"emitDecoratorMetadata": true,
"inlineSourceMap":true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedLocals": false,
"stripInternal": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"pretty": true,
"declaration": true,
"noImplicitAny": false,