This commit is contained in:
COOL 2025-02-07 18:49:39 +08:00
parent b8b40b4bf2
commit a618bd70b0
31 changed files with 139 additions and 648 deletions

View File

@ -33,254 +33,4 @@
│ │ └── service(服务,写业务逻辑)
│ │ └── config.ts(必须,模块的配置)
│ │ └── db.json(可选,初始化该模块的数据)
│ │ └── menu.json(可选,初始化该模块的菜单)
# 核心
- Controller
```ts
import { Get, Provide } from "@midwayjs/core";
import { CoolController, BaseController } from "@cool-midway/core";
import { BaseSysUserEntity } from "../../../base/entity/sys/user";
import { DemoAppGoodsEntity } from "../../entity/goods";
/**
* 商品
*/
@Provide()
@CoolController({
// 添加通用CRUD接口
api: ["add", "delete", "update", "info", "list", "page"],
// 设置表实体
entity: DemoAppGoodsEntity,
// 向表插入当前登录用户ID
insertParam: (ctx) => {
return {
// 获得当前登录的后台用户ID需要请求头传Authorization参数
userId: ctx.admin.userId,
};
},
// 操作crud之前做的事情 @cool-midway/core@3.2.14 新增
before: (ctx) => {
// 将前端的数据转JSON格式存数据库
const { data } = ctx.request.body;
ctx.request.body.data = JSON.stringify(data);
},
// info接口忽略价格字段
infoIgnoreProperty: ["a.price"],
// 分页查询配置
pageQueryOp: {
// 让title字段支持模糊查询
keyWordLikeFields: ["a.title"],
// 让type字段支持筛选请求筛选字段与表字段一致是情况
fieldEq: ["a.type"],
// 多表关联,请求筛选字段与表字段不一致的情况
fieldEq: [{ column: "a.id", requestParam: "id" }],
// 指定返回字段,注意多表查询这个是必要的,否则会出现重复字段的问题
select: ["a.*", "b.name", "a.name AS userName"],
// 4.x置为过时 改用 join 关联表用户表
leftJoin: [
{
entity: BaseSysUserEntity,
alias: "b",
condition: "a.userId = b.id",
},
],
// 4.x新增
join: [
{
entity: BaseSysUserEntity,
alias: "b",
condition: "a.userId = b.id",
type: "innerJoin",
},
],
// 4.x 新增 追加其他条件
extend: async (find: SelectQueryBuilder<DemoGoodsEntity>) => {
find.groupBy("a.id");
},
// 增加其他条件
where: async (ctx) => {
// 获取body参数
const { a } = ctx.request.body;
return [
// 价格大于90
["a.price > :price", { price: 90.0 }],
// 满足条件才会执行
["a.price > :price", { price: 90.0 }, "条件"],
// 多个条件一起
[
"(a.price = :price or a.userId = :userId)",
{ price: 90.0, userId: ctx.admin.userId },
],
];
},
// 可选添加排序默认按createTime Desc排序
addOrderBy: {
price: "desc",
},
},
})
export class DemoAppGoodsController extends BaseController {
/**
* 其他接口
*/
@Get("/other")
async other() {
return this.ok("hello, cool-admin!!!");
}
}
```
注意:
- CoolController的entityalias 为 "a";
- 如果是多表查询,必须设置 select 参数,否则会出现重复字段的错误,因为每个表都继承了 BaseEntity至少都有 id、createTime、updateTime 三个相同的字段;
- keyWordLikeFields、fieldEq等配置哪个字段都需要有对应的别名
- Entity
```ts
// BaseEntity的路径是固定不能修改
import { BaseEntity } from '../../base/entity/base';
import { Column, Entity, Index } from 'typeorm';
/**
* demo模块-用户信息
*/
// 表名必须包含模块固定格式模块_
@Entity('demo_user_info')
// DemoUserInfoEntity是模块+表名+Entity
export class DemoUserInfoEntity extends BaseEntity {
@Index()
@Column({ comment: '手机号', length: 11 })
phone: string;
@Index({ unique: true })
@Column({ comment: '身份证', length: 50 })
idCard: string;
// 生日只需要精确到哪一天所以type:'date',如果需要精确到时分秒,应为'datetime'
@Column({ comment: '生日', type: 'date' })
birthday: Date;
@Column({ comment: '状态', dict: ['禁用', '启用'], default: 1 })
status: number;
@Column({ comment: '分类', dict: ['普通', '会员', '超级会员'], default: 0, type: 'tinyint' })
type: number;
// 由于labels的类型是一个数组所以Column中的type类型必须得是'json'
@Column({ comment: '标签', nullable: true, type: 'json' })
labels: string[];
@Column({
comment: '余额',
type: 'decimal',
precision: 12,
scale: 2,
})
balance: number;
@Column({ comment: '备注', nullable: true })
remark: string;
@Column({ comment: '简介', type: 'text', nullable: true })
summary: string;
@Column({ comment: '省', length: 50 })
province: string;
@Column({ comment: '市', length: 50 })
city: string;
@Column({ comment: '区', length: 50 })
district: string;
@Column({ comment: '详细地址', length: 255 })
address: string;
}
```
注意:
- 禁止使用外键如ManyToOne、JoinColumn等
- comment需要简短如班级表的名称不要叫班级名称直接叫名称
- dict如果遇到可选项如状态、类型等需要配置
- BaseEntity的路径是固定不能修改
- Service
```ts
import { Init, Provide } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
/**
* 描述
*/
@Provide()
export class XxxService extends BaseService {
@InjectEntityModel(实体)
xxxEntity: Repository<实体>;
// 获得ctx
@Inject()
ctx;
@Init()
async init() {
await super.init();
this.setEntity(this.xxxEntity);
}
/**
* 其它方法
*/
async xxx() {}
}
```
- 自动路由
规则: /controller 文件夹下的文件夹名或者文件名/模块文件夹名/方法名
// 模块目录
├── modules
│ └── demo(模块名)
│ │ └── controller(api接口)
│ │ │ └── app(参数校验)
│ │ │ │ └── goods.ts(商品的controller)
│ │ │ └── pay.ts(支付的controller)
│ │ └── config.ts(必须,模块的配置)
│ │ └── init.sql(可选初始化该模块的sql)
生成的路由前缀为: /pay/demo/xxx(具体的方法)与/app/demo/goods/xxx(具体的方法)
- config.ts
```ts
import { ModuleConfig } from '@cool-midway/core';
/**
* 模块配置
*/
export default () => {
return {
// 模块名称
name: 'xxx',
// 模块描述
description: 'xxx',
// 中间件,只对本模块有效
middlewares: [],
// 中间件,全局有效
globalMiddlewares: [],
// 模块加载顺序默认为0值越大越优先加载
order: 0,
} as ModuleConfig;
};
```
# 其它
- 根据需要进行必要的关联表查询;
- 禁止出现import 但是没有使用的情况;
- 所有代码需有类级注释;
│ │ └── menu.json(可选,初始化该模块的菜单)

