mirror of https://github.com/certd/certd
perf: 增加系统设置,可以关闭自助注册功能
parent
575bf2b73b
commit
20feacea12
|
@ -0,0 +1,13 @@
|
||||||
|
import { request } from "../service";
|
||||||
|
|
||||||
|
export type SysPublicSetting = {
|
||||||
|
registerEnabled:boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function getSysPublicSettings(): Promise<SysPublicSetting> {
|
||||||
|
return await request({
|
||||||
|
url: "/basic/settings/public",
|
||||||
|
method: "get"
|
||||||
|
});
|
||||||
|
}
|
|
@ -55,6 +55,16 @@ export const sysResources = [
|
||||||
},
|
},
|
||||||
path: "/sys/authority/user",
|
path: "/sys/authority/user",
|
||||||
component: "/sys/authority/user/index.vue"
|
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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { LocalStorage } from "/src/utils/util.storage";
|
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 { replaceStyleVariables } from "vite-plugin-theme/es/client";
|
||||||
|
|
||||||
// import { getThemeColors, generateColors } from "/src/../build/theme-colors";
|
// import { getThemeColors, generateColors } from "/src/../build/theme-colors";
|
||||||
|
@ -23,8 +26,10 @@ import { LocalStorage } from "/src/utils/util.storage";
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
interface SettingState {
|
interface SettingState {
|
||||||
theme: any;
|
theme: any;
|
||||||
|
sysPublic?: SysPublicSetting
|
||||||
}
|
}
|
||||||
|
|
||||||
const SETTING_THEME_KEY = "SETTING_THEME";
|
const SETTING_THEME_KEY = "SETTING_THEME";
|
||||||
|
@ -32,14 +37,24 @@ export const useSettingStore = defineStore({
|
||||||
id: "app.setting",
|
id: "app.setting",
|
||||||
state: (): SettingState => ({
|
state: (): SettingState => ({
|
||||||
// user info
|
// user info
|
||||||
theme: null
|
theme: null,
|
||||||
|
sysPublic: {
|
||||||
|
registerEnabled: false
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
getTheme(): any {
|
getTheme(): any {
|
||||||
return this.theme || LocalStorage.get(SETTING_THEME_KEY) || {};
|
return this.theme || LocalStorage.get(SETTING_THEME_KEY) || {};
|
||||||
|
},
|
||||||
|
getSysPublic():SysPublicSetting{
|
||||||
|
return this.sysPublic
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
async loadSysSettings(){
|
||||||
|
const settings = await basicApi.getSysPublicSettings()
|
||||||
|
_.merge(this.sysPublic,settings)
|
||||||
|
},
|
||||||
persistTheme() {
|
persistTheme() {
|
||||||
LocalStorage.set(SETTING_THEME_KEY, this.getTheme);
|
LocalStorage.set(SETTING_THEME_KEY, this.getTheme);
|
||||||
},
|
},
|
||||||
|
@ -58,6 +73,7 @@ export const useSettingStore = defineStore({
|
||||||
},
|
},
|
||||||
async init() {
|
async init() {
|
||||||
await this.setTheme(this.getTheme);
|
await this.setTheme(this.getTheme);
|
||||||
|
await this.loadSysSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { request } from "/@/api/service";
|
import { request } from "/@/api/service";
|
||||||
const apiPrefix = "/sys/settings";
|
const apiPrefix = "/user/settings";
|
||||||
|
|
||||||
export const SettingKeys = {
|
export const SettingKeys = {
|
||||||
Email: "email"
|
Email: "email"
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item class="user-login-other">
|
<a-form-item class="user-login-other">
|
||||||
<router-link class="register" :to="{ name: 'register' }"> 注册 </router-link>
|
<router-link v-if="sysPublicSettings.registerEnabled" class="register" :to="{ name: 'register' }"> 注册 </router-link>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -74,11 +74,13 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, reactive, ref, toRaw, computed } from "vue";
|
import { defineComponent, reactive, ref, toRaw, computed } from "vue";
|
||||||
import { useUserStore } from "/src/store/modules/user";
|
import { useUserStore } from "/src/store/modules/user";
|
||||||
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "LoginPage",
|
name: "LoginPage",
|
||||||
setup() {
|
setup() {
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
const settingStore = useSettingStore()
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const formState = reactive({
|
const formState = reactive({
|
||||||
username: "",
|
username: "",
|
||||||
|
@ -165,6 +167,7 @@ export default defineComponent({
|
||||||
function sendSmsCode() {
|
function sendSmsCode() {
|
||||||
//api.sendSmsCode();
|
//api.sendSmsCode();
|
||||||
}
|
}
|
||||||
|
const sysPublicSettings = settingStore.getSysPublic
|
||||||
return {
|
return {
|
||||||
loading,
|
loading,
|
||||||
formState,
|
formState,
|
||||||
|
@ -179,7 +182,8 @@ export default defineComponent({
|
||||||
resetImageCode,
|
resetImageCode,
|
||||||
smsTime,
|
smsTime,
|
||||||
smsSendBtnDisabled,
|
smsSendBtnDisabled,
|
||||||
sendSmsCode
|
sendSmsCode,
|
||||||
|
sysPublicSettings
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -65,6 +65,7 @@ export default defineComponent({
|
||||||
//处理过,无需再次处理
|
//处理过,无需再次处理
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
value.class="is-twig"
|
||||||
if (value.children != null && value.children.length > 0) {
|
if (value.children != null && value.children.length > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -82,8 +83,13 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
// 所有的子节点都没有children
|
// 所有的子节点都没有children
|
||||||
parent.class = "is-twig"; // 连接叶子节点的末梢枝杈节点
|
parent.class = "is-twig"; // 连接叶子节点的末梢枝杈节点
|
||||||
|
let i = 0
|
||||||
for (const child of parent.children) {
|
for (const child of parent.children) {
|
||||||
child.class = "is-leaf";
|
child.class = "is-leaf";
|
||||||
|
if(i !== 0){
|
||||||
|
child.class += " leaf-after";
|
||||||
|
}
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return [
|
return [
|
||||||
|
@ -129,21 +135,40 @@ export default defineComponent({
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.fs-permission-tree {
|
.fs-permission-tree {
|
||||||
.is-twig ul {
|
|
||||||
display: flex;
|
.ant-tree-list-holder-inner{
|
||||||
|
flex-direction: row !important;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
.is-twig{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.is-leaf {
|
.is-leaf {
|
||||||
border-bottom: 1px solid #ddd;
|
//border-bottom: 1px solid #ddd;
|
||||||
padding: 5px;
|
|
||||||
&::before {
|
&::before {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.leaf-after{
|
||||||
|
.ant-tree-indent-unit{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-title-pane {
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//.is-twig ul {
|
||||||
|
// display: flex;
|
||||||
|
// flex-wrap: wrap;
|
||||||
|
//}
|
||||||
.node-title-pane {
|
.node-title-pane {
|
||||||
display: flex;
|
display: flex;
|
||||||
.node-title {
|
.node-title {
|
||||||
width: 80px;
|
width: 110px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
<a-button v-permission="'sys:auth:per:add'" style="margin-left: 20px" @click="addHandle({})">
|
<a-button v-permission="'sys:auth:per:add'" style="margin-left: 20px" @click="addHandle({})">
|
||||||
<fs-icon :icon="ui.icons.add"></fs-icon>
|
<fs-icon :icon="ui.icons.add"></fs-icon>
|
||||||
添加</a-button
|
添加
|
||||||
>
|
</a-button>
|
||||||
<fs-permission-tree class="permission-tree" :tree="crudBinding.data" :checkable="false" :actions="permission" @add="addHandle" @edit="editHandle" @remove="removeHandle"></fs-permission-tree>
|
<fs-permission-tree class="permission-tree mt-10" :tree="crudBinding.data" :checkable="false" :actions="permission" @add="addHandle" @edit="editHandle" @remove="removeHandle"></fs-permission-tree>
|
||||||
</fs-crud>
|
</fs-crud>
|
||||||
</fs-page>
|
</fs-page>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
// @ts-ignore
|
||||||
|
import { request } from "/@/api/service";
|
||||||
|
const apiPrefix = "/sys/settings";
|
||||||
|
|
||||||
|
export const SettingKeys = {
|
||||||
|
SysPublic: "sys.public",
|
||||||
|
SysPrivate: "sys.private",
|
||||||
|
|
||||||
|
};
|
||||||
|
export async function SettingsGet(key: string) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/get",
|
||||||
|
method: "post",
|
||||||
|
params: {
|
||||||
|
key
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SettingsSave(key: string,setting: any) {
|
||||||
|
await request({
|
||||||
|
url: apiPrefix + "/save",
|
||||||
|
method: "post",
|
||||||
|
data: {
|
||||||
|
key,
|
||||||
|
setting: JSON.stringify(setting),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function PublicSettingsSave(setting: any) {
|
||||||
|
await request({
|
||||||
|
url: apiPrefix + "/savePublicSettings",
|
||||||
|
method: "post",
|
||||||
|
data: setting
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
<template>
|
||||||
|
<fs-page class="page-sys-settings">
|
||||||
|
<template #header>
|
||||||
|
<div class="title">系统设置</div>
|
||||||
|
</template>
|
||||||
|
<div class="sys-settings-form">
|
||||||
|
<a-form :model="formState" name="basic" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onFinish" @finish-failed="onFinishFailed">
|
||||||
|
<a-form-item label="开启自助注册" name="registerEnabled">
|
||||||
|
<a-switch v-model:checked="formState.registerEnabled" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
|
||||||
|
<a-button type="primary" html-type="submit">保存</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive } from "vue";
|
||||||
|
import * as api from "./api";
|
||||||
|
import { PublicSettingsSave, SettingKeys } from "./api";
|
||||||
|
import { notification } from "ant-design-vue";
|
||||||
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
|
|
||||||
|
interface FormState {
|
||||||
|
registerEnabled: boolean;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const formState = reactive<Partial<FormState>>({
|
||||||
|
registerEnabled:false
|
||||||
|
});
|
||||||
|
|
||||||
|
async function loadSysPublicSettings() {
|
||||||
|
const data: any = await api.SettingsGet(SettingKeys.SysPublic);
|
||||||
|
const setting = JSON.parse(data.setting);
|
||||||
|
Object.assign(formState, setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadSysPublicSettings();
|
||||||
|
const settingsStore= useSettingStore()
|
||||||
|
const onFinish = async (form: any) => {
|
||||||
|
console.log("Success:", form);
|
||||||
|
await api.PublicSettingsSave(form);
|
||||||
|
await settingsStore.loadSysSettings()
|
||||||
|
notification.success({
|
||||||
|
message: "保存成功"
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFinishFailed = (errorInfo: any) => {
|
||||||
|
// console.log("Failed:", errorInfo);
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.page-sys-settings {
|
||||||
|
.sys-settings-form {
|
||||||
|
width: 500px;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,9 +2,9 @@ import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/decorator';
|
||||||
import type { EmailSend } from '@certd/pipeline';
|
import type { EmailSend } from '@certd/pipeline';
|
||||||
import { IEmailService } from '@certd/pipeline';
|
import { IEmailService } from '@certd/pipeline';
|
||||||
import nodemailer from 'nodemailer';
|
import nodemailer from 'nodemailer';
|
||||||
import { SettingsService } from '../../system/service/settings-service';
|
|
||||||
import type SMTPConnection from 'nodemailer/lib/smtp-connection';
|
import type SMTPConnection from 'nodemailer/lib/smtp-connection';
|
||||||
import { logger } from '../../../utils/logger';
|
import { logger } from '../../../utils/logger';
|
||||||
|
import { UserSettingsService } from '../../mine/service/user-settings-service';
|
||||||
|
|
||||||
export type EmailConfig = {
|
export type EmailConfig = {
|
||||||
host: string;
|
host: string;
|
||||||
|
@ -24,7 +24,7 @@ export type EmailConfig = {
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Singleton)
|
||||||
export class EmailService implements IEmailService {
|
export class EmailService implements IEmailService {
|
||||||
@Inject()
|
@Inject()
|
||||||
settingsService: SettingsService;
|
settingsService: UserSettingsService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { BaseController } from '../../../basic/base-controller';
|
||||||
import { Constants } from '../../../basic/constants';
|
import { Constants } from '../../../basic/constants';
|
||||||
import { UserService } from '../../authority/service/user-service';
|
import { UserService } from '../../authority/service/user-service';
|
||||||
import { UserEntity } from '../../authority/entity/user';
|
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 {
|
export class RegisterController extends BaseController {
|
||||||
@Inject()
|
@Inject()
|
||||||
userService: UserService;
|
userService: UserService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
||||||
@Post('/register', { summary: Constants.per.guest })
|
@Post('/register', { summary: Constants.per.guest })
|
||||||
public async register(
|
public async register(
|
||||||
@Body(ALL)
|
@Body(ALL)
|
||||||
user: UserEntity
|
user: UserEntity
|
||||||
) {
|
) {
|
||||||
|
const sysPublicSettings = await this.sysSettingsService.getPublicSettings();
|
||||||
|
if (sysPublicSettings.registerEnabled === false) {
|
||||||
|
throw new Error('当前站点已禁止自助注册功能');
|
||||||
|
}
|
||||||
const newUser = await this.userService.register(user);
|
const newUser = await this.userService.register(user);
|
||||||
return this.ok(newUser);
|
return this.ok(newUser);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,16 @@
|
||||||
import {
|
import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/decorator";
|
||||||
ALL,
|
import { CrudController } from "../../../basic/crud-controller";
|
||||||
Body,
|
import { Constants } from "../../../basic/constants";
|
||||||
Controller,
|
import { UserSettingsService } from "../service/user-settings-service";
|
||||||
Inject,
|
import { UserSettingsEntity } from "../entity/user-settings";
|
||||||
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';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Controller('/api/sys/settings')
|
@Controller('/api/user/settings')
|
||||||
export class SettingsController extends CrudController<SettingsService> {
|
export class UserSettingsController extends CrudController<UserSettingsService> {
|
||||||
@Inject()
|
@Inject()
|
||||||
service: SettingsService;
|
service: UserSettingsService;
|
||||||
|
|
||||||
getService() {
|
getService() {
|
||||||
return this.service;
|
return this.service;
|
||||||
|
@ -61,7 +53,7 @@ export class SettingsController extends CrudController<SettingsService> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/save', { summary: Constants.per.authOnly })
|
@Post('/save', { summary: Constants.per.authOnly })
|
||||||
async save(@Body(ALL) bean: SettingsEntity) {
|
async save(@Body(ALL) bean: UserSettingsEntity) {
|
||||||
bean.userId = this.ctx.user.id;
|
bean.userId = this.ctx.user.id;
|
||||||
await this.service.save(bean);
|
await this.service.save(bean);
|
||||||
return this.ok({});
|
return this.ok({});
|
|
@ -2,8 +2,8 @@ import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@Entity('sys_settings')
|
@Entity('user_settings')
|
||||||
export class SettingsEntity {
|
export class UserSettingsEntity {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number;
|
id: number;
|
||||||
@Column({ name: 'user_id', comment: '用户id' })
|
@Column({ name: 'user_id', comment: '用户id' })
|
|
@ -2,22 +2,22 @@ import { Provide, Scope, ScopeEnum } from '@midwayjs/decorator';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { BaseService } from '../../../basic/base-service';
|
import { BaseService } from '../../../basic/base-service';
|
||||||
import { SettingsEntity } from '../entity/settings';
|
import { UserSettingsEntity } from '../entity/user-settings';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 授权
|
* 授权
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Singleton)
|
||||||
export class SettingsService extends BaseService<SettingsEntity> {
|
export class UserSettingsService extends BaseService<UserSettingsEntity> {
|
||||||
@InjectEntityModel(SettingsEntity)
|
@InjectEntityModel(UserSettingsEntity)
|
||||||
repository: Repository<SettingsEntity>;
|
repository: Repository<UserSettingsEntity>;
|
||||||
|
|
||||||
getRepository() {
|
getRepository() {
|
||||||
return this.repository;
|
return this.repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getById(id: any): Promise<SettingsEntity | null> {
|
async getById(id: any): Promise<UserSettingsEntity | null> {
|
||||||
const entity = await this.info(id);
|
const entity = await this.info(id);
|
||||||
if (!entity) {
|
if (!entity) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -30,7 +30,7 @@ export class SettingsService extends BaseService<SettingsEntity> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async getByKey(key: string, userId: number): Promise<SettingsEntity | null> {
|
async getByKey(key: string, userId: number): Promise<UserSettingsEntity | null> {
|
||||||
if (!key || !userId) {
|
if (!key || !userId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ export class SettingsService extends BaseService<SettingsEntity> {
|
||||||
return JSON.parse(entity.setting);
|
return JSON.parse(entity.setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
async save(bean: SettingsEntity) {
|
async save(bean: UserSettingsEntity) {
|
||||||
const entity = await this.repository.findOne({
|
const entity = await this.repository.findOne({
|
||||||
where: {
|
where: {
|
||||||
key: bean.key,
|
key: bean.key,
|
|
@ -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<SysSettingsService> {
|
||||||
|
@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({});
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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<unknown>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置
|
||||||
|
*/
|
||||||
|
@Provide()
|
||||||
|
@Scope(ScopeEnum.Singleton)
|
||||||
|
export class SysSettingsService extends BaseService<SysSettingsEntity> {
|
||||||
|
@InjectEntityModel(SysSettingsEntity)
|
||||||
|
repository: Repository<SysSettingsEntity>;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
cache: CacheManager; // 依赖注入CacheManager
|
||||||
|
|
||||||
|
getRepository() {
|
||||||
|
return this.repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getById(id: any): Promise<SysSettingsEntity | null> {
|
||||||
|
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<SysSettingsEntity | null> {
|
||||||
|
if (!key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return await this.repository.findOne({
|
||||||
|
where: {
|
||||||
|
key,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSettingByKey(key: string): Promise<any | null> {
|
||||||
|
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<SysPublicSettings> {
|
||||||
|
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<SysPublicSettings> {
|
||||||
|
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<SysPrivateSettings> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue