fix: 安全入口逻辑调整 (#821)

This commit is contained in:
ssongliu 2023-04-27 22:44:16 +08:00 committed by GitHub
parent ebe0f98209
commit 292dca6419
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 783 additions and 842 deletions

View File

@ -65,33 +65,6 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
helper.SuccessWithData(c, nil)
}
// @Tags System Setting
// @Summary Update system entrance
// @Description 更新系统安全入口
// @Accept json
// @Param request body dto.SettingUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /settings/entrance/enable [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改系统配置 [SecurityEntranceStatus] => [打开]","formatEN":"update system setting [SecurityEntranceStatus] => [Enable]"}
func (b *BaseApi) UpdateEntrance(c *gin.Context) {
var req dto.SettingUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := settingService.UpdateEntrance(req.Value); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags System Setting
// @Summary Update system password
// @Description 更新系统登录密码

View File

@ -16,7 +16,6 @@ type SettingInfo struct {
Language string `json:"language"`
ServerPort string `json:"serverPort"`
SecurityEntranceStatus string `json:"securityEntranceStatus"`
SSL string `json:"ssl"`
SSLType string `json:"sslType"`
SecurityEntrance string `json:"securityEntrance"`

View File

@ -148,18 +148,14 @@ func (u *AuthService) VerifyCode(code string) (bool, error) {
}
func (u *AuthService) CheckIsSafety(code string) bool {
status, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntranceStatus"))
status, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
if err != nil {
return false
}
if status.Value == "disable" {
if len(status.Value) == 0 {
return true
}
setting, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
if err != nil {
return false
}
return setting.Value == code
return status.Value == code
}
func (u *AuthService) CheckIsFirst() bool {

View File

@ -28,7 +28,6 @@ type SettingService struct{}
type ISettingService interface {
GetSettingInfo() (*dto.SettingInfo, error)
Update(key, value string) error
UpdateEntrance(value string) error
UpdatePassword(c *gin.Context, old, new string) error
UpdatePort(port uint) error
UpdateSSL(c *gin.Context, req dto.SSLUpdate) error
@ -68,16 +67,6 @@ func (u *SettingService) Update(key, value string) error {
return err
}
}
if key == "SecurityEntrance" {
if err := settingRepo.Update("SecurityEntranceStatus", "enable"); err != nil {
return err
}
}
if key == "SecurityEntranceStatus" {
if err := settingRepo.Update("SecurityEntrance", ""); err != nil {
return err
}
}
if err := settingRepo.Update(key, value); err != nil {
return err
}
@ -87,16 +76,6 @@ func (u *SettingService) Update(key, value string) error {
return nil
}
func (u *SettingService) UpdateEntrance(value string) error {
if err := settingRepo.Update("SecurityEntranceStatus", "enable"); err != nil {
return err
}
if err := settingRepo.Update("SecurityEntrance", value); err != nil {
return err
}
return nil
}
func (u *SettingService) UpdatePort(port uint) error {
if common.ScanPort(int(port)) {
return buserr.WithDetail(constant.ErrPortInUsed, port, nil)

View File

@ -15,5 +15,8 @@ type System struct {
Mode string `mapstructure:"mode"`
RepoUrl string `mapstructure:"repo_url"`
Version string `mapstructure:"version"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Entrance string `mapstructure:"entrance"`
IsDemo bool `mapstructure:"is_demo"`
}

View File

@ -61,10 +61,10 @@ var AddTableSetting = &gormigrate.Migration{
if err := tx.AutoMigrate(&model.Setting{}); err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "UserName", Value: ""}).Error; err != nil {
if err := tx.Create(&model.Setting{Key: "UserName", Value: global.CONF.System.Username}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "Password", Value: ""}).Error; err != nil {
if err := tx.Create(&model.Setting{Key: "Password", Value: global.CONF.System.Password}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "Email", Value: ""}).Error; err != nil {
@ -91,7 +91,7 @@ var AddTableSetting = &gormigrate.Migration{
if err := tx.Create(&model.Setting{Key: "ServerPort", Value: global.CONF.System.Port}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "SecurityEntrance", Value: "onepanel"}).Error; err != nil {
if err := tx.Create(&model.Setting{Key: "SecurityEntrance", Value: global.CONF.System.Entrance}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "JWTSigningKey", Value: common.RandStr(16)}).Error; err != nil {
@ -291,10 +291,9 @@ var UpdateTableWebsite = &gormigrate.Migration{
var AddEntranceAndSSL = &gormigrate.Migration{
ID: "20230414-add-entrance-and-ssl",
Migrate: func(tx *gorm.DB) error {
if err := tx.Create(&model.Setting{Key: "SecurityEntranceStatus", Value: "disable"}).Error; err != nil {
return err
}
if err := tx.Model(&model.Setting{}).Where("key = ?", "SecurityEntrance").Updates(map[string]interface{}{"value": ""}).Error; err != nil {
if err := tx.Model(&model.Setting{}).
Where("key = ? AND value = ?", "SecurityEntrance", "onepanel").
Updates(map[string]interface{}{"value": ""}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "SSLType", Value: "self"}).Error; err != nil {

View File

@ -21,6 +21,7 @@ func Init() {
port := "9999"
mode := ""
version := "v1.0.0"
username, password, entrance := "", "", ""
fileOp := files.NewFileOp()
v := viper.NewWithOptions()
v.SetConfigType("yaml")
@ -40,8 +41,11 @@ func Init() {
}
} else {
baseDir = loadParams("BASE_DIR")
port = loadParams("PANEL_PORT")
version = loadParams("ORIGINAL_INSTALLED_VERSION")
port = loadParams("ORIGINAL_PORT")
version = loadParams("ORIGINAL_VERSION")
username = loadParams("ORIGINAL_USERNAME")
password = loadParams("ORIGINAL_PASSWORD")
entrance = loadParams("ORIGINAL_ENTRANCE")
if strings.HasSuffix(baseDir, "/") {
baseDir = baseDir[:strings.LastIndex(baseDir, "/")]
@ -60,14 +64,25 @@ func Init() {
if err := v.Unmarshal(&serverConfig); err != nil {
panic(err)
}
if mode == "dev" && fileOp.Stat("/opt/1panel/conf/app.yaml") && serverConfig.System.BaseDir != "" {
baseDir = serverConfig.System.BaseDir
}
if mode == "dev" && fileOp.Stat("/opt/1panel/conf/app.yaml") && serverConfig.System.Port != "" {
port = serverConfig.System.Port
}
if mode == "dev" && fileOp.Stat("/opt/1panel/conf/app.yaml") && serverConfig.System.Version != "" {
version = serverConfig.System.Version
if mode == "dev" && fileOp.Stat("/opt/1panel/conf/app.yaml") {
if serverConfig.System.BaseDir != "" {
baseDir = serverConfig.System.BaseDir
}
if serverConfig.System.Port != "" {
port = serverConfig.System.Port
}
if serverConfig.System.Version != "" {
version = serverConfig.System.Version
}
if serverConfig.System.Username != "" {
version = serverConfig.System.Username
}
if serverConfig.System.Password != "" {
version = serverConfig.System.Password
}
if serverConfig.System.Entrance != "" {
version = serverConfig.System.Entrance
}
}
global.CONF = serverConfig
@ -81,6 +96,9 @@ func Init() {
global.CONF.System.TmpDir = global.CONF.System.DataDir + "/tmp"
global.CONF.System.Port = port
global.CONF.System.Version = version
global.CONF.System.Username = username
global.CONF.System.Password = password
global.CONF.System.Entrance = entrance
global.Viper = v
}

View File

@ -22,7 +22,6 @@ func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) {
router.POST("/expired/handle", baseApi.HandlePasswordExpired)
settingRouter.GET("/search/available", baseApi.GetSystemAvailable)
settingRouter.POST("/update", baseApi.UpdateSetting)
settingRouter.POST("/entrance/enable", baseApi.UpdateEntrance)
settingRouter.POST("/port/update", baseApi.UpdatePort)
settingRouter.POST("/ssl/update", baseApi.UpdateSSL)
settingRouter.GET("/ssl/info", baseApi.LoadFromCert)

View File

@ -24,7 +24,7 @@ var resetMFACmd = &cobra.Command{
}
var resetSSLCmd = &cobra.Command{
Use: "reset-ssl",
Use: "reset-https",
Short: "取消 1Panel https 方式登录",
RunE: func(cmd *cobra.Command, args []string) error {
db, err := loadDBConn()
@ -44,6 +44,6 @@ var resetEntranceCmd = &cobra.Command{
return err
}
return setSettingByKey(db, "SecurityEntranceStatus", "disable")
return setSettingByKey(db, "SecurityEntrance", "")
},
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,6 @@ export namespace Setting {
language: string;
serverPort: number;
securityEntranceStatus: string;
ssl: string;
sslType: string;
securityEntrance: string;

View File

@ -16,10 +16,6 @@ export const updateSetting = (param: Setting.SettingUpdate) => {
return http.post(`/settings/update`, param);
};
export const updateEntrance = (param: Setting.SettingUpdate) => {
return http.post(`/settings/entrance/enable`, param);
};
export const updatePassword = (param: Setting.PasswordUpdate) => {
return http.post(`/settings/password/update`, param);
};

View File

@ -869,10 +869,11 @@ const message = {
path: 'Path',
safe: 'Security',
safeEntrance: 'Security entrance',
entrance: 'Entrance',
entranceHelper: 'Enabling secure entry will only allow logging in to the panel through specified secure entry.',
entranceError:
'Please enter a secure login entry point of 6-10 characters, only numbers or letters are supported.',
entranceInputHelper: 'When the security entry is set to blank, the security entry is cancelled.',
expirationTime: 'Expiration Time',
unSetting: 'Not Set',
noneSetting:

View File

@ -830,9 +830,6 @@ const message = {
portHelper: '建议端口范围8888 - 65535注意有安全组的服务器请提前在安全组放行新端口',
portChange: '端口修改',
portChangeHelper: '服务端口修改需要重启服务是否继续',
entrance: '安全入口',
entranceHelper: '开启安全入口后只能通过指定安全入口登录面板',
entranceError: '请输入 6-10 位安全登录入口仅支持输入数字或字母',
theme: '主题颜色',
componentSize: '组件大小',
dark: '暗色',
@ -924,8 +921,10 @@ const message = {
hasNewVersion: '有新版本',
safe: '安全',
safeEntrance: '安全入口',
safeEntranceHelper: '面板管理入口设置后只能通过指定安全入口登录面板: onepanel',
entrance: '安全入口',
entranceHelper: '开启安全入口后只能通过指定安全入口登录面板',
entranceError: '请输入 6-10 位安全登录入口仅支持输入数字或字母',
entranceInputHelper: '安全入口设置为空时则取消安全入口',
expirationTime: '密码过期时间',
unSetting: '未设置',
noneSetting: '为面板密码设置过期时间过期后需要重新设置密码',

View File

@ -502,7 +502,7 @@ const loadUpgradeStatus = async () => {
const loadSafeStatus = async () => {
const res = await getSettingInfo();
isSafety.value = res.data.securityEntranceStatus === 'enable';
isSafety.value = res.data.securityEntrance;
};
onMounted(() => {

View File

@ -183,9 +183,6 @@ const loadDetail = (log: string) => {
if (log.indexOf('[SessionTimeout]') !== -1) {
return log.replace('[SessionTimeout]', '[' + i18n.global.t('setting.sessionTimeout') + ']');
}
if (log.indexOf('SecurityEntranceStatus') !== -1) {
return log.replace('[SecurityEntranceStatus]', '[' + i18n.global.t('setting.entrance') + ']');
}
if (log.indexOf('SecurityEntrance') !== -1) {
return log.replace('[SecurityEntrance]', '[' + i18n.global.t('setting.entrance') + ']');
}

View File

@ -21,7 +21,7 @@
</el-form-item>
<el-form-item :label="$t('setting.passwd')" :rules="Rules.requiredInput" prop="password">
<el-input type="password" clearable disabled v-model="form.password">
<el-input type="password" disabled v-model="form.password">
<template #append>
<el-button style="width: 85px" icon="Setting" @click="onChangePassword">
{{ $t('commons.button.set') }}

View File

@ -0,0 +1,100 @@
<template>
<div>
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('setting.entrance')" :back="handleClose" />
</template>
<el-form label-position="top" v-loading="loading">
<el-form-item :label="$t('setting.entrance')" prop="days">
<el-input clearable v-model="securityEntrance">
<template #append>
<el-button @click="random" icon="RefreshRight"></el-button>
</template>
</el-input>
<span class="input-help">
{{ $t('setting.entranceInputHelper') }}
</span>
<span class="input-error" v-if="codeError">
{{ $t('setting.entranceError') }}
</span>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="drawerVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="submitEntrance">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { updateSetting } from '@/api/modules/setting';
import { GlobalStore } from '@/store';
import { getRandomStr } from '@/utils/util';
const globalStore = GlobalStore();
const emit = defineEmits<{ (e: 'search'): void }>();
interface DialogProps {
securityEntrance: string;
}
const securityEntrance = ref();
const drawerVisiable = ref();
const loading = ref();
const codeError = ref();
const acceptParams = (params: DialogProps): void => {
securityEntrance.value = params.securityEntrance;
drawerVisiable.value = true;
};
const random = async () => {
securityEntrance.value = getRandomStr(8);
};
const submitEntrance = async () => {
if (securityEntrance.value !== '') {
const reg = /^[A-Za-z0-9]{6,10}$/;
if (!reg.test(securityEntrance.value)) {
codeError.value = true;
return;
}
}
let param = {
key: 'SecurityEntrance',
value: securityEntrance.value,
};
loading.value = true;
await updateSetting(param)
.then(() => {
globalStore.entrance = securityEntrance.value;
loading.value = false;
drawerVisiable.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
emit('search');
})
.catch(() => {
loading.value = false;
});
};
const handleClose = () => {
drawerVisiable.value = false;
};
defineExpose({
acceptParams,
});
</script>
<style scoped lang="scss">
.margintop {
margin-top: 10px;
}
</style>

View File

@ -21,32 +21,26 @@
</el-form-item>
<el-form-item :label="$t('setting.entrance')">
<el-switch
@change="handleEntrance"
v-model="form.securityEntranceStatus"
active-value="enable"
inactive-value="disable"
/>
<span class="input-help">
{{ $t('setting.entranceHelper') }}
</span>
<el-input
@blur="codeError = false"
v-if="isEntranceShow"
type="password"
show-password
clearable
disabled
v-if="form.securityEntrance"
v-model="form.securityEntrance"
>
<template #append>
<el-button style="width: 85px" @click="onSaveEntrance" icon="Collection">
{{ $t('commons.button.save') }}
<el-button style="width: 85px" @click="onChangeEntrance" icon="Setting">
{{ $t('commons.button.set') }}
</el-button>
</template>
</el-input>
<span class="input-error" v-if="codeError">
{{ $t('setting.entranceError') }}
</span>
<el-input disabled v-if="!form.securityEntrance" v-model="unset">
<template #append>
<el-button style="width: 85px" @click="onChangeEntrance" icon="Setting">
{{ $t('commons.button.set') }}
</el-button>
</template>
</el-input>
<span class="input-help">{{ $t('setting.entranceHelper') }}</span>
</el-form-item>
<el-form-item :label="$t('setting.expirationTime')" prop="expirationTime">
@ -142,25 +136,9 @@
</el-form>
</template>
</LayoutContent>
<el-drawer v-model="timeoutVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('setting.expirationTime')" :back="handleClose" />
</template>
<el-form ref="timeoutFormRef" label-position="top" :model="timeoutForm">
<el-form-item :label="$t('setting.days')" prop="days" :rules="[Rules.number, checkNumberRange(0, 60)]">
<el-input clearable v-model.number="timeoutForm.days" />
<span class="input-help">{{ $t('setting.expirationHelper') }}</span>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="timeoutVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="submitTimeout(timeoutFormRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-drawer>
<EntranceSetting ref="entranceRef" @search="search" />
<TimeoutSetting ref="timeoutref" @search="search" />
</div>
</template>
@ -170,7 +148,8 @@ import { ElForm, ElMessageBox } from 'element-plus';
import { Setting } from '@/api/interface/setting';
import LayoutContent from '@/layout/layout-content.vue';
import SSLSetting from '@/views/setting/safe/ssl/index.vue';
import DrawerHeader from '@/components/drawer-header/index.vue';
import TimeoutSetting from '@/views/setting/safe/timeout/index.vue';
import EntranceSetting from '@/views/setting/safe/entrance/index.vue';
import {
updateSetting,
getMFA,
@ -178,21 +157,18 @@ import {
getSettingInfo,
updatePort,
getSystemAvailable,
updateEntrance,
updateSSL,
} from '@/api/modules/setting';
import i18n from '@/lang';
import { Rules, checkNumberRange } from '@/global/form-rules';
import { dateFormatSimple } from '@/utils/util';
import { Rules } from '@/global/form-rules';
import { MsgError, MsgSuccess } from '@/utils/message';
import { GlobalStore } from '@/store';
const globalStore = GlobalStore();
const loading = ref(false);
const entranceRef = ref();
const timeoutref = ref();
const form = reactive({
serverPort: 9999,
securityEntranceStatus: 'disable',
ssl: 'disable',
sslType: 'self',
securityEntrance: '',
@ -203,20 +179,15 @@ const form = reactive({
mfaSecret: 'disable',
});
type FormInstance = InstanceType<typeof ElForm>;
const timeoutFormRef = ref<FormInstance>();
const timeoutVisiable = ref<boolean>(false);
const timeoutForm = reactive({
days: 0,
});
const sslShow = ref();
const oldSSLStatus = ref();
const unset = ref(i18n.global.t('setting.unSetting'));
const search = async () => {
const res = await getSettingInfo();
form.serverPort = Number(res.data.serverPort);
form.securityEntranceStatus = res.data.securityEntranceStatus;
isEntranceShow.value = res.data.securityEntranceStatus === 'enable';
form.ssl = res.data.ssl;
oldSSLStatus.value = res.data.ssl;
form.sslType = res.data.sslType;
@ -231,9 +202,6 @@ const search = async () => {
form.mfaSecret = res.data.mfaSecret;
};
const isEntranceShow = ref(false);
const codeError = ref(false);
const isMFAShow = ref<boolean>(false);
const otp = reactive<Setting.MFAInfo>({
secret: '',
@ -322,23 +290,8 @@ const handleMFA = async () => {
}
};
const handleEntrance = async () => {
if (form.securityEntranceStatus === 'enable') {
isEntranceShow.value = true;
} else {
isEntranceShow.value = false;
loading.value = true;
await updateSetting({ key: 'SecurityEntranceStatus', value: 'disable' })
.then(() => {
globalStore.entrance = '';
loading.value = false;
search();
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
loading.value = false;
});
}
const onChangeEntrance = async () => {
entranceRef.value.acceptParams({ securityEntrance: form.securityEntrance });
};
const handleSSL = async () => {
@ -368,29 +321,6 @@ const handleSSL = async () => {
});
};
const onSaveEntrance = async () => {
const reg = /^[A-Za-z0-9]{6,10}$/;
if ((!reg.test(form.securityEntrance) && form.securityEntrance !== '') || form.securityEntrance === '') {
codeError.value = true;
return;
}
loading.value = true;
await updateEntrance({ key: 'SecurityEntrance', value: form.securityEntrance })
.then(() => {
globalStore.entrance = form.securityEntrance;
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
search();
})
.catch(() => {
loading.value = false;
});
};
const handleClose = () => {
timeoutVisiable.value = false;
};
const onBind = async () => {
if (!mfaCode.value) {
MsgError(i18n.global.t('commons.msg.comfimNoNull', ['code']));
@ -415,28 +345,7 @@ const onCancelMfaBind = async () => {
};
const onChangeExpirationTime = async () => {
timeoutForm.days = form.expirationDays;
timeoutVisiable.value = true;
};
const submitTimeout = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let time = new Date(new Date().getTime() + 3600 * 1000 * 24 * timeoutForm.days);
loading.value = true;
await updateSetting({ key: 'ExpirationDays', value: timeoutForm.days + '' })
.then(() => {
loading.value = false;
search();
loadTimeOut();
form.expirationTime = dateFormatSimple(time);
timeoutVisiable.value = false;
})
.catch(() => {
loading.value = false;
});
});
timeoutref.value.acceptParams({ expirationDays: form.expirationDays });
};
function loadTimeOut() {

View File

@ -0,0 +1,81 @@
<template>
<div>
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('setting.expirationTime')" :back="handleClose" />
</template>
<el-form ref="timeoutFormRef" label-position="top" :model="form">
<el-form-item :label="$t('setting.days')" prop="days" :rules="[Rules.number, checkNumberRange(0, 60)]">
<el-input clearable v-model.number="form.days" />
<span class="input-help">{{ $t('setting.expirationHelper') }}</span>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="drawerVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="submitTimeout(timeoutFormRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { MsgSuccess } from '@/utils/message';
import { updateSetting } from '@/api/modules/setting';
import { FormInstance } from 'element-plus';
import { Rules, checkNumberRange } from '@/global/form-rules';
import i18n from '@/lang';
const emit = defineEmits<{ (e: 'search'): void }>();
interface DialogProps {
expirationDays: number;
}
const drawerVisiable = ref();
const loading = ref();
const timeoutFormRef = ref();
const form = reactive({
days: 0,
});
const acceptParams = (params: DialogProps): void => {
form.days = params.expirationDays;
drawerVisiable.value = true;
};
const submitTimeout = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
loading.value = true;
await updateSetting({ key: 'ExpirationDays', value: form.days + '' })
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
emit('search');
drawerVisiable.value = false;
})
.catch(() => {
loading.value = false;
});
});
};
const handleClose = () => {
drawerVisiable.value = false;
};
defineExpose({
acceptParams,
});
</script>
<style scoped lang="scss">
.margintop {
margin-top: 10px;
}
</style>