View File

@ -4,7 +4,7 @@
"description": "一个很酷的Ai快速开发框架",
"private": true,
"dependencies": {
"@cool-midway/core": "8.0.0-beta.1",
"@cool-midway/core": "file:///Users/ap/Documents/src/admin/midway-packages/core",
"@cool-midway/rpc": "8.0.0-beta.2",
"@cool-midway/task": "8.0.0-beta.2",
"@midwayjs/bootstrap": "^3.20.0",

43
pnpm-lock.yaml generated
View File

@ -9,8 +9,8 @@ importers:
.:
dependencies:
'@cool-midway/core':
specifier: 8.0.0-beta.1
version: 8.0.0-beta.1(debug@4.4.0)
specifier: file:///Users/ap/Documents/src/admin/midway-packages/core
version: file:../midway-packages/core(debug@4.4.0)
'@cool-midway/rpc':
specifier: 8.0.0-beta.2
version: 8.0.0-beta.2(debug@4.4.0)(encoding@0.1.13)
@ -62,9 +62,6 @@ importers:
cron:
specifier: ^3.5.0
version: 3.5.0
deasync:
specifier: ^0.1.30
version: 0.1.30
jsonwebtoken:
specifier: ^9.0.2
version: 9.0.2
@ -321,8 +318,8 @@ packages:
resolution: {integrity: sha512-Bl43bVCUm0V+w1wkfOicRfiHHZtaH1mQCp06baNapG86uC7OiXwMrml5+cvZD+mYSHdP07qUxtqkL8oUhrgAfg==}
engines: {node: '>=8.0.0'}
'@cool-midway/core@8.0.0-beta.1':
resolution: {integrity: sha512-3pNmtB2f3MrkBPCJlFiizWui1FqGxti8VBaBtOWJhg66tZeNdsSQsnG4/o1R2WfLHjlMkSMsCL0Jrl7HC7/Aig==}
'@cool-midway/core@file:../midway-packages/core':
resolution: {directory: ../midway-packages/core, type: directory}
hasBin: true
'@cool-midway/rpc@8.0.0-beta.2':
@ -1638,10 +1635,6 @@ packages:
dayjs@1.8.36:
resolution: {integrity: sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==}
deasync@0.1.30:
resolution: {integrity: sha512-OaAjvEQuQ9tJsKG4oHO9nV1UHTwb2Qc2+fadB0VeVtD0Z9wiG1XPGLJ4W3aLhAoQSYTaLROFRbd5X20Dkzf7MQ==}
engines: {node: '>=0.11.0'}
debug@3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
@ -2949,8 +2942,8 @@ packages:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
libphonenumber-js@1.11.18:
resolution: {integrity: sha512-okMm/MCoFrm1vByeVFLBdkFIXLSHy/AIK2AEGgY3eoicfWZeOZqv3GfhtQgICkzs/tqorAMm3a4GBg5qNCrqzg==}
libphonenumber-js@1.11.19:
resolution: {integrity: sha512-bW/Yp/9dod6fmyR+XqSUL1N5JE7QRxQ3KrBIbYS1FTv32e5i3SEtQVX+71CYNv8maWNSOgnlCoNp9X78f/cKiA==}
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
@ -3398,9 +3391,6 @@ packages:
node-abort-controller@3.1.1:
resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
node-addon-api@1.7.2:
resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==}
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
@ -3713,8 +3703,8 @@ packages:
engines: {node: '>=12.0.0'}
hasBin: true
possible-typed-array-names@1.0.0:
resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
possible-typed-array-names@1.1.0:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
prebuild-install@7.1.3:
@ -4900,7 +4890,7 @@ snapshots:
dependencies:
lockfile: 1.0.4
'@cool-midway/core@8.0.0-beta.1(debug@4.4.0)':
'@cool-midway/core@file:../midway-packages/core(debug@4.4.0)':
dependencies:
'@cool-midway/cache-manager-fs-hash': 7.0.0
'@midwayjs/cache-manager': 3.20.0
@ -5993,7 +5983,7 @@ snapshots:
available-typed-arrays@1.0.7:
dependencies:
possible-typed-array-names: 1.0.0
possible-typed-array-names: 1.1.0
aws-ssl-profiles@1.1.2: {}
@ -6304,7 +6294,7 @@ snapshots:
class-validator@0.14.1:
dependencies:
'@types/validator': 13.12.2
libphonenumber-js: 1.11.18
libphonenumber-js: 1.11.19
validator: 13.12.0
clean-stack@2.2.0:
@ -6504,11 +6494,6 @@ snapshots:
dayjs@1.8.36: {}
deasync@0.1.30:
dependencies:
bindings: 1.5.0
node-addon-api: 1.7.2
debug@3.2.7:
dependencies:
ms: 2.1.3
@ -8110,7 +8095,7 @@ snapshots:
prelude-ls: 1.2.1
type-check: 0.4.0
libphonenumber-js@1.11.18: {}
libphonenumber-js@1.11.19: {}
lines-and-columns@1.2.4: {}
@ -8505,8 +8490,6 @@ snapshots:
node-abort-controller@3.1.1: {}
node-addon-api@1.7.2: {}
node-addon-api@7.1.1: {}
node-fetch@2.7.0(encoding@0.1.13):
@ -8861,7 +8844,7 @@ snapshots:
- supports-color
- utf-8-validate
possible-typed-array-names@1.0.0: {}
possible-typed-array-names@1.1.0: {}
prebuild-install@7.1.3:
dependencies:

