From 20feacea12d43386540db6a600f391d786be4014 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Sun, 16 Jun 2024 00:20:02 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E5=A2=9E=E5=8A=A0=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=EF=BC=8C=E5=8F=AF=E4=BB=A5=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E8=87=AA=E5=8A=A9=E6=B3=A8=E5=86=8C=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../certd-client/src/api/modules/api.basic.ts | 13 ++ .../src/router/source/modules/sys.ts | 10 ++ .../src/store/modules/settings.ts | 18 ++- .../src/views/certd/settings/api.ts | 2 +- .../src/views/framework/login/index.vue | 8 +- .../permission/fs-permission-tree.vue | 35 ++++- .../views/sys/authority/permission/index.vue | 6 +- .../src/views/sys/settings/api.ts | 38 +++++ .../src/views/sys/settings/index.vue | 65 ++++++++ .../db/migration/v10004__settings.sql | 20 +++ .../basic/controller/settings-controller.ts | 34 +++++ .../modules/basic/service/email-service.ts | 4 +- .../login/controller/register-controller.ts | 9 ++ .../controller/user-settings-controller.ts} | 26 ++-- .../entity/user-settings.ts} | 4 +- .../service/user-settings-service.ts} | 14 +- .../controller/sys-settings-controller.ts | 80 ++++++++++ .../src/modules/system/entity/sys-settings.ts | 33 ++++ .../system/service/sys-settings-service.ts | 143 ++++++++++++++++++ 19 files changed, 522 insertions(+), 40 deletions(-) create mode 100644 packages/ui/certd-client/src/api/modules/api.basic.ts create mode 100644 packages/ui/certd-client/src/views/sys/settings/api.ts create mode 100644 packages/ui/certd-client/src/views/sys/settings/index.vue create mode 100644 packages/ui/certd-server/db/migration/v10004__settings.sql create mode 100644 packages/ui/certd-server/src/modules/basic/controller/settings-controller.ts rename packages/ui/certd-server/src/modules/{system/controller/settings-controller.ts => mine/controller/user-settings-controller.ts} (73%) rename packages/ui/certd-server/src/modules/{system/entity/settings.ts => mine/entity/user-settings.ts} (91%) rename packages/ui/certd-server/src/modules/{system/service/settings-service.ts => mine/service/user-settings-service.ts} (75%) create mode 100644 packages/ui/certd-server/src/modules/system/controller/sys-settings-controller.ts create mode 100644 packages/ui/certd-server/src/modules/system/entity/sys-settings.ts create mode 100644 packages/ui/certd-server/src/modules/system/service/sys-settings-service.ts diff --git a/packages/ui/certd-client/src/api/modules/api.basic.ts b/packages/ui/certd-client/src/api/modules/api.basic.ts new file mode 100644 index 00000000..9ace67f6 --- /dev/null +++ b/packages/ui/certd-client/src/api/modules/api.basic.ts @@ -0,0 +1,13 @@ +import { request } from "../service"; + +export type SysPublicSetting = { + registerEnabled:boolean +} + + +export async function getSysPublicSettings(): Promise { + return await request({ + url: "/basic/settings/public", + method: "get" + }); +} diff --git a/packages/ui/certd-client/src/router/source/modules/sys.ts b/packages/ui/certd-client/src/router/source/modules/sys.ts index a2d75127..29261481 100644 --- a/packages/ui/certd-client/src/router/source/modules/sys.ts +++ b/packages/ui/certd-client/src/router/source/modules/sys.ts @@ -55,6 +55,16 @@ export const sysResources = [ }, path: "/sys/authority/user", component: "/sys/authority/user/index.vue" + }, + { + title: "系统设置", + name: "settings", + meta: { + icon: "ion:settings-outline", + permission: "sys:settings:view" + }, + path: "/sys/settings", + component: "/sys/settings/index.vue" } ] } diff --git a/packages/ui/certd-client/src/store/modules/settings.ts b/packages/ui/certd-client/src/store/modules/settings.ts index 0b0b39c3..932401b5 100644 --- a/packages/ui/certd-client/src/store/modules/settings.ts +++ b/packages/ui/certd-client/src/store/modules/settings.ts @@ -1,6 +1,9 @@ import { defineStore } from "pinia"; // @ts-ignore import { LocalStorage } from "/src/utils/util.storage"; +import { SysPublicSetting } from "/@/api/modules/api.basic"; +import * as basicApi from '/@/api/modules/api.basic' +import _ from "lodash-es"; // import { replaceStyleVariables } from "vite-plugin-theme/es/client"; // import { getThemeColors, generateColors } from "/src/../build/theme-colors"; @@ -23,8 +26,10 @@ import { LocalStorage } from "/src/utils/util.storage"; // }); // } + interface SettingState { theme: any; + sysPublic?: SysPublicSetting } const SETTING_THEME_KEY = "SETTING_THEME"; @@ -32,14 +37,24 @@ export const useSettingStore = defineStore({ id: "app.setting", state: (): SettingState => ({ // user info - theme: null + theme: null, + sysPublic: { + registerEnabled: false + } }), getters: { getTheme(): any { return this.theme || LocalStorage.get(SETTING_THEME_KEY) || {}; + }, + getSysPublic():SysPublicSetting{ + return this.sysPublic } }, actions: { + async loadSysSettings(){ + const settings = await basicApi.getSysPublicSettings() + _.merge(this.sysPublic,settings) + }, persistTheme() { LocalStorage.set(SETTING_THEME_KEY, this.getTheme); }, @@ -58,6 +73,7 @@ export const useSettingStore = defineStore({ }, async init() { await this.setTheme(this.getTheme); + await this.loadSysSettings() } } }); diff --git a/packages/ui/certd-client/src/views/certd/settings/api.ts b/packages/ui/certd-client/src/views/certd/settings/api.ts index f56f5253..fd29f071 100644 --- a/packages/ui/certd-client/src/views/certd/settings/api.ts +++ b/packages/ui/certd-client/src/views/certd/settings/api.ts @@ -1,5 +1,5 @@ import { request } from "/@/api/service"; -const apiPrefix = "/sys/settings"; +const apiPrefix = "/user/settings"; export const SettingKeys = { Email: "email" diff --git a/packages/ui/certd-client/src/views/framework/login/index.vue b/packages/ui/certd-client/src/views/framework/login/index.vue index fd5f1a2d..bce6ec57 100644 --- a/packages/ui/certd-client/src/views/framework/login/index.vue +++ b/packages/ui/certd-client/src/views/framework/login/index.vue @@ -66,7 +66,7 @@ @@ -74,11 +74,13 @@ + + diff --git a/packages/ui/certd-server/db/migration/v10004__settings.sql b/packages/ui/certd-server/db/migration/v10004__settings.sql new file mode 100644 index 00000000..1c83a697 --- /dev/null +++ b/packages/ui/certd-server/db/migration/v10004__settings.sql @@ -0,0 +1,20 @@ +ALTER TABLE "sys_settings" RENAME TO "user_settings"; + +CREATE TABLE "sys_settings" ( + "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, + "key" varchar(100) NOT NULL, + "title" varchar(100) NOT NULL, + "setting" varchar(1024), + "access" varchar(100) NOT NULL, + "create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP), + "update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP) +); + + +INSERT INTO sys_permission (title, permission, parent_id, sort, create_time, update_time) VALUES ('系统设置', 'sys:settings', (SELECT id FROM sys_permission WHERE permission = 'sys'), 1, 1, 1); +INSERT INTO sys_role_permission (role_id, permission_id) VALUES (1, last_insert_rowid()); +INSERT INTO sys_permission (title, permission, parent_id, sort, create_time, update_time) VALUES ('查看', 'sys:settings:view', (SELECT id FROM sys_permission WHERE permission = 'sys:settings'), 1, 1, 1); +INSERT INTO sys_role_permission (role_id, permission_id) VALUES (1, last_insert_rowid()); +INSERT INTO sys_permission (title, permission, parent_id, sort, create_time, update_time) VALUES ('编辑', 'sys:settings:edit', (SELECT id FROM sys_permission WHERE permission = 'sys:settings'), 1, 1, 1); +INSERT INTO sys_role_permission (role_id, permission_id) VALUES (1, last_insert_rowid()); + diff --git a/packages/ui/certd-server/src/modules/basic/controller/settings-controller.ts b/packages/ui/certd-server/src/modules/basic/controller/settings-controller.ts new file mode 100644 index 00000000..380c73a5 --- /dev/null +++ b/packages/ui/certd-server/src/modules/basic/controller/settings-controller.ts @@ -0,0 +1,34 @@ +import { Rule, RuleType } from '@midwayjs/validate'; +import { Controller, Get, Inject, Provide } from '@midwayjs/decorator'; +import { BaseController } from '../../../basic/base-controller'; +import { Constants } from '../../../basic/constants'; +import { SysSettingsService } from '../../system/service/sys-settings-service'; + +export class SmsCodeReq { + @Rule(RuleType.number().required()) + phoneCode: number; + + @Rule(RuleType.string().required()) + mobile: string; + + @Rule(RuleType.string().required().max(10)) + randomStr: string; + + @Rule(RuleType.number().required().max(4)) + imgCode: string; +} + +/** + */ +@Provide() +@Controller('/api/basic/settings') +export class BasicSettingsController extends BaseController { + @Inject() + sysSettingsService: SysSettingsService; + + @Get('/public', { summary: Constants.per.guest }) + public async getSysPublic() { + const settings = await this.sysSettingsService.readPublicSettings(); + return this.ok(settings); + } +} diff --git a/packages/ui/certd-server/src/modules/basic/service/email-service.ts b/packages/ui/certd-server/src/modules/basic/service/email-service.ts index 815ff8f3..5aeb1b6e 100644 --- a/packages/ui/certd-server/src/modules/basic/service/email-service.ts +++ b/packages/ui/certd-server/src/modules/basic/service/email-service.ts @@ -2,9 +2,9 @@ import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; import type { EmailSend } from '@certd/pipeline'; import { IEmailService } from '@certd/pipeline'; import nodemailer from 'nodemailer'; -import { SettingsService } from '../../system/service/settings-service'; import type SMTPConnection from 'nodemailer/lib/smtp-connection'; import { logger } from '../../../utils/logger'; +import { UserSettingsService } from '../../mine/service/user-settings-service'; export type EmailConfig = { host: string; @@ -24,7 +24,7 @@ export type EmailConfig = { @Scope(ScopeEnum.Singleton) export class EmailService implements IEmailService { @Inject() - settingsService: SettingsService; + settingsService: UserSettingsService; /** */ diff --git a/packages/ui/certd-server/src/modules/login/controller/register-controller.ts b/packages/ui/certd-server/src/modules/login/controller/register-controller.ts index d95485e4..5a26f4aa 100644 --- a/packages/ui/certd-server/src/modules/login/controller/register-controller.ts +++ b/packages/ui/certd-server/src/modules/login/controller/register-controller.ts @@ -10,6 +10,7 @@ import { BaseController } from '../../../basic/base-controller'; import { Constants } from '../../../basic/constants'; import { UserService } from '../../authority/service/user-service'; import { UserEntity } from '../../authority/entity/user'; +import { SysSettingsService } from '../../system/service/sys-settings-service'; /** */ @@ -18,11 +19,19 @@ import { UserEntity } from '../../authority/entity/user'; export class RegisterController extends BaseController { @Inject() userService: UserService; + + @Inject() + sysSettingsService: SysSettingsService; + @Post('/register', { summary: Constants.per.guest }) public async register( @Body(ALL) user: UserEntity ) { + const sysPublicSettings = await this.sysSettingsService.getPublicSettings(); + if (sysPublicSettings.registerEnabled === false) { + throw new Error('当前站点已禁止自助注册功能'); + } const newUser = await this.userService.register(user); return this.ok(newUser); } diff --git a/packages/ui/certd-server/src/modules/system/controller/settings-controller.ts b/packages/ui/certd-server/src/modules/mine/controller/user-settings-controller.ts similarity index 73% rename from packages/ui/certd-server/src/modules/system/controller/settings-controller.ts rename to packages/ui/certd-server/src/modules/mine/controller/user-settings-controller.ts index 7f28225d..6c3a8b51 100644 --- a/packages/ui/certd-server/src/modules/system/controller/settings-controller.ts +++ b/packages/ui/certd-server/src/modules/mine/controller/user-settings-controller.ts @@ -1,24 +1,16 @@ -import { - ALL, - Body, - Controller, - Inject, - Post, - Provide, - Query, -} from '@midwayjs/decorator'; -import { CrudController } from '../../../basic/crud-controller'; -import { SettingsService } from '../service/settings-service'; -import { SettingsEntity } from '../entity/settings'; -import { Constants } from '../../../basic/constants'; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/decorator"; +import { CrudController } from "../../../basic/crud-controller"; +import { Constants } from "../../../basic/constants"; +import { UserSettingsService } from "../service/user-settings-service"; +import { UserSettingsEntity } from "../entity/user-settings"; /** */ @Provide() -@Controller('/api/sys/settings') -export class SettingsController extends CrudController { +@Controller('/api/user/settings') +export class UserSettingsController extends CrudController { @Inject() - service: SettingsService; + service: UserSettingsService; getService() { return this.service; @@ -61,7 +53,7 @@ export class SettingsController extends CrudController { } @Post('/save', { summary: Constants.per.authOnly }) - async save(@Body(ALL) bean: SettingsEntity) { + async save(@Body(ALL) bean: UserSettingsEntity) { bean.userId = this.ctx.user.id; await this.service.save(bean); return this.ok({}); diff --git a/packages/ui/certd-server/src/modules/system/entity/settings.ts b/packages/ui/certd-server/src/modules/mine/entity/user-settings.ts similarity index 91% rename from packages/ui/certd-server/src/modules/system/entity/settings.ts rename to packages/ui/certd-server/src/modules/mine/entity/user-settings.ts index 70829c94..84cd1f2a 100644 --- a/packages/ui/certd-server/src/modules/system/entity/settings.ts +++ b/packages/ui/certd-server/src/modules/mine/entity/user-settings.ts @@ -2,8 +2,8 @@ import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; /** */ -@Entity('sys_settings') -export class SettingsEntity { +@Entity('user_settings') +export class UserSettingsEntity { @PrimaryGeneratedColumn() id: number; @Column({ name: 'user_id', comment: '用户id' }) diff --git a/packages/ui/certd-server/src/modules/system/service/settings-service.ts b/packages/ui/certd-server/src/modules/mine/service/user-settings-service.ts similarity index 75% rename from packages/ui/certd-server/src/modules/system/service/settings-service.ts rename to packages/ui/certd-server/src/modules/mine/service/user-settings-service.ts index f2b76ffb..a19c4da0 100644 --- a/packages/ui/certd-server/src/modules/system/service/settings-service.ts +++ b/packages/ui/certd-server/src/modules/mine/service/user-settings-service.ts @@ -2,22 +2,22 @@ import { Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; import { InjectEntityModel } from '@midwayjs/typeorm'; import { Repository } from 'typeorm'; import { BaseService } from '../../../basic/base-service'; -import { SettingsEntity } from '../entity/settings'; +import { UserSettingsEntity } from '../entity/user-settings'; /** * 授权 */ @Provide() @Scope(ScopeEnum.Singleton) -export class SettingsService extends BaseService { - @InjectEntityModel(SettingsEntity) - repository: Repository; +export class UserSettingsService extends BaseService { + @InjectEntityModel(UserSettingsEntity) + repository: Repository; getRepository() { return this.repository; } - async getById(id: any): Promise { + async getById(id: any): Promise { const entity = await this.info(id); if (!entity) { return null; @@ -30,7 +30,7 @@ export class SettingsService extends BaseService { }; } - async getByKey(key: string, userId: number): Promise { + async getByKey(key: string, userId: number): Promise { if (!key || !userId) { return null; } @@ -50,7 +50,7 @@ export class SettingsService extends BaseService { return JSON.parse(entity.setting); } - async save(bean: SettingsEntity) { + async save(bean: UserSettingsEntity) { const entity = await this.repository.findOne({ where: { key: bean.key, diff --git a/packages/ui/certd-server/src/modules/system/controller/sys-settings-controller.ts b/packages/ui/certd-server/src/modules/system/controller/sys-settings-controller.ts new file mode 100644 index 00000000..00800234 --- /dev/null +++ b/packages/ui/certd-server/src/modules/system/controller/sys-settings-controller.ts @@ -0,0 +1,80 @@ +import { + ALL, + Body, + Controller, + Inject, + Post, + Provide, + Query, +} from '@midwayjs/decorator'; +import { CrudController } from '../../../basic/crud-controller'; +import { SysSettingsService } from '../service/sys-settings-service'; +import { SysSettingsEntity } from '../entity/sys-settings'; + +/** + */ +@Provide() +@Controller('/api/sys/settings') +export class SysSettingsController extends CrudController { + @Inject() + service: SysSettingsService; + + getService() { + return this.service; + } + + @Post('/page', { summary: 'sys:settings:view' }) + async page(@Body(ALL) body) { + body.query = body.query ?? {}; + body.query.userId = this.ctx.user.id; + return super.page(body); + } + + @Post('/list', { summary: 'sys:settings:view' }) + async list(@Body(ALL) body) { + body.userId = this.ctx.user.id; + return super.list(body); + } + + @Post('/add', { summary: 'sys:settings:edit' }) + async add(@Body(ALL) bean) { + bean.userId = this.ctx.user.id; + return super.add(bean); + } + + @Post('/update', { summary: 'sys:settings:edit' }) + async update(@Body(ALL) bean) { + await this.service.checkUserId(bean.id, this.ctx.user.id); + return super.update(bean); + } + @Post('/info', { summary: 'sys:settings:view' }) + async info(@Query('id') id) { + await this.service.checkUserId(id, this.ctx.user.id); + return super.info(id); + } + + @Post('/delete', { summary: 'sys:settings:edit' }) + async delete(@Query('id') id) { + await this.service.checkUserId(id, this.ctx.user.id); + return super.delete(id); + } + + @Post('/save', { summary: 'sys:settings:edit' }) + async save(@Body(ALL) bean: SysSettingsEntity) { + await this.service.save(bean); + return this.ok({}); + } + + @Post('/get', { summary: 'sys:settings:view' }) + async get(@Query('key') key: string) { + const entity = await this.service.getByKey(key); + return this.ok(entity); + } + + // savePublicSettings + @Post('/savePublicSettings', { summary: 'sys:settings:edit' }) + async savePublicSettings(@Body(ALL) body) { + await this.service.savePublicSettings(body); + return this.ok({}); + } +} diff --git a/packages/ui/certd-server/src/modules/system/entity/sys-settings.ts b/packages/ui/certd-server/src/modules/system/entity/sys-settings.ts new file mode 100644 index 00000000..9c713981 --- /dev/null +++ b/packages/ui/certd-server/src/modules/system/entity/sys-settings.ts @@ -0,0 +1,33 @@ +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; + +/** + */ +@Entity('sys_settings') +export class SysSettingsEntity { + @PrimaryGeneratedColumn() + id: number; + @Column({ comment: 'key', length: 100 }) + key: string; + @Column({ comment: '名称', length: 100 }) + title: string; + + @Column({ name: 'setting', comment: '设置', length: 1024, nullable: true }) + setting: string; + + // public 公开读,私有写, private 私有读,私有写 + @Column({ name: 'access', comment: '访问权限' }) + access: string; + + @Column({ + name: 'create_time', + comment: '创建时间', + default: () => 'CURRENT_TIMESTAMP', + }) + createTime: Date; + @Column({ + name: 'update_time', + comment: '修改时间', + default: () => 'CURRENT_TIMESTAMP', + }) + updateTime: Date; +} diff --git a/packages/ui/certd-server/src/modules/system/service/sys-settings-service.ts b/packages/ui/certd-server/src/modules/system/service/sys-settings-service.ts new file mode 100644 index 00000000..fa521e9c --- /dev/null +++ b/packages/ui/certd-server/src/modules/system/service/sys-settings-service.ts @@ -0,0 +1,143 @@ +import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; +import { InjectEntityModel } from '@midwayjs/typeorm'; +import { Repository } from 'typeorm'; +import { BaseService } from '../../../basic/base-service'; +import { SysSettingsEntity } from '../entity/sys-settings'; +import { CacheManager } from '@midwayjs/cache'; + +const SYS_PUBLIC_KEY = 'sys.public'; +const SYS_PRIVATE_KEY = 'sys.private'; +const CACHE_SYS_PUBLIC_KEY = `settings.${SYS_PUBLIC_KEY}`; +const CACHE_SYS_PRIVATE_KEY = `settings.${SYS_PRIVATE_KEY}`; +export type SysPublicSettings = { + registerEnabled: boolean; +}; + +export type SysPrivateSettings = NonNullable; + +/** + * 设置 + */ +@Provide() +@Scope(ScopeEnum.Singleton) +export class SysSettingsService extends BaseService { + @InjectEntityModel(SysSettingsEntity) + repository: Repository; + + @Inject() + cache: CacheManager; // 依赖注入CacheManager + + getRepository() { + return this.repository; + } + + async getById(id: any): Promise { + const entity = await this.info(id); + if (!entity) { + return null; + } + const setting = JSON.parse(entity.setting); + return { + id: entity.id, + ...setting, + }; + } + + async getByKey(key: string): Promise { + if (!key) { + return null; + } + return await this.repository.findOne({ + where: { + key, + }, + }); + } + + async getSettingByKey(key: string): Promise { + const entity = await this.getByKey(key); + if (!entity) { + return null; + } + return JSON.parse(entity.setting); + } + + async save(bean: SysSettingsEntity) { + const entity = await this.repository.findOne({ + where: { + key: bean.key, + }, + }); + if (entity) { + entity.setting = bean.setting; + await this.repository.save(entity); + } else { + bean.title = bean.key; + await this.repository.save(bean); + } + } + + async getPublicSettings(): Promise { + const key = CACHE_SYS_PUBLIC_KEY; + let settings: SysPublicSettings = await this.cache.get(key); + if (settings == null) { + settings = await this.readPublicSettings(); + await this.cache.set(key, settings); + } + return settings; + } + + async readPublicSettings(): Promise { + const key = SYS_PUBLIC_KEY; + const entity = await this.getByKey(key); + if (!entity) { + return { + registerEnabled: false, + }; + } + return JSON.parse(entity.setting); + } + + async savePublicSettings(bean: SysPublicSettings) { + const key = SYS_PUBLIC_KEY; + const entity = await this.getByKey(key); + if (entity) { + entity.setting = JSON.stringify(bean); + await this.repository.save(entity); + } else { + const newEntity = new SysSettingsEntity(); + newEntity.key = key; + newEntity.title = '系统公共设置'; + newEntity.setting = JSON.stringify(bean); + newEntity.access = 'public'; + await this.repository.save(newEntity); + } + await this.cache.del(CACHE_SYS_PRIVATE_KEY); + } + + async readPrivateSettings(): Promise { + const key = SYS_PRIVATE_KEY; + const entity = await this.getByKey(key); + if (!entity) { + return {}; + } + return JSON.parse(entity.setting); + } + + async savePrivateSettings(bean: SysPrivateSettings) { + const key = SYS_PRIVATE_KEY; + const entity = await this.getByKey(key); + if (entity) { + entity.setting = JSON.stringify(bean); + await this.repository.save(entity); + } else { + const newEntity = new SysSettingsEntity(); + newEntity.key = key; + newEntity.title = '系统私有设置'; + newEntity.setting = JSON.stringify(bean); + newEntity.access = 'private'; + await this.repository.save(newEntity); + } + await this.cache.del(CACHE_SYS_PRIVATE_KEY); + } +}