1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-31 14:08:06 +08:00

feat: 面板设置增加表单校验

This commit is contained in:
ssongliu 2022-09-16 16:00:49 +08:00 committed by ssongliu
parent 9f5e9d26f5
commit fc3318c8e9
20 changed files with 266 additions and 133 deletions

View File

@ -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"`

View File

@ -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
}

View File

@ -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;

View File

@ -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',

View File

@ -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',

View File

@ -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 位验证码',

View File

@ -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';

View File

@ -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>();

View File

@ -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';

View File

@ -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: {

View File

@ -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';

View File

@ -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';

View 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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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();
});

View File

@ -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);

View File

@ -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>

View File

@ -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;
});