View File

@ -1,7 +1,6 @@
import { CoolConfig } from '@cool-midway/core';
import { MidwayConfig } from '@midwayjs/core';
import { pSqlitePath } from '../comm/path';
import { entities } from '../entities';
import { TenantSubscriber } from '../modules/base/db/tenant';
/**

View File

@ -3,6 +3,7 @@ import { MidwayConfig } from '@midwayjs/core';
import { entities } from '../entities';
import { pSqlitePath } from '../comm/path';
import { TenantSubscriber } from '../modules/base/db/tenant';
/**
* npm run prod
*/

View File

@ -1 +0,0 @@
2025-01-21T11:32:10.104Z

View File

@ -1,11 +0,0 @@
{
"COOL": "COOL",
"闪酷": "Flashy",
"法师": "Mage",
"战士": "Warrior",
"坦克": "Tank",
"刺客": "Assassin",
"射手": "Shooter",
"幻影刺客": "Phantom Assassin",
"你好": "Hello"
}

View File

@ -1,11 +0,0 @@
{
"COOL": "COOL",
"闪酷": "闪酷",
"法师": "法师",
"战士": "战士",
"坦克": "坦克",
"刺客": "刺客",
"射手": "射手",
"幻影刺客": "幻影刺客",
"你好": "你好"
}

