mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-24 02:59:16 +08:00
feat: 完成面板设置前端界面效果
This commit is contained in:
parent
6ceb040061
commit
2a1403904f
@ -17,7 +17,7 @@ func (b *BaseApi) GetSettingInfo(c *gin.Context) {
|
||||
helper.SuccessWithData(c, setting)
|
||||
}
|
||||
|
||||
func (b *BaseApi) UpdateInfo(c *gin.Context) {
|
||||
func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||
var req dto.SettingUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
|
@ -2,10 +2,10 @@ package dto
|
||||
|
||||
type SettingInfo struct {
|
||||
UserName string `json:"userName"`
|
||||
Password string `json:"password"`
|
||||
Email string `json:"email"`
|
||||
|
||||
SessionTimeout string `json:"sessionTimeout"`
|
||||
LocalTime string `json:"localTime"`
|
||||
|
||||
PanelName string `json:"panelName"`
|
||||
Theme string `json:"theme"`
|
||||
@ -13,6 +13,7 @@ type SettingInfo struct {
|
||||
|
||||
ServerPort string `json:"serverPort"`
|
||||
SecurityEntrance string `json:"securityEntrance"`
|
||||
PasswordTimeOut string `json:"passwordTimeOut"`
|
||||
ComplexityVerification string `json:"complexityVerification"`
|
||||
MFAStatus string `json:"mfaStatus"`
|
||||
|
||||
|
@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/constant"
|
||||
@ -35,6 +36,7 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
|
||||
if err := json.Unmarshal(arr, &info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info.LocalTime = time.Now().Format("2006.01.02 15:04:05")
|
||||
return &info, err
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/app/model"
|
||||
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
@ -90,6 +92,9 @@ var AddTableSetting = &gormigrate.Migration{
|
||||
if err := tx.Create(&model.Setting{Key: "SessionTimeout", Value: "86400"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "LocalTime", Value: ""}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Create(&model.Setting{Key: "ServerPort", Value: "4004"}).Error; err != nil {
|
||||
return err
|
||||
@ -97,6 +102,9 @@ var AddTableSetting = &gormigrate.Migration{
|
||||
if err := tx.Create(&model.Setting{Key: "SecurityEntrance", Value: "/89dc6ae8"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "PasswordTimeOut", Value: time.Now().AddDate(0, 0, 10).Format("2016.01.02 15:04:05")}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "ComplexityVerification", Value: "enable"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -9,9 +9,10 @@ import (
|
||||
type SettingRouter struct{}
|
||||
|
||||
func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) {
|
||||
monitorRouter := Router.Group("settings").Use(middleware.JwtAuth()).Use(middleware.SessionAuth())
|
||||
settingRouter := Router.Group("settings").Use(middleware.JwtAuth()).Use(middleware.SessionAuth())
|
||||
baseApi := v1.ApiGroupApp.BaseApi
|
||||
{
|
||||
monitorRouter.POST("/search", baseApi.GetSettingInfo)
|
||||
settingRouter.POST("/search", baseApi.GetSettingInfo)
|
||||
settingRouter.PUT("", baseApi.UpdateSetting)
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ export namespace Setting {
|
||||
email: string;
|
||||
|
||||
sessionTimeout: string;
|
||||
localTime: string;
|
||||
|
||||
panelName: string;
|
||||
theme: string;
|
||||
@ -12,6 +13,7 @@ export namespace Setting {
|
||||
|
||||
serverPort: string;
|
||||
securityEntrance: string;
|
||||
passwordTimeOut: string;
|
||||
complexityVerification: string;
|
||||
mfaStatus: string;
|
||||
|
||||
@ -23,4 +25,13 @@ export namespace Setting {
|
||||
weChatVars: string;
|
||||
dingVars: string;
|
||||
}
|
||||
export interface SettingUpdate {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
export interface PasswordUpdate {
|
||||
oldPassword: string;
|
||||
newPassword: string;
|
||||
retryPassword: string;
|
||||
}
|
||||
}
|
||||
|
@ -4,3 +4,7 @@ import { Setting } from '../interface/setting';
|
||||
export const getSettingInfo = () => {
|
||||
return http.post<Setting.SettingInfo>(`/settings/search`);
|
||||
};
|
||||
|
||||
export const updateSetting = (param: Setting.SettingUpdate) => {
|
||||
return http.put(`/settings`, param);
|
||||
};
|
||||
|
@ -18,6 +18,16 @@ export default {
|
||||
dateStart: '开始日期',
|
||||
dateEnd: '结束日期',
|
||||
},
|
||||
personal: {
|
||||
about: '关于',
|
||||
project_url: '项目地址',
|
||||
issue: '问题反馈',
|
||||
talk: '参与讨论',
|
||||
star: '点亮 Star',
|
||||
version: '版本',
|
||||
ko_introduction:
|
||||
'是一个开源的轻量级 Kubernetes 发行版,专注于帮助企业规划、部署和运营生产级别的 Kubernetes 集群。',
|
||||
},
|
||||
table: {
|
||||
name: '名称',
|
||||
group: '组',
|
||||
@ -47,6 +57,7 @@ export default {
|
||||
rule: {
|
||||
username: '请输入用户名',
|
||||
password: '请输入密码',
|
||||
rePassword: '密码不一致,请检查后重新输入',
|
||||
requiredInput: '请填写必填项',
|
||||
requiredSelect: '请选择必选项',
|
||||
commonName: '支持英文、中文、数字、.-_,长度1-30',
|
||||
@ -84,7 +95,10 @@ export default {
|
||||
menu: {
|
||||
home: '概览',
|
||||
demo: '样例',
|
||||
monitor: '监控',
|
||||
terminal: '终端',
|
||||
operations: '操作日志',
|
||||
files: '文件管理',
|
||||
apps: '应用商店',
|
||||
website: '网站',
|
||||
project: '项目',
|
||||
@ -95,12 +109,8 @@ export default {
|
||||
plan: '计划任务',
|
||||
host: '主机',
|
||||
security: '安全',
|
||||
systemConfig: '面板设置',
|
||||
settings: '面板设置',
|
||||
toolbox: '工具箱',
|
||||
monitor: '监控',
|
||||
operations: '操作记录',
|
||||
files: '文件管理',
|
||||
settings: '系统设置',
|
||||
},
|
||||
home: {
|
||||
welcome: '欢迎使用',
|
||||
|
@ -1,22 +0,0 @@
|
||||
import { Layout } from '@/routers/constant';
|
||||
|
||||
const systemConfigRouter = {
|
||||
sort: 8,
|
||||
path: '/configs',
|
||||
component: Layout,
|
||||
redirect: '/configs',
|
||||
meta: {
|
||||
icon: 'p-config',
|
||||
title: 'menu.systemConfig',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '/configs',
|
||||
name: 'SystemConfig',
|
||||
component: () => import('@/views/system-config/index.vue'),
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default systemConfigRouter;
|
@ -1,13 +1,13 @@
|
||||
import { Layout } from '@/routers/constant';
|
||||
|
||||
const settingRouter = {
|
||||
sort: 3,
|
||||
sort: 7,
|
||||
path: '/settings',
|
||||
component: Layout,
|
||||
redirect: '/setting',
|
||||
meta: {
|
||||
title: 'menu.settings',
|
||||
icon: 'Setting',
|
||||
icon: 'p-config',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
@ -114,3 +114,13 @@
|
||||
.form-button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.input-help {
|
||||
font-size: 12px;
|
||||
word-break: break-all;
|
||||
color: #4A4B4D;
|
||||
transform: scale(0.9);
|
||||
transform-origin: left;
|
||||
width: 110%;
|
||||
display: inline-block;
|
||||
}
|
@ -34,7 +34,7 @@
|
||||
</span>
|
||||
</template>
|
||||
<Terminal
|
||||
style="height: calc(100vh - 210px); background-color: #000"
|
||||
style="height: calc(100vh - 150px); background-color: #000"
|
||||
:ref="'Ref' + item.key"
|
||||
:wsID="item.wsID"
|
||||
:terminalID="item.key"
|
||||
@ -106,7 +106,7 @@
|
||||
</el-tab-pane>
|
||||
<div v-if="terminalTabs.length === 0">
|
||||
<el-empty
|
||||
style="background-color: #000; height: calc(100vh - 210px)"
|
||||
style="background-color: #000; height: calc(100vh - 150px)"
|
||||
:description="$t('terminal.emptyTerminal')"
|
||||
></el-empty>
|
||||
</div>
|
||||
@ -182,9 +182,9 @@ import i18n from '@/lang';
|
||||
import { ElForm } from 'element-plus';
|
||||
import { Host } from '@/api/interface/host';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import Terminal from '@/views/terminal/terminal/index.vue';
|
||||
import HostTab from '@/views/terminal/host/index.vue';
|
||||
import CommandTab from '@/views/terminal/command/index.vue';
|
||||
import Terminal from '@/views/host/terminal/terminal/index.vue';
|
||||
import HostTab from '@/views/host/terminal/host/index.vue';
|
||||
import CommandTab from '@/views/host/terminal/command/index.vue';
|
||||
import type Node from 'element-plus/es/components/tree/src/model/node';
|
||||
import { ElTree } from 'element-plus';
|
||||
import screenfull from 'screenfull';
|
||||
|
@ -3,100 +3,45 @@
|
||||
<el-card class="topCard">
|
||||
<el-radio-group v-model="activeNames">
|
||||
<el-radio-button class="topButton" size="large" label="all">全部</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="user">用户设置</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="panel">面板设置</el-radio-button>
|
||||
<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="panel">面板</el-radio-button>
|
||||
<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>
|
||||
<el-form :model="form" label-position="left" label-width="120px">
|
||||
<el-card v-if="activeNames === 'all' || activeNames === 'user'" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>用户设置</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="用户名">
|
||||
<el-input size="small" clearable v-model="form.userName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="密码">
|
||||
<el-input type="password" clearable show-password size="small" v-model="form.password" />
|
||||
</el-form-item>
|
||||
<el-form-item label="主题色">
|
||||
<el-radio-group size="small" v-model="form.theme">
|
||||
<el-radio-button label="black">
|
||||
<el-icon><Moon /></el-icon>黑金
|
||||
</el-radio-button>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
placement="top"
|
||||
content="选择自动设置,将会在晚 6 点到次日早 6 点间自动切换到黑金主题。"
|
||||
>
|
||||
<el-radio-button label="auto" icon="Sunny">
|
||||
<el-icon><MagicStick /></el-icon>自动
|
||||
</el-radio-button>
|
||||
</el-tooltip>
|
||||
<el-radio-button label="write">
|
||||
<el-icon><Sunny /></el-icon>白金
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="系统语言">
|
||||
<el-radio-group size="small" v-model="form.language">
|
||||
<el-radio-button label="ch">中文 </el-radio-button>
|
||||
<el-radio-button label="en">English </el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="small" icon="Pointer">更新用户设置</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card v-if="activeNames === 'all' || activeNames === 'panel'" style="margin-top: 10px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>面板设置</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="超时时间">
|
||||
<el-input size="small" v-model="form.sessionTimeout" />
|
||||
</el-form-item>
|
||||
<el-form-item label="同步时间">
|
||||
<el-input size="small" v-model="form.password" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
<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" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, reactive } from 'vue';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getSettingInfo } 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';
|
||||
|
||||
const activeNames = ref('all');
|
||||
let form = reactive<Setting.SettingInfo>({
|
||||
let form = ref<Setting.SettingInfo>({
|
||||
userName: '',
|
||||
password: '',
|
||||
email: '',
|
||||
sessionTimeout: '',
|
||||
localTime: '',
|
||||
panelName: '',
|
||||
theme: '',
|
||||
language: '',
|
||||
serverPort: '',
|
||||
securityEntrance: '',
|
||||
passwordTimeOut: '',
|
||||
complexityVerification: '',
|
||||
mfaStatus: '',
|
||||
monitorStatus: '',
|
||||
@ -109,9 +54,10 @@ let form = reactive<Setting.SettingInfo>({
|
||||
|
||||
const search = async () => {
|
||||
const res = await getSettingInfo();
|
||||
console.log(res);
|
||||
form = res.data;
|
||||
form.value = res.data;
|
||||
form.value.password = '******';
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
});
|
||||
|
0
frontend/src/views/setting/tabs/about.vue
Normal file
0
frontend/src/views/setting/tabs/about.vue
Normal file
17
frontend/src/views/setting/tabs/backup.vue
Normal file
17
frontend/src/views/setting/tabs/backup.vue
Normal file
@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<el-card style="margin-top: 10px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>备份</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="8"> </el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue';
|
||||
onMounted(() => {});
|
||||
</script>
|
152
frontend/src/views/setting/tabs/message.vue
Normal file
152
frontend/src/views/setting/tabs/message.vue
Normal file
@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<el-form size="small" :model="form" label-position="left" label-width="120px">
|
||||
<el-card style="margin-top: 10px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>通知</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="通知方式">
|
||||
<el-radio-group v-model="form.settingInfo.messageType">
|
||||
<el-radio-button label="none">关闭</el-radio-button>
|
||||
<el-radio-button label="email">email</el-radio-button>
|
||||
<el-radio-button label="wechat">企业微信</el-radio-button>
|
||||
<el-radio-button label="dingding">钉钉</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div v-if="form.settingInfo.messageType === 'none'">
|
||||
<el-form-item>
|
||||
<el-button @click="SaveSetting()">关闭消息通知</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="form.settingInfo.messageType === 'email'">
|
||||
<el-form-item label="邮箱服务名称">
|
||||
<el-input clearable v-model="emailVars.serverName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱地址">
|
||||
<el-input clearable v-model="emailVars.serverAddr" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱SMTP授权码">
|
||||
<el-input clearable v-model="emailVars.serverSMTP" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="SaveSetting()">保存并启用</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="form.settingInfo.messageType === 'wechat'">
|
||||
<el-form-item label="orpid">
|
||||
<el-input clearable v-model="weChatVars.orpid" />
|
||||
</el-form-item>
|
||||
<el-form-item label="corpsecret">
|
||||
<el-input clearable v-model="weChatVars.corpsecret" />
|
||||
</el-form-item>
|
||||
<el-form-item label="touser">
|
||||
<el-input clearable v-model="weChatVars.touser" />
|
||||
</el-form-item>
|
||||
<el-form-item label="agentid">
|
||||
<el-input clearable v-model="weChatVars.agentid" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="SaveSetting()">保存并启用</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="form.settingInfo.messageType === 'dingding'">
|
||||
<el-form-item label="webhook token">
|
||||
<el-input clearable v-model="dingVars.webhookToken" />
|
||||
</el-form-item>
|
||||
<el-form-item label="密钥">
|
||||
<el-input clearable v-model="dingVars.secret" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱 SMTP 授权码">
|
||||
<el-input clearable v-model="emailVars.serverSMTP" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="SaveSetting()">保存并启用</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { updateSetting } from '@/api/modules/setting';
|
||||
import i18n from '@/lang';
|
||||
|
||||
interface Props {
|
||||
settingInfo: any;
|
||||
}
|
||||
const form = withDefaults(defineProps<Props>(), {
|
||||
settingInfo: {
|
||||
messageType: '',
|
||||
emailVars: '',
|
||||
weChatVars: '',
|
||||
dingVars: '',
|
||||
},
|
||||
});
|
||||
|
||||
const emailVars = ref({
|
||||
serverName: '',
|
||||
serverAddr: '',
|
||||
serverSMTP: '',
|
||||
});
|
||||
const weChatVars = ref({
|
||||
orpid: '',
|
||||
corpsecret: '',
|
||||
touser: '',
|
||||
agentid: '',
|
||||
});
|
||||
const dingVars = ref({
|
||||
webhookToken: '',
|
||||
secret: '',
|
||||
});
|
||||
|
||||
const SaveSetting = async () => {
|
||||
let settingKey = '';
|
||||
let settingVal = '';
|
||||
switch (form.settingInfo.messageType) {
|
||||
case 'none':
|
||||
settingVal = '';
|
||||
break;
|
||||
case 'email':
|
||||
settingVal = JSON.stringify(emailVars.value);
|
||||
settingKey = 'EmailVars';
|
||||
break;
|
||||
case 'wechat':
|
||||
settingVal = JSON.stringify(emailVars.value);
|
||||
settingKey = 'WeChatVars';
|
||||
break;
|
||||
case 'dingding':
|
||||
settingVal = JSON.stringify(emailVars.value);
|
||||
settingKey = 'DingVars';
|
||||
break;
|
||||
}
|
||||
let param = {
|
||||
key: settingKey,
|
||||
value: settingVal,
|
||||
};
|
||||
await updateSetting({ key: 'MessageType', value: form.settingInfo.messageType });
|
||||
await updateSetting(param);
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
};
|
||||
onMounted(() => {
|
||||
switch (form.settingInfo.messageType) {
|
||||
case 'email':
|
||||
emailVars.value = JSON.parse(form.settingInfo.emailVars);
|
||||
console.log(emailVars.value);
|
||||
break;
|
||||
case 'wechat':
|
||||
weChatVars.value = JSON.parse(form.settingInfo.weChatVars);
|
||||
break;
|
||||
case 'dingding':
|
||||
dingVars.value = JSON.parse(form.settingInfo.dingVars);
|
||||
break;
|
||||
}
|
||||
});
|
||||
</script>
|
64
frontend/src/views/setting/tabs/monitor.vue
Normal file
64
frontend/src/views/setting/tabs/monitor.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<el-form size="small" :model="form" label-position="left" label-width="120px">
|
||||
<el-card style="margin-top: 10px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>监控</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="开启监控">
|
||||
<el-switch
|
||||
v-model="form.settingInfo.monitorStatus"
|
||||
active-value="enable"
|
||||
inactive-value="disable"
|
||||
@change="SaveSetting('MonitorStatus', form.settingInfo.monitorStatus)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="过期时间">
|
||||
<el-input clearable v-model="form.settingInfo.monitorStoreDays">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('MonitorStoreDays', form.settingInfo.monitorStoreDays)"
|
||||
icon="Collection"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="Delete"> 清空监控记录 </el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { updateSetting } from '@/api/modules/setting';
|
||||
import i18n from '@/lang';
|
||||
|
||||
interface Props {
|
||||
settingInfo: any;
|
||||
}
|
||||
const form = withDefaults(defineProps<Props>(), {
|
||||
settingInfo: {
|
||||
monitorStatus: '',
|
||||
monitorStoreDays: '',
|
||||
},
|
||||
});
|
||||
|
||||
const SaveSetting = async (key: string, val: string) => {
|
||||
let param = {
|
||||
key: key,
|
||||
value: val,
|
||||
};
|
||||
await updateSetting(param);
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
};
|
||||
</script>
|
214
frontend/src/views/setting/tabs/panel.vue
Normal file
214
frontend/src/views/setting/tabs/panel.vue
Normal file
@ -0,0 +1,214 @@
|
||||
<template>
|
||||
<el-form size="small" :model="form" label-position="left" label-width="120px">
|
||||
<el-card style="margin-top: 20px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>面板</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="用户名">
|
||||
<el-input clearable v-model="form.settingInfo.userName">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('UserName', form.settingInfo.userName)"
|
||||
icon="Collection"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码">
|
||||
<el-input type="password" clearable disabled v-model="form.settingInfo.password">
|
||||
<template #append>
|
||||
<el-button icon="Setting" @click="passwordVisiable = true">设置</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱">
|
||||
<el-input clearable v-model="form.settingInfo.email">
|
||||
<template #append>
|
||||
<el-button @click="SaveSetting('Email', form.settingInfo.email)" icon="Collection">
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<div><span class="input-help">用于密码找回</span></div>
|
||||
</el-form-item>
|
||||
<el-form-item label="面板别名">
|
||||
<el-input clearable v-model="form.settingInfo.panelName">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('PanelName', form.settingInfo.panelName)"
|
||||
icon="Collection"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="主题色">
|
||||
<el-radio-group
|
||||
@change="SaveSetting('Theme', form.settingInfo.theme)"
|
||||
v-model="form.settingInfo.theme"
|
||||
>
|
||||
<el-radio-button label="black">
|
||||
<el-icon><Moon /></el-icon>黑金
|
||||
</el-radio-button>
|
||||
<el-radio-button label="auto" icon="Sunny">
|
||||
<el-icon><MagicStick /></el-icon>自动
|
||||
</el-radio-button>
|
||||
<el-radio-button label="write">
|
||||
<el-icon><Sunny /></el-icon>白金
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
<div>
|
||||
<span class="input-help">
|
||||
选择自动设置,将会在晚 6 点到次日早 6 点间自动切换到黑金主题。
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="系统语言">
|
||||
<el-radio-group
|
||||
@change="SaveSetting('Language', form.settingInfo.language)"
|
||||
v-model="form.settingInfo.language"
|
||||
>
|
||||
<el-radio-button label="ch">中文 </el-radio-button>
|
||||
<el-radio-button label="en">English </el-radio-button>
|
||||
</el-radio-group>
|
||||
<div>
|
||||
<span class="input-help">
|
||||
默认跟随浏览器语言,设置后只对当前浏览器生效,更换浏览器后需要重新设置。
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="超时时间">
|
||||
<el-input v-model="form.settingInfo.sessionTimeout">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('SessionTimeout', form.settingInfo.sessionTimeout)"
|
||||
icon="Collection"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<div>
|
||||
<span class="input-help">如果用户超过 86400秒未操作面板,面板将自动退出登录 </span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="同步时间">
|
||||
<el-input v-model="form.settingInfo.localTime">
|
||||
<template #append>
|
||||
<el-button icon="Refresh">同步</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
<el-dialog v-model="passwordVisiable" title="密码修改" width="30%">
|
||||
<el-form
|
||||
size="small"
|
||||
ref="passFormRef"
|
||||
label-width="80px"
|
||||
label-position="left"
|
||||
:model="passForm"
|
||||
:rules="passRules"
|
||||
>
|
||||
<el-form-item label="原密码" prop="oldPassword">
|
||||
<el-input type="password" show-password clearable v-model="passForm.oldPassword" />
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码" prop="newPassword">
|
||||
<el-input type="password" show-password clearable v-model="passForm.newPassword" />
|
||||
</el-form-item>
|
||||
<el-form-item label="确认密码" prop="retryPassword">
|
||||
<el-input type="password" show-password clearable v-model="passForm.retryPassword" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="passwordVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||
<el-button @click="submitChangePassword()">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ElMessage, ElForm } from 'element-plus';
|
||||
import { updateSetting } 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 { Rules } from '@/global/form-rues';
|
||||
|
||||
const i18n = useI18n();
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
type FormInstance = InstanceType<typeof ElForm>;
|
||||
const passFormRef = ref<FormInstance>();
|
||||
const passRules = reactive({
|
||||
oldPassword: [Rules.requiredInput],
|
||||
newPassword: [Rules.requiredInput],
|
||||
retryPassword: [Rules.requiredInput, { validator: checkPassword, trigger: 'blur' }],
|
||||
});
|
||||
const passwordVisiable = ref<boolean>(false);
|
||||
const passForm = reactive<Setting.PasswordUpdate>({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
retryPassword: '',
|
||||
});
|
||||
|
||||
interface Props {
|
||||
settingInfo: any;
|
||||
}
|
||||
const form = withDefaults(defineProps<Props>(), {
|
||||
settingInfo: {
|
||||
userName: '',
|
||||
password: '',
|
||||
email: '',
|
||||
sessionTimeout: '',
|
||||
localTime: '',
|
||||
panelName: '',
|
||||
theme: '',
|
||||
language: '',
|
||||
},
|
||||
});
|
||||
|
||||
const { switchDark } = useTheme();
|
||||
|
||||
const SaveSetting = async (key: string, val: string) => {
|
||||
switch (key) {
|
||||
case 'Language':
|
||||
i18n.locale.value = val;
|
||||
globalStore.updateLanguage(val);
|
||||
break;
|
||||
case 'theme':
|
||||
switchDark();
|
||||
break;
|
||||
}
|
||||
let param = {
|
||||
key: key,
|
||||
value: val,
|
||||
};
|
||||
await updateSetting(param);
|
||||
ElMessage.success(i18n.t('commons.msg.operationSuccess'));
|
||||
};
|
||||
|
||||
function checkPassword(rule: any, value: any, callback: any) {
|
||||
if (passForm.newPassword !== passForm.retryPassword) {
|
||||
return callback(new Error(i18n.t('commons.rule.rePassword')));
|
||||
}
|
||||
callback();
|
||||
}
|
||||
function submitChangePassword() {}
|
||||
</script>
|
122
frontend/src/views/setting/tabs/safe.vue
Normal file
122
frontend/src/views/setting/tabs/safe.vue
Normal file
@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<el-form size="small" :model="form" label-position="left" label-width="120px">
|
||||
<el-card style="margin-top: 10px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>安全</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row>
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="面板端口">
|
||||
<el-input clearable v-model="form.settingInfo.serverPort">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('ServerPort', form.settingInfo.serverPort)"
|
||||
icon="Collection"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
<el-tooltip
|
||||
class="box-item"
|
||||
effect="dark"
|
||||
content="Top Left prompts info"
|
||||
placement="top-start"
|
||||
>
|
||||
<el-icon style="font-size: 14px; margin-top: 8px"><WarningFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-input>
|
||||
<div>
|
||||
<span class="input-help">
|
||||
建议端口范围8888 - 65535,注意:有安全组的服务器请提前在安全组放行新端口
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="安全入口">
|
||||
<el-input clearable v-model="form.settingInfo.securityEntrance">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('SecurityEntrance', form.settingInfo.securityEntrance)"
|
||||
icon="Collection"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<div>
|
||||
<span class="input-help">
|
||||
面板管理入口,设置后只能通过指定安全入口登录面板,如: /89dc6ae8
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码过期时间">
|
||||
<el-input clearable v-model="form.settingInfo.passwordTimeOut">
|
||||
<template #append>
|
||||
<el-button
|
||||
@click="SaveSetting('Password', form.settingInfo.passwordTimeOut)"
|
||||
icon="Collection"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<div>
|
||||
<span class="input-help"> 为面板密码设置过期时间,过期后需要重新设置密码 </span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码复杂度验证">
|
||||
<el-switch
|
||||
v-model="form.settingInfo.complexityVerification"
|
||||
active-value="enable"
|
||||
inactive-value="disable"
|
||||
@change="SaveSetting('ComplexityVerification', form.settingInfo.complexityVerification)"
|
||||
/>
|
||||
<div>
|
||||
<span class="input-help">
|
||||
密码必须满足密码长度大于8位且大写字母、小写字母、数字、特殊字符至少3项组合
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="两步验证">
|
||||
<el-switch
|
||||
v-model="form.settingInfo.mfaStatus"
|
||||
active-value="enable"
|
||||
inactive-value="disable"
|
||||
@change="SaveSetting('MFAStatus', form.settingInfo.mfaStatus)"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElMessage, ElForm } from 'element-plus';
|
||||
import { updateSetting } from '@/api/modules/setting';
|
||||
import i18n from '@/lang';
|
||||
|
||||
interface Props {
|
||||
settingInfo: any;
|
||||
}
|
||||
const form = withDefaults(defineProps<Props>(), {
|
||||
settingInfo: {
|
||||
serverPort: '',
|
||||
securityEntrance: '',
|
||||
passwordTimeOut: '',
|
||||
complexityVerification: '',
|
||||
mfaStatus: '',
|
||||
},
|
||||
});
|
||||
|
||||
const SaveSetting = async (key: string, val: string) => {
|
||||
let param = {
|
||||
key: key,
|
||||
value: val,
|
||||
};
|
||||
await updateSetting(param);
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
};
|
||||
</script>
|
@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<LayoutContent></LayoutContent>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import LayoutContent from '@/layout/layout-content.vue';
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user