mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat: 面板设置增加表单校验
This commit is contained in:
parent
9f5e9d26f5
commit
fc3318c8e9
@ -4,14 +4,14 @@ type SettingInfo struct {
|
||||
UserName string `json:"userName"`
|
||||
Email string `json:"email"`
|
||||
|
||||
SessionTimeout string `json:"sessionTimeout"`
|
||||
SessionTimeout int `json:"sessionTimeout"`
|
||||
LocalTime string `json:"localTime"`
|
||||
|
||||
PanelName string `json:"panelName"`
|
||||
Theme string `json:"theme"`
|
||||
Language string `json:"language"`
|
||||
|
||||
ServerPort string `json:"serverPort"`
|
||||
ServerPort int `json:"serverPort"`
|
||||
SecurityEntrance string `json:"securityEntrance"`
|
||||
PasswordTimeOut string `json:"passwordTimeOut"`
|
||||
ComplexityVerification string `json:"complexityVerification"`
|
||||
@ -19,7 +19,7 @@ type SettingInfo struct {
|
||||
MFASecret string `json:"mfaSecret"`
|
||||
|
||||
MonitorStatus string `json:"monitorStatus"`
|
||||
MonitorStoreDays string `json:"monitorStoreDays"`
|
||||
MonitorStoreDays int `json:"monitorStoreDays"`
|
||||
|
||||
MessageType string `json:"messageType"`
|
||||
EmailVars string `json:"emailVars"`
|
||||
|
@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/app/dto"
|
||||
@ -37,9 +38,10 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.Unmarshal(arr, &info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = json.Unmarshal(arr, &info)
|
||||
info.MonitorStoreDays, _ = strconv.Atoi(settingMap["MonitorStoreDays"])
|
||||
info.ServerPort, _ = strconv.Atoi(settingMap["ServerPort"])
|
||||
info.SessionTimeout, _ = strconv.Atoi(settingMap["SessionTimeout"])
|
||||
info.LocalTime = time.Now().Format("2006-01-02 15:04:05")
|
||||
return &info, err
|
||||
}
|
||||
|
@ -4,14 +4,14 @@ export namespace Setting {
|
||||
password: string;
|
||||
email: string;
|
||||
|
||||
sessionTimeout: string;
|
||||
sessionTimeout: number;
|
||||
localTime: string;
|
||||
|
||||
panelName: string;
|
||||
theme: string;
|
||||
language: string;
|
||||
|
||||
serverPort: string;
|
||||
serverPort: number;
|
||||
securityEntrance: string;
|
||||
passwordTimeOut: string;
|
||||
complexityVerification: string;
|
||||
@ -19,7 +19,7 @@ export namespace Setting {
|
||||
mfaSecret: string;
|
||||
|
||||
monitorStatus: string;
|
||||
monitorStoreDays: string;
|
||||
monitorStoreDays: number;
|
||||
|
||||
messageType: string;
|
||||
emailVars: string;
|
||||
@ -33,7 +33,6 @@ export namespace Setting {
|
||||
export interface PasswordUpdate {
|
||||
oldPassword: string;
|
||||
newPassword: string;
|
||||
retryPassword: string;
|
||||
}
|
||||
export interface MFAInfo {
|
||||
secret: string;
|
||||
|
@ -15,10 +15,37 @@ const checkIp = (rule: any, value: any, callback: any) => {
|
||||
}
|
||||
};
|
||||
|
||||
const complexityPassword = (rule: any, value: any, callback: any) => {
|
||||
if (value === '' || typeof value === 'undefined' || value == null) {
|
||||
callback(new Error(i18n.global.t('commons.rule.complexityPassword')));
|
||||
} else {
|
||||
const reg = /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[~!@#$%^&*.])[\da-zA-Z~!@#$%^&*.]{8,}$/;
|
||||
if (!reg.test(value) && value !== '') {
|
||||
callback(new Error(i18n.global.t('commons.rule.complexityPassword')));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const checkName = (rule: any, value: any, callback: any) => {
|
||||
if (value === '' || typeof value === 'undefined' || value == null) {
|
||||
callback(new Error(i18n.global.t('commons.rule.commonName')));
|
||||
} else {
|
||||
const reg = /^[a-zA-Z0-9\u4e00-\u9fa5]{1}[a-zA-Z0-9_.\u4e00-\u9fa5-]{0,30}$/;
|
||||
if (!reg.test(value) && value !== '') {
|
||||
callback(new Error(i18n.global.t('commons.rule.commonName')));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
interface CommonRule {
|
||||
requiredInput: FormItemRule;
|
||||
requiredSelect: FormItemRule;
|
||||
name: FormItemRule;
|
||||
password: FormItemRule;
|
||||
email: FormItemRule;
|
||||
number: FormItemRule;
|
||||
ip: FormItemRule;
|
||||
@ -37,14 +64,15 @@ export const Rules: CommonRule = {
|
||||
trigger: 'change',
|
||||
},
|
||||
name: {
|
||||
type: 'regexp',
|
||||
min: 1,
|
||||
max: 30,
|
||||
message: i18n.global.t('commons.rule.commonName'),
|
||||
validator: checkName,
|
||||
trigger: 'blur',
|
||||
},
|
||||
password: {
|
||||
validator: complexityPassword,
|
||||
trigger: 'blur',
|
||||
pattern: '/^[a-zA-Z0-9\u4e00-\u9fa5]{1}[a-zA-Z0-9_.\u4e00-\u9fa5-]{0,30}$/',
|
||||
},
|
||||
email: {
|
||||
required: true,
|
||||
type: 'email',
|
||||
message: i18n.global.t('commons.rule.email'),
|
||||
trigger: 'blur',
|
@ -68,6 +68,9 @@ export default {
|
||||
requiredInput: 'Please enter the required fields',
|
||||
requiredSelect: 'Please select the required fields',
|
||||
commonName: 'Support English, Chinese, numbers, .-_, length 1-30',
|
||||
complexityPassword:
|
||||
'Please enter a password with more than 8 characters and must contain letters, digits, and special symbols',
|
||||
commonPassword: 'Please enter a password with more than 6 characters',
|
||||
email: 'Email format error',
|
||||
ip: 'Please enter the correct IP address',
|
||||
port: 'Please enter the correct port',
|
||||
|
@ -77,6 +77,8 @@ export default {
|
||||
requiredInput: '请填写必填项',
|
||||
requiredSelect: '请选择必选项',
|
||||
commonName: '支持英文、中文、数字、.-_,长度1-30',
|
||||
complexityPassword: '请输入 8 位以上、必须含有字母、数字、特殊符号的密码',
|
||||
commonPassword: '请输入 6 位以上长度密码',
|
||||
email: '请输入正确的邮箱',
|
||||
number: '请输入正确的数字',
|
||||
ip: '请输入正确的 IP 地址',
|
||||
@ -298,7 +300,7 @@ export default {
|
||||
passwordTimeout: '密码过期时间',
|
||||
timeoutHelper: '【 {0} 天后 】面板密码即将过期,过期后需要重新设置密码',
|
||||
complexity: '密码复杂度验证',
|
||||
complexityHelper: '密码必须满足密码长度大于8位且大写字母、小写字母、数字、特殊字符至少3项组合',
|
||||
complexityHelper: '密码必须满足密码长度大于 8 位且包含字母、数字及特殊字符',
|
||||
mfa: '两步验证',
|
||||
mfaHelper1: '下载两步验证手机应用 如:',
|
||||
mfaHelper2: '使用手机应用扫描以下二维码,获取 6 位验证码',
|
||||
|
@ -41,7 +41,7 @@ import i18n from '@/lang';
|
||||
import { computed, reactive, ref, toRefs } from 'vue';
|
||||
import { File } from '@/api/interface/file';
|
||||
import { ElMessage, FormInstance, FormRules } from 'element-plus';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { CompressExtention, CompressType } from '@/enums/files';
|
||||
import { CompressFile } from '@/api/modules/files';
|
||||
import FileList from '@/components/file-list/index.vue';
|
||||
|
@ -56,7 +56,7 @@ import { ElMessage, FormInstance, FormRules } from 'element-plus';
|
||||
import { CreateFile } from '@/api/modules/files';
|
||||
import i18n from '@/lang';
|
||||
import FileRole from '@/components/file-role/index.vue';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import FileList from '@/components/file-list/index.vue';
|
||||
|
||||
const fileForm = ref<FormInstance>();
|
||||
|
@ -33,7 +33,7 @@ import i18n from '@/lang';
|
||||
import { reactive, ref, toRefs } from 'vue';
|
||||
import { File } from '@/api/interface/file';
|
||||
import { ElMessage, FormInstance, FormRules } from 'element-plus';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { DeCompressFile } from '@/api/modules/files';
|
||||
import { Mimetypes } from '@/global/mimetype';
|
||||
import FileList from '@/components/file-list/index.vue';
|
||||
|
@ -36,7 +36,7 @@ import { CompressExtention, CompressType } from '@/enums/files';
|
||||
import { computed, PropType, reactive, ref, toRefs } from 'vue';
|
||||
import { DownloadFile } from '@/api/modules/files';
|
||||
import { File } from '@/api/interface/file';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
|
||||
const props = defineProps({
|
||||
open: {
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { MoveFile } from '@/api/modules/files';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { ElMessage, FormInstance, FormRules } from 'element-plus';
|
||||
import { toRefs, ref, reactive, PropType, computed } from 'vue';
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { RenameRile } from '@/api/modules/files';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { ElMessage, FormInstance, FormRules } from 'element-plus';
|
||||
import { reactive, ref, toRefs } from 'vue';
|
||||
import { File } from '@/api/interface/file';
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { WgetFile } from '@/api/modules/files';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { ElMessage, FormInstance, FormRules } from 'element-plus';
|
||||
import { reactive, ref, toRefs } from 'vue';
|
||||
|
@ -41,7 +41,7 @@ import { addCommand, editCommand, deleteCommand, getCommandPage } from '@/api/mo
|
||||
import { reactive, ref } from '@vue/runtime-core';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import type { ElForm } from 'element-plus';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
|
@ -119,7 +119,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import type { ElForm } from 'element-plus';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { Host } from '@/api/interface/host';
|
||||
import { Group } from '@/api/interface/group';
|
||||
import { testConn, getHostTree, getHostInfo, addHost, editHost, deleteHost } from '@/api/modules/host';
|
||||
|
@ -173,7 +173,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onBeforeMount, ref, watch, reactive, getCurrentInstance } from 'vue';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { testConn, getHostTree, addHost } from '@/api/modules/host';
|
||||
import { getCommandList } from '@/api/modules/command';
|
||||
import i18n from '@/lang';
|
||||
|
@ -7,45 +7,51 @@
|
||||
<el-radio-button class="topButton" size="large" label="safe">安全</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="backup">备份</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="monitor">监控</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="message">通知</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="about">关于</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-card>
|
||||
<Panel v-if="activeNames === 'all' || activeNames === 'panel'" :settingInfo="form" />
|
||||
<Safe v-if="activeNames === 'all' || activeNames === 'safe'" :settingInfo="form" />
|
||||
<Backup v-if="activeNames === 'all' || activeNames === 'backup'" :settingInfo="form" />
|
||||
<Monitor v-if="activeNames === 'all' || activeNames === 'monitor'" :settingInfo="form" />
|
||||
<Message v-if="activeNames === 'all' || activeNames === 'message'" :settingInfo="form" />
|
||||
<Panel v-if="activeNames === 'all' || activeNames === 'panel'" :settingInfo="form" @on-save="SaveSetting" />
|
||||
<Safe v-if="activeNames === 'all' || activeNames === 'safe'" :settingInfo="form" @on-save="SaveSetting" />
|
||||
<Backup v-if="activeNames === 'all' || activeNames === 'backup'" :settingInfo="form" @on-save="SaveSetting" />
|
||||
<Monitor v-if="activeNames === 'all' || activeNames === 'monitor'" :settingInfo="form" @on-save="SaveSetting" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getSettingInfo } from '@/api/modules/setting';
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { getSettingInfo, updateSetting } from '@/api/modules/setting';
|
||||
import { Setting } from '@/api/interface/setting';
|
||||
import Panel from '@/views/setting/tabs/panel.vue';
|
||||
import Safe from '@/views/setting/tabs/safe.vue';
|
||||
import Backup from '@/views/setting/tabs/backup.vue';
|
||||
import Monitor from '@/views/setting/tabs/monitor.vue';
|
||||
import Message from '@/views/setting/tabs/message.vue';
|
||||
import { GlobalStore } from '@/store';
|
||||
import { useTheme } from '@/hooks/use-theme';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { ElMessage, FormInstance } from 'element-plus';
|
||||
|
||||
const i18n = useI18n();
|
||||
const globalStore = GlobalStore();
|
||||
const themeConfig = computed(() => globalStore.themeConfig);
|
||||
|
||||
const activeNames = ref('all');
|
||||
let form = ref<Setting.SettingInfo>({
|
||||
userName: '',
|
||||
password: '',
|
||||
email: '',
|
||||
sessionTimeout: '',
|
||||
sessionTimeout: 86400,
|
||||
localTime: '',
|
||||
panelName: '',
|
||||
theme: '',
|
||||
language: '',
|
||||
serverPort: '',
|
||||
serverPort: 8888,
|
||||
securityEntrance: '',
|
||||
passwordTimeOut: '',
|
||||
complexityVerification: '',
|
||||
mfaStatus: '',
|
||||
mfaSecret: '',
|
||||
monitorStatus: '',
|
||||
monitorStoreDays: '',
|
||||
monitorStoreDays: 30,
|
||||
messageType: '',
|
||||
emailVars: '',
|
||||
weChatVars: '',
|
||||
@ -58,6 +64,52 @@ const search = async () => {
|
||||
form.value.password = '******';
|
||||
};
|
||||
|
||||
const { switchDark } = useTheme();
|
||||
|
||||
const SaveSetting = async (formEl: FormInstance | undefined, key: string, val: any) => {
|
||||
if (!formEl) return;
|
||||
const result = await formEl.validateField('settingInfo.' + key.replace(key[0], key[0].toLowerCase()), callback);
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
if (val === '') {
|
||||
return;
|
||||
}
|
||||
switch (key) {
|
||||
case 'Language':
|
||||
i18n.locale.value = val;
|
||||
globalStore.updateLanguage(val);
|
||||
break;
|
||||
case 'Theme':
|
||||
globalStore.setThemeConfig({ ...themeConfig.value, theme: val });
|
||||
switchDark();
|
||||
break;
|
||||
case 'PanelName':
|
||||
globalStore.setThemeConfig({ ...themeConfig.value, panelName: val });
|
||||
break;
|
||||
case 'SessionTimeout':
|
||||
case 'MonitorStoreDays':
|
||||
case 'ServerPort':
|
||||
val = val + '';
|
||||
break;
|
||||
}
|
||||
let param = {
|
||||
key: key,
|
||||
value: val,
|
||||
};
|
||||
await updateSetting(param);
|
||||
ElMessage.success(i18n.t('commons.msg.operationSuccess'));
|
||||
search();
|
||||
};
|
||||
|
||||
function callback(error: any) {
|
||||
if (error) {
|
||||
return error.message;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-form :model="form" label-position="left" label-width="160px">
|
||||
<el-form :model="form" ref="panelFormRef" label-position="left" label-width="160px">
|
||||
<el-card style="margin-top: 10px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
@ -9,20 +9,28 @@
|
||||
<el-row>
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item :label="$t('setting.enableMonitor')">
|
||||
<el-form-item
|
||||
:label="$t('setting.enableMonitor')"
|
||||
:rules="Rules.requiredInput"
|
||||
prop="settingInfo.monitorStatus"
|
||||
>
|
||||
<el-radio-group
|
||||
@change="SaveSetting('MonitorStatus', form.settingInfo.monitorStatus)"
|
||||
@change="onSave(panelFormRef, 'MonitorStatus', form.settingInfo.monitorStatus)"
|
||||
v-model="form.settingInfo.monitorStatus"
|
||||
>
|
||||
<el-radio-button label="enable">{{ $t('commons.button.enable') }}</el-radio-button>
|
||||
<el-radio-button label="disable">{{ $t('commons.button.disable') }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.storeDays')">
|
||||
<el-input clearable v-model="form.settingInfo.monitorStoreDays">
|
||||
<el-form-item
|
||||
:label="$t('setting.storeDays')"
|
||||
:rules="Rules.number"
|
||||
prop="settingInfo.monitorStoreDays"
|
||||
>
|
||||
<el-input clearable v-model.number="form.settingInfo.monitorStoreDays">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('MonitorStoreDays', form.settingInfo.monitorStoreDays)"
|
||||
@click="onSave(panelFormRef, 'MonitorStoreDays', form.settingInfo.monitorStoreDays)"
|
||||
icon="Collection"
|
||||
>
|
||||
{{ $t('commons.button.save') }}
|
||||
@ -40,10 +48,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { updateSetting, cleanMonitors } from '@/api/modules/setting';
|
||||
import i18n from '@/lang';
|
||||
import { ref } from 'vue';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { cleanMonitors } from '@/api/modules/setting';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
|
||||
const emit = defineEmits<{ (e: 'on-save', formEl: FormInstance | undefined, key: string, val: any): void }>();
|
||||
|
||||
interface Props {
|
||||
settingInfo: any;
|
||||
@ -51,18 +62,14 @@ interface Props {
|
||||
const form = withDefaults(defineProps<Props>(), {
|
||||
settingInfo: {
|
||||
monitorStatus: '',
|
||||
monitorStoreDays: '',
|
||||
monitorStoreDays: 30,
|
||||
},
|
||||
});
|
||||
const panelFormRef = ref<FormInstance>();
|
||||
|
||||
const SaveSetting = async (key: string, val: string) => {
|
||||
let param = {
|
||||
key: key,
|
||||
value: val,
|
||||
};
|
||||
await updateSetting(param);
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
};
|
||||
function onSave(formEl: FormInstance | undefined, key: string, val: any) {
|
||||
emit('on-save', formEl, key, val);
|
||||
}
|
||||
|
||||
const onClean = async () => {
|
||||
await useDeleteData(cleanMonitors, {}, 'commons.msg.delete', true);
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-form :model="form" label-position="left" label-width="160px">
|
||||
<el-form :model="form" ref="panelFormRef" label-position="left" label-width="160px">
|
||||
<el-card style="margin-top: 20px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
@ -9,11 +9,11 @@
|
||||
<el-row>
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item :label="$t('auth.username')" prop="settingInfo.userName">
|
||||
<el-form-item :label="$t('auth.username')" :rules="Rules.requiredInput" prop="settingInfo.userName">
|
||||
<el-input clearable v-model="form.settingInfo.userName">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('UserName', form.settingInfo.userName)"
|
||||
@click="onSave(panelFormRef, 'UserName', form.settingInfo.userName)"
|
||||
icon="Collection"
|
||||
>
|
||||
{{ $t('commons.button.save') }}
|
||||
@ -21,7 +21,7 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('auth.password')" prop="settingInfo.password">
|
||||
<el-form-item :label="$t('auth.password')" :rules="Rules.requiredInput" prop="settingInfo.password">
|
||||
<el-input type="password" clearable disabled v-model="form.settingInfo.password">
|
||||
<template #append>
|
||||
<el-button icon="Setting" @click="passwordVisiable = true">
|
||||
@ -30,10 +30,13 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('auth.email')" prop="settingInfo.email">
|
||||
<el-form-item :label="$t('auth.email')" :rules="Rules.email" prop="settingInfo.email">
|
||||
<el-input clearable v-model="form.settingInfo.email">
|
||||
<template #append>
|
||||
<el-button @click="SaveSetting('Email', form.settingInfo.email)" icon="Collection">
|
||||
<el-button
|
||||
@click="onSave(panelFormRef, 'Email', form.settingInfo.email)"
|
||||
icon="Collection"
|
||||
>
|
||||
{{ $t('commons.button.save') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@ -42,11 +45,15 @@
|
||||
<span class="input-help">{{ $t('setting.emailHelper') }}</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.title')" prop="settingInfo.panelName">
|
||||
<el-form-item
|
||||
:label="$t('setting.title')"
|
||||
:rules="Rules.requiredInput"
|
||||
prop="settingInfo.panelName"
|
||||
>
|
||||
<el-input clearable v-model="form.settingInfo.panelName">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('PanelName', form.settingInfo.panelName)"
|
||||
@click="onSave(panelFormRef, 'PanelName', form.settingInfo.panelName)"
|
||||
icon="Collection"
|
||||
>
|
||||
{{ $t('commons.button.save') }}
|
||||
@ -54,9 +61,9 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.theme')" prop="settingInfo.theme">
|
||||
<el-form-item :label="$t('setting.theme')" :rules="Rules.requiredSelect" prop="settingInfo.theme">
|
||||
<el-radio-group
|
||||
@change="SaveSetting('Theme', form.settingInfo.theme)"
|
||||
@change="onSave(panelFormRef, 'Theme', form.settingInfo.theme)"
|
||||
v-model="form.settingInfo.theme"
|
||||
>
|
||||
<el-radio-button label="dark">
|
||||
@ -69,9 +76,13 @@
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.language')" prop="settingInfo.language">
|
||||
<el-form-item
|
||||
:label="$t('setting.language')"
|
||||
:rules="Rules.requiredSelect"
|
||||
prop="settingInfo.language"
|
||||
>
|
||||
<el-radio-group
|
||||
@change="SaveSetting('Language', form.settingInfo.language)"
|
||||
@change="onSave(panelFormRef, 'Language', form.settingInfo.language)"
|
||||
v-model="form.settingInfo.language"
|
||||
>
|
||||
<el-radio-button label="zh">中文</el-radio-button>
|
||||
@ -83,11 +94,15 @@
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.sessionTimeout')" prop="settingInfo.sessionTimeout">
|
||||
<el-form-item
|
||||
:label="$t('setting.sessionTimeout')"
|
||||
:rules="Rules.number"
|
||||
prop="settingInfo.sessionTimeout"
|
||||
>
|
||||
<el-input v-model.number="form.settingInfo.sessionTimeout">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('SessionTimeout', form.settingInfo.sessionTimeout)"
|
||||
@click="onSave(panelFormRef, 'SessionTimeout', form.settingInfo.sessionTimeout)"
|
||||
icon="Collection"
|
||||
>
|
||||
{{ $t('commons.button.save') }}
|
||||
@ -118,9 +133,20 @@
|
||||
<el-form-item :label="$t('setting.oldPassword')" prop="oldPassword">
|
||||
<el-input type="password" show-password clearable v-model="passForm.oldPassword" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.newPassword')" prop="newPassword">
|
||||
<el-form-item
|
||||
v-if="form.settingInfo.complexityVerification === 'disable'"
|
||||
:label="$t('setting.newPassword')"
|
||||
prop="newPassword"
|
||||
>
|
||||
<el-input type="password" show-password clearable v-model="passForm.newPassword" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.settingInfo.complexityVerification === 'enable'"
|
||||
:label="$t('setting.newPassword')"
|
||||
prop="newPasswordComplexity"
|
||||
>
|
||||
<el-input type="password" show-password clearable v-model="passForm.newPasswordComplexity" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.retryPassword')" prop="retryPassword">
|
||||
<el-input type="password" show-password clearable v-model="passForm.retryPassword" />
|
||||
</el-form-item>
|
||||
@ -137,31 +163,30 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ElMessage, ElForm } from 'element-plus';
|
||||
import { updateSetting, updatePassword, syncTime } from '@/api/modules/setting';
|
||||
import { Setting } from '@/api/interface/setting';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { GlobalStore } from '@/store';
|
||||
import { useTheme } from '@/hooks/use-theme';
|
||||
import { updatePassword, syncTime } from '@/api/modules/setting';
|
||||
import router from '@/routers/router';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { GlobalStore } from '@/store';
|
||||
|
||||
const i18n = useI18n();
|
||||
const globalStore = GlobalStore();
|
||||
const themeConfig = computed(() => globalStore.themeConfig);
|
||||
const emit = defineEmits<{ (e: 'on-save', formEl: FormInstance | undefined, key: string, val: any): void }>();
|
||||
|
||||
type FormInstance = InstanceType<typeof ElForm>;
|
||||
const passFormRef = ref<FormInstance>();
|
||||
const passRules = reactive({
|
||||
oldPassword: [Rules.requiredInput],
|
||||
newPassword: [Rules.requiredInput],
|
||||
newPassword: [Rules.requiredInput, { min: 6, message: i18n.global.t('commons.rule.passwordLen'), trigger: 'blur' }],
|
||||
newPasswordComplexity: [Rules.password],
|
||||
retryPassword: [Rules.requiredInput, { validator: checkPassword, trigger: 'blur' }],
|
||||
});
|
||||
const passwordVisiable = ref<boolean>(false);
|
||||
const passForm = reactive<Setting.PasswordUpdate>({
|
||||
const passForm = reactive({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
newPasswordComplexity: '',
|
||||
retryPassword: '',
|
||||
});
|
||||
|
||||
@ -173,61 +198,49 @@ const form = withDefaults(defineProps<Props>(), {
|
||||
userName: '',
|
||||
password: '',
|
||||
email: '',
|
||||
sessionTimeout: '',
|
||||
sessionTimeout: 0,
|
||||
localTime: '',
|
||||
panelName: '',
|
||||
theme: '',
|
||||
language: '',
|
||||
complexityVerification: '',
|
||||
},
|
||||
});
|
||||
|
||||
const { switchDark } = useTheme();
|
||||
const panelFormRef = ref<FormInstance>();
|
||||
|
||||
const SaveSetting = async (key: string, val: string) => {
|
||||
if (val === '') {
|
||||
return;
|
||||
}
|
||||
switch (key) {
|
||||
case 'Language':
|
||||
i18n.locale.value = val;
|
||||
globalStore.updateLanguage(val);
|
||||
break;
|
||||
case 'Theme':
|
||||
globalStore.setThemeConfig({ ...themeConfig.value, theme: val });
|
||||
switchDark();
|
||||
break;
|
||||
case 'PanelName':
|
||||
globalStore.setThemeConfig({ ...themeConfig.value, panelName: val });
|
||||
break;
|
||||
}
|
||||
let param = {
|
||||
key: key,
|
||||
value: val,
|
||||
};
|
||||
await updateSetting(param);
|
||||
ElMessage.success(i18n.t('commons.msg.operationSuccess'));
|
||||
};
|
||||
function onSave(formEl: FormInstance | undefined, key: string, val: any) {
|
||||
emit('on-save', formEl, key, val);
|
||||
}
|
||||
|
||||
function checkPassword(rule: any, value: any, callback: any) {
|
||||
if (passForm.newPassword !== passForm.retryPassword) {
|
||||
return callback(new Error(i18n.t('commons.rule.rePassword')));
|
||||
let password =
|
||||
form.settingInfo.complexityVerification === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
|
||||
if (password !== passForm.retryPassword) {
|
||||
return callback(new Error(i18n.global.t('commons.rule.rePassword')));
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
const submitChangePassword = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
await updatePassword(passForm);
|
||||
let password =
|
||||
form.settingInfo.complexityVerification === 'disable'
|
||||
? passForm.newPassword
|
||||
: passForm.newPasswordComplexity;
|
||||
await updatePassword({ oldPassword: passForm.oldPassword, newPassword: password });
|
||||
passwordVisiable.value = false;
|
||||
ElMessage.success(i18n.t('commons.msg.operationSuccess'));
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
router.push({ name: 'login', params: { code: '' } });
|
||||
globalStore.setLogStatus(false);
|
||||
});
|
||||
};
|
||||
|
||||
const onSyncTime = async () => {
|
||||
const res = await syncTime();
|
||||
form.settingInfo.localTime = res.data;
|
||||
ElMessage.success(i18n.t('commons.msg.operationSuccess'));
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
};
|
||||
</script>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form :model="form" label-position="left" label-width="160px">
|
||||
<el-form :model="form" ref="panelFormRef" label-position="left" label-width="160px">
|
||||
<el-card style="margin-top: 10px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
@ -10,11 +10,15 @@
|
||||
<el-row>
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item :label="$t('setting.panelPort')">
|
||||
<el-form-item
|
||||
:label="$t('setting.panelPort')"
|
||||
prop="settingInfo.serverPort"
|
||||
:rules="Rules.number"
|
||||
>
|
||||
<el-input clearable v-model="form.settingInfo.serverPort">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('ServerPort', form.settingInfo.serverPort)"
|
||||
@click="onSave(panelFormRef, 'ServerPort', form.settingInfo.serverPort)"
|
||||
icon="Collection"
|
||||
>
|
||||
{{ $t('commons.button.save') }}
|
||||
@ -35,11 +39,17 @@
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.safeEntrance')">
|
||||
<el-form-item
|
||||
:label="$t('setting.safeEntrance')"
|
||||
prop="settingInfo.securityEntrance"
|
||||
:rules="Rules.requiredInput"
|
||||
>
|
||||
<el-input clearable v-model="form.settingInfo.securityEntrance">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('SecurityEntrance', form.settingInfo.securityEntrance)"
|
||||
@click="
|
||||
onSave(panelFormRef, 'SecurityEntrance', form.settingInfo.securityEntrance)
|
||||
"
|
||||
icon="Collection"
|
||||
>
|
||||
{{ $t('commons.button.save') }}
|
||||
@ -52,8 +62,12 @@
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.passwordTimeout')">
|
||||
<el-input clearable v-model="form.settingInfo.passwordTimeOut">
|
||||
<el-form-item
|
||||
:label="$t('setting.passwordTimeout')"
|
||||
prop="settingInfo.passwordTimeOut"
|
||||
:rules="Rules.requiredInput"
|
||||
>
|
||||
<el-input disabled v-model="form.settingInfo.passwordTimeOut">
|
||||
<template #append>
|
||||
<el-button @click="timeoutVisiable = true" icon="Collection">
|
||||
{{ $t('commons.button.set') }}
|
||||
@ -66,9 +80,19 @@
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.complexity')">
|
||||
<el-form-item
|
||||
:label="$t('setting.complexity')"
|
||||
prop="settingInfo.complexityVerification"
|
||||
:rules="Rules.requiredSelect"
|
||||
>
|
||||
<el-radio-group
|
||||
@change="SaveSetting('ComplexityVerification', form.settingInfo.complexityVerification)"
|
||||
@change="
|
||||
onSave(
|
||||
panelFormRef,
|
||||
'ComplexityVerification',
|
||||
form.settingInfo.complexityVerification,
|
||||
)
|
||||
"
|
||||
v-model="form.settingInfo.complexityVerification"
|
||||
>
|
||||
<el-radio-button label="enable">{{ $t('commons.button.enable') }}</el-radio-button>
|
||||
@ -80,7 +104,11 @@
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.mfa')">
|
||||
<el-form-item
|
||||
:label="$t('setting.mfa')"
|
||||
prop="settingInfo.securityEntrance"
|
||||
:rules="Rules.requiredSelect"
|
||||
>
|
||||
<el-radio-group @change="handleMFA()" v-model="form.settingInfo.mfaStatus">
|
||||
<el-radio-button label="enable">{{ $t('commons.button.enable') }}</el-radio-button>
|
||||
<el-radio-button label="disable">{{ $t('commons.button.disable') }}</el-radio-button>
|
||||
@ -143,9 +171,12 @@ import { ElMessage, ElForm } from 'element-plus';
|
||||
import { Setting } from '@/api/interface/setting';
|
||||
import { updateSetting, getMFA, bindMFA } from '@/api/modules/setting';
|
||||
import i18n from '@/lang';
|
||||
import { Rules } from '@/global/form-rues';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { dateFromat } from '@/utils/util';
|
||||
|
||||
// const emit = defineEmits(['on-save']);
|
||||
const emit = defineEmits<{ (e: 'on-save', formEl: FormInstance | undefined, key: string, val: any): void }>();
|
||||
|
||||
interface Props {
|
||||
settingInfo: any;
|
||||
}
|
||||
@ -172,15 +203,11 @@ const otp = reactive<Setting.MFAInfo>({
|
||||
qrImage: '',
|
||||
});
|
||||
const mfaCode = ref();
|
||||
const panelFormRef = ref<FormInstance>();
|
||||
|
||||
const SaveSetting = async (key: string, val: string) => {
|
||||
let param = {
|
||||
key: key,
|
||||
value: val,
|
||||
};
|
||||
await updateSetting(param);
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
};
|
||||
function onSave(formEl: FormInstance | undefined, key: string, val: any) {
|
||||
emit('on-save', formEl, key, val);
|
||||
}
|
||||
|
||||
const handleMFA = async () => {
|
||||
if (form.settingInfo.mfaStatus === 'enable') {
|
||||
@ -205,7 +232,7 @@ const submitTimeout = async (formEl: FormInstance | undefined) => {
|
||||
formEl.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
let time = new Date(new Date().getTime() + 3600 * 1000 * 24 * timeoutForm.days);
|
||||
SaveSetting('PasswordTimeOut', dateFromat(0, 0, time));
|
||||
await updateSetting({ key: 'PasswordTimeOut', value: dateFromat(0, 0, time) });
|
||||
form.settingInfo.passwordTimeOut = dateFromat(0, 0, time);
|
||||
timeoutVisiable.value = false;
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user