View File

@ -1,11 +0,0 @@
{
"COOL": "酷",
"闪酷": "閃酷",
"法师": "法師",
"战士": "戰士",
"坦克": "坦克",
"刺客": "刺客",
"射手": "射手",
"幻影刺客": "幻影刺客",
"你好": "你好"
}

View File

@ -1,4 +0,0 @@
{
"品牌": "Brand",
"职业": "Job"
}

View File

@ -1,4 +0,0 @@
{
"品牌": "品牌",
"职业": "职业"
}

View File

@ -1,4 +0,0 @@
{
"品牌": "品牌",
"职业": "職業"
}

View File

@ -1 +0,0 @@
2025-01-21T11:32:17.870Z

View File

@ -1,47 +0,0 @@
{
"系统管理": "System",
"权限管理": "Auth",
"菜单列表": "Menu",
"新增": "Add",
"删除": "Del",
"查询": "Search",
"参数": "Param",
"编辑": "Edit",
"角色列表": "Role",
"修改": "Modify",
"用户列表": "User",
"部门列表": "Dept",
"新增部门": "Add Dept",
"更新部门": "Update Dept",
"删除部门": "Del Dept",
"部门排序": "Sort Dept",
"用户转移": "Transfer",
"参数配置": "Config",
"参数列表": "Param List",
"查看": "View",
"监控管理": "Monitor",
"请求日志": "Log",
"权限": "Auth",
"任务管理": "Task",
"任务列表": "Task List",
"框架教程": "Tutorial",
"文档官网": "Docs",
"crud 示例": "CRUD",
"通用": "Common",
"图片上传": "Upload",
"首页": "Home",
"数据管理": "Data",
"字典管理": "Dict",
"获得字典数据": "Get Dict",
"单个信息": "Single",
"列表查询": "List",
"分页查询": "Page",
"组权限": "Group",
"字典类型": "Dict Type",
"数据回收站": "Recycle",
"恢复数据": "Restore",
"文件管理": "File",
"用户管理": "User",
"扩展管理": "Extend",
"插件列表": "Plugin"
}

View File

@ -1,47 +0,0 @@
{
"系统管理": "系统管理",
"权限管理": "权限管理",
"菜单列表": "菜单列表",
"新增": "新增",
"删除": "删除",
"查询": "查询",
"参数": "参数",
"编辑": "编辑",
"角色列表": "角色列表",
"修改": "修改",
"用户列表": "用户列表",
"部门列表": "部门列表",
"新增部门": "新增部门",
"更新部门": "更新部门",
"删除部门": "删除部门",
"部门排序": "部门排序",
"用户转移": "用户转移",
"参数配置": "参数配置",
"参数列表": "参数列表",
"查看": "查看",
"监控管理": "监控管理",
"请求日志": "请求日志",
"权限": "权限",
"任务管理": "任务管理",
"任务列表": "任务列表",
"框架教程": "框架教程",
"文档官网": "文档官网",
"crud 示例": "crud 示例",
"通用": "通用",
"图片上传": "图片上传",
"首页": "首页",
"数据管理": "数据管理",
"字典管理": "字典管理",
"获得字典数据": "获得字典数据",
"单个信息": "单个信息",
"列表查询": "列表查询",
"分页查询": "分页查询",
"组权限": "组权限",
"字典类型": "字典类型",
"数据回收站": "数据回收站",
"恢复数据": "恢复数据",
"文件管理": "文件管理",
"用户管理": "用户管理",
"扩展管理": "扩展管理",
"插件列表": "插件列表"
}

View File

@ -1,47 +0,0 @@
{
"系统管理": "系統管理",
"权限管理": "權限管理",
"菜单列表": "選單列表",
"新增": "新增",
"删除": "刪除",
"查询": "查詢",
"参数": "參數",
"编辑": "編輯",
"角色列表": "角色列表",
"修改": "修改",
"用户列表": "用戶列表",
"部门列表": "部門列表",
"新增部门": "新增部門",
"更新部门": "更新部門",
"删除部门": "刪除部門",
"部门排序": "部門排序",
"用户转移": "用戶轉移",
"参数配置": "參數配置",
"参数列表": "參數列表",
"查看": "查看",
"监控管理": "監控管理",
"请求日志": "請求日誌",
"权限": "權限",
"任务管理": "任務管理",
"任务列表": "任務列表",
"框架教程": "框架教程",
"文档官网": "文件官網",
"crud 示例": "crud 示例",
"通用": "通用",
"图片上传": "圖片上傳",
"首页": "首頁",
"数据管理": "數據管理",
"字典管理": "字典管理",
"获得字典数据": "獲得字典數據",
"单个信息": "單個信息",
"列表查询": "列表查詢",
"分页查询": "分頁查詢",
"组权限": "組權限",
"字典类型": "字典類型",
"数据回收站": "數據回收站",
"恢复数据": "恢復數據",
"文件管理": "文件管理",
"用户管理": "用戶管理",
"扩展管理": "擴展管理",
"插件列表": "插件列表"
}

View File

@ -1 +0,0 @@
2025-01-21T11:32:17.869Z

View File

@ -1,27 +0,0 @@
{
"登录失效~": "Login expired~",
"登录失效或无权限访问~": "Login expired or no access~",
"账户或密码不正确~": "Incorrect account or password~",
"该用户未设置任何角色,无法登录~": "No role set, cannot login~",
"验证码不正确": "Incorrect code",
"代码结构不正确,请检查": "Invalid code structure, check",
"存在相同的keyName": "Duplicate keyName",
"非法操作~": "Illegal operation~",
"用户名已经存在~": "Username exists~",
"用户不存在": "User not found",
"原密码错误": "Wrong old password",
"非法的key值": "Invalid key",
"上传文件为空": "Empty upload",
"插件信息不完整": "Incomplete plugin info",
"插件key不能为plugin请更换其他key": "Plugin key cannot be 'plugin', change it",
"更新失败,参数错误或者手机号已存在": "Update failed, wrong params or phone exists",
"验证码错误": "Wrong code",
"图片验证码错误": "Wrong image code",
"获得手机号失败,请检查配置": "Failed to get phone, check config",
"token类型非refreshToken": "Token type not refreshToken",
"账号或密码错误": "Wrong account or password",
"发送过于频繁,请稍后再试": "Too frequent, try later",
"用户不存在或已被禁用": "User not found or disabled",
"登录失败,请重试": "Login failed, retry",
"获取手机号失败,请刷新重试": "Failed to get phone, refresh and retry"
}

View File

@ -1,27 +0,0 @@
{
"登录失效~": "登录失效~",
"登录失效或无权限访问~": "登录失效或无权限访问~",
"账户或密码不正确~": "账户或密码不正确~",
"该用户未设置任何角色,无法登录~": "该用户未设置任何角色,无法登录~",
"验证码不正确": "验证码不正确",
"代码结构不正确,请检查": "代码结构不正确,请检查",
"存在相同的keyName": "存在相同的keyName",
"非法操作~": "非法操作~",
"用户名已经存在~": "用户名已经存在~",
"用户不存在": "用户不存在",
"原密码错误": "原密码错误",
"非法的key值": "非法的key值",
"上传文件为空": "上传文件为空",
"插件信息不完整": "插件信息不完整",
"插件key不能为plugin请更换其他key": "插件key不能为plugin请更换其他key",
"更新失败,参数错误或者手机号已存在": "更新失败,参数错误或者手机号已存在",
"验证码错误": "验证码错误",
"图片验证码错误": "图片验证码错误",
"获得手机号失败,请检查配置": "获得手机号失败,请检查配置",
"token类型非refreshToken": "token类型非refreshToken",
"账号或密码错误": "账号或密码错误",
"发送过于频繁,请稍后再试": "发送过于频繁,请稍后再试",
"用户不存在或已被禁用": "用户不存在或已被禁用",
"登录失败,请重试": "登录失败,请重试",
"获取手机号失败,请刷新重试": "获取手机号失败,请刷新重试"
}

View File

@ -1,27 +0,0 @@
{
"登录失效~": "登入失效~",
"登录失效或无权限访问~": "登入失效或無權限訪問~",
"账户或密码不正确~": "帳號或密碼不正確~",
"该用户未设置任何角色,无法登录~": "該用戶未設置任何角色,無法登入~",
"验证码不正确": "驗證碼不正確",
"代码结构不正确,请检查": "代碼結構不正確,請檢查",
"存在相同的keyName": "存在相同的keyName",
"非法操作~": "非法操作~",
"用户名已经存在~": "用戶名已經存在~",
"用户不存在": "用戶不存在",
"原密码错误": "原密碼錯誤",
"非法的key值": "非法的key值",
"上传文件为空": "上傳文件為空",
"插件信息不完整": "插件信息不完整",
"插件key不能为plugin请更换其他key": "插件key不能為plugin請更換其他key",
"更新失败,参数错误或者手机号已存在": "更新失敗,參數錯誤或手機號已存在",
"验证码错误": "驗證碼錯誤",
"图片验证码错误": "圖片驗證碼錯誤",
"获得手机号失败,请检查配置": "獲取手機號失敗,請檢查配置",
"token类型非refreshToken": "token類型非refreshToken",
"账号或密码错误": "帳號或密碼錯誤",
"发送过于频繁,请稍后再试": "發送過於頻繁,請稍後再試",
"用户不存在或已被禁用": "用戶不存在或已被禁用",
"登录失败,请重试": "登入失敗,請重試",
"获取手机号失败,请刷新重试": "獲取手機號失敗,請刷新重試"
}

View File

@ -16,7 +16,7 @@ export default () => {
globalMiddlewares: [
BaseTranslateMiddleware,
BaseAuthorityMiddleware,
// BaseLogMiddleware,
BaseLogMiddleware,
],
// 模块加载顺序默认为0值越大越优先加载
order: 10,

View File

@ -1,12 +1,18 @@
import {
Index,
UpdateDateColumn,
CreateDateColumn,
PrimaryGeneratedColumn,
Column,
} from 'typeorm';
import { Index, PrimaryGeneratedColumn, Column } from 'typeorm';
import * as moment from 'moment';
import { CoolBaseEntity } from '@cool-midway/core';
const transformer = {
to(value) {
return value
? moment(value).format('YYYY-MM-DD HH:mm:ss')
: moment().format('YYYY-MM-DD HH:mm:ss');
},
from(value) {
return value;
},
};
/**
*
*/
@ -18,11 +24,19 @@ export abstract class BaseEntity extends CoolBaseEntity {
id: number;
@Index()
@CreateDateColumn({ comment: '创建时间' })
@Column({
comment: '创建时间',
type: 'varchar',
transformer,
})
createTime: Date;
@Index()
@UpdateDateColumn({ comment: '更新时间' })
@Column({
comment: '更新时间',
type: 'varchar',
transformer,
})
updateTime: Date;
@Index()

View File

@ -4,7 +4,7 @@
"router": "/sys",
"perms": null,
"type": 0,
"icon": "icon-system",
"icon": "icon-set",
"orderNum": 2,
"viewPath": null,
"keepAlive": true,
@ -834,20 +834,100 @@
"isShow": true,
"childMenus": [
{
"name": "后端插件",
"router": "/helper/plugins/serve",
"tenantId": null,
"name": "插件列表",
"router": "/helper/plugins",
"perms": null,
"type": 1,
"icon": "icon-component",
"orderNum": 2,
"viewPath": "modules/helper/views/plugins/serve.vue",
"icon": "icon-list",
"orderNum": 1,
"viewPath": "modules/helper/views/plugins.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "权限",
"tenantId": null,
"name": "删除",
"router": null,
"perms": "plugin:info:install,plugin:info:delete,plugin:info:update,plugin:info:page,plugin:info:info",
"perms": "plugin:info:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"tenantId": null,
"name": "分页查询",
"router": null,
"perms": "plugin:info:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"tenantId": null,
"name": "单个信息",
"router": null,
"perms": "plugin:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"tenantId": null,
"name": "安装插件",
"router": null,
"perms": "plugin:info:install",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"tenantId": null,
"name": "修改",
"router": null,
"perms": "plugin:info:update",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"tenantId": null,
"name": "列表查询",
"router": null,
"perms": "plugin:info:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"tenantId": null,
"name": "新增",
"router": null,
"perms": "plugin:info:add",
"type": 2,
"icon": null,
"orderNum": 0,
@ -857,18 +937,6 @@
"childMenus": []
}
]
},
{
"name": "前端插件",
"router": "/helper/plugins/vue",
"perms": null,
"type": 1,
"icon": "icon-vue",
"orderNum": 1,
"viewPath": "modules/helper/views/plugins/vue.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}

View File

@ -58,7 +58,7 @@ export class BaseAuthorityMiddleware
ctx.admin.tenantId = 1;
if (ctx.admin.isRefresh) {
ctx.status = 401;
throw new CoolCommException('登录失效~');
throw new CoolCommException('登录失效~', ctx.status);
}
} catch (error) {}
// 使用matchUrl方法来检查URL是否应该被忽略
@ -78,14 +78,12 @@ export class BaseAuthorityMiddleware
`admin:passwordVersion:${ctx.admin.userId}`
);
if (passwordV != ctx.admin.passwordVersion) {
ctx.status = 401;
throw new CoolCommException('登录失效~');
throw new CoolCommException('登录失效~', 401);
}
// 超管拥有所有权限
if (ctx.admin.username == 'admin' && !ctx.admin.isRefresh) {
if (rToken !== token && this.jwtConfig.jwt.sso) {
ctx.status = 401;
throw new CoolCommException('登录失效~');
throw new CoolCommException('登录失效~', 401);
} else {
await next();
return;
@ -102,12 +100,10 @@ export class BaseAuthorityMiddleware
}
// 如果传的token是refreshToken则校验失败
if (ctx.admin.isRefresh) {
ctx.status = 401;
throw new CoolCommException('登录失效~');
throw new CoolCommException('登录失效~', 401);
}
if (!rToken) {
ctx.status = 401;
throw new CoolCommException('登录失效或无权限访问~');
throw new CoolCommException('登录失效或无权限访问~', 401);
}
if (rToken !== token && this.jwtConfig.jwt.sso) {
statusCode = 401;
@ -130,8 +126,7 @@ export class BaseAuthorityMiddleware
statusCode = 401;
}
if (statusCode > 200) {
ctx.status = statusCode;
throw new CoolCommException('登录失效或无权限访问~');
throw new CoolCommException('登录失效或无权限访问~', statusCode);
}
}
await next();

View File

@ -39,7 +39,7 @@ export class BaseTranslateMiddleware
// 处理翻译消息
if (error.name == 'CoolCommException') {
if (language && error.message && error.message !== 'success') {
ctx.status = 200;
ctx.status = error.statusCode || 200;
ctx.body = {
code: RESCODE.COMMFAIL,
message: await this.baseTranslateService.translate(

View File

@ -1,8 +1,7 @@
import { CoolController, BaseController } from '@cool-midway/core';
import { DemoGoodsEntity } from '../../entity/goods';
import { Get, Inject } from '@midwayjs/core';
import { DemoGoodsService } from '../../service/goods';
import { UserInfoEntity } from '../../../user/entity/info';
import { DemoGoodsService } from '../../service/goods';
/**
* -
@ -10,6 +9,7 @@ import { UserInfoEntity } from '../../../user/entity/info';
@CoolController({
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
entity: DemoGoodsEntity,
service: DemoGoodsService,
pageQueryOp: {
keyWordLikeFields: ['a.description'],
fieldEq: ['a.status'],
@ -24,13 +24,4 @@ import { UserInfoEntity } from '../../../user/entity/info';
],
},
})
export class AdminDemoGoodsController extends BaseController {
@Inject()
demoGoodsService: DemoGoodsService;
@Get('/test', { summary: '测试' })
async test() {
await this.demoGoodsService.test();
return this.ok('test');
}
}
export class AdminDemoGoodsController extends BaseController {}

View File

@ -1,6 +1,6 @@
import { DemoGoodsService } from '../../service/goods';
import { DemoGoodsEntity } from '../../entity/goods';
import { Body, Config, Get, Inject, Post, Provide } from '@midwayjs/core';
import { Body, Inject, Post } from '@midwayjs/core';
import { CoolController, BaseController } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
@ -32,10 +32,4 @@ export class OpenDemoGoodsController extends BaseController {
async entityPage(@Body() query) {
return this.ok(await this.demoGoodsService.entityPage(query));
}
@Get('/test', { summary: '测试' })
async test() {
await this.demoGoodsService.test();
return this.ok('test');
}
}

View File

@ -3,7 +3,6 @@ import { Inject, Provide } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { noTenant } from '../../base/db/tenant';
/**
*
@ -41,14 +40,4 @@ export class DemoGoodsService extends BaseService {
const find = this.demoGoodsEntity.createQueryBuilder();
return this.entityRenderPage(find, query);
}
async test() {
const a = await this.demoGoodsEntity.createQueryBuilder().getMany();
await noTenant(this.ctx, async () => {
const b = await this.demoGoodsEntity.createQueryBuilder().getMany();
console.log('b');
});
const c = await this.demoGoodsEntity.createQueryBuilder().getMany();
console.log(a);
}
}

View File

@ -3,7 +3,6 @@ import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { DemoGoodsEntity } from '../entity/goods';
import { UserInfoEntity } from '../../user/entity/info';
import { noTenant } from '../../base/db/tenant';
/**

View File

@ -1,6 +1,5 @@
import { CoolController, BaseController } from '@cool-midway/core';
import { UserInfoEntity } from '../../entity/info';
import { DemoGoodsEntity } from '../../../demo/entity/goods';
/**
*
@ -10,16 +9,7 @@ import { DemoGoodsEntity } from '../../../demo/entity/goods';
entity: UserInfoEntity,
pageQueryOp: {
fieldEq: ['a.status', 'a.gender', 'a.loginType'],
fieldLike: ['b.title'],
keyWordLikeFields: ['a.nickName', 'a.phone'],
select: ['a.*', 'b.title as goodsName'],
join: [
{
entity: DemoGoodsEntity,
alias: 'b',
condition: 'a.id = b.id',
},
],
},
})
export class AdminUserInfoController extends BaseController {}

View File

@ -29,21 +29,9 @@ export class UserInfoEntity extends BaseEntity {
@Column({ comment: '登录方式', dict: ['小程序', '公众号', 'H5'], default: 0 })
loginType: number;
@Column({ comment: '来源', dict: 'sourceType', default: 0 })
source: number;
@Column({ comment: '密码', nullable: true })
password: string;
@Column({ comment: '介绍', type: 'text', nullable: true })
description: string;
@Column({
comment: '余额',
type: 'decimal',
precision: 10,
scale: 2,
default: 0,
})
balance: number;
}