style: 增加分页

This commit is contained in:
zhengkunwang223 2022-09-15 10:44:43 +08:00 committed by ssongliu
parent 95b18ebc89
commit 6ceb040061
19 changed files with 452 additions and 2 deletions

View file

@ -15,4 +15,5 @@ var (
commandService = service.ServiceGroupApp.CommandService
operationService = service.ServiceGroupApp.OperationService
fileService = service.ServiceGroupApp.FileService
settingService = service.ServiceGroupApp.SettingService
)

View file

@ -0,0 +1,36 @@
package v1
import (
"github.com/1Panel-dev/1Panel/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/app/dto"
"github.com/1Panel-dev/1Panel/constant"
"github.com/1Panel-dev/1Panel/global"
"github.com/gin-gonic/gin"
)
func (b *BaseApi) GetSettingInfo(c *gin.Context) {
setting, err := settingService.GetSettingInfo()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, setting)
}
func (b *BaseApi) UpdateInfo(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.Update(req.Key, req.Value); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}

View file

@ -0,0 +1,31 @@
package dto
type SettingInfo struct {
UserName string `json:"userName"`
Password string `json:"password"`
Email string `json:"email"`
SessionTimeout string `json:"sessionTimeout"`
PanelName string `json:"panelName"`
Theme string `json:"theme"`
Language string `json:"language"`
ServerPort string `json:"serverPort"`
SecurityEntrance string `json:"securityEntrance"`
ComplexityVerification string `json:"complexityVerification"`
MFAStatus string `json:"mfaStatus"`
MonitorStatus string `json:"monitorStatus"`
MonitorStoreDays string `json:"monitorStoreDays"`
MessageType string `json:"messageType"`
EmailVars string `json:"emailVars"`
WeChatVars string `json:"weChatVars"`
DingVars string `json:"dingVars"`
}
type SettingUpdate struct {
Key string `json:"key" validate:"required"`
Value string `json:"value"`
}

View file

@ -0,0 +1,10 @@
package model
import "gorm.io/gorm"
type Setting struct {
gorm.Model
Key string `json:"key" gorm:"type:varchar(256);not null;"`
Value string `json:"value" gorm:"type:varchar(256)"`
About string `json:"about" gorm:"type:longText"`
}

View file

@ -7,6 +7,7 @@ type RepoGroup struct {
CommandRepo
OperationRepo
CommonRepo
SettingRepo
}
var RepoGroupApp = new(RepoGroup)

View file

@ -0,0 +1,31 @@
package repo
import (
"github.com/1Panel-dev/1Panel/app/model"
"github.com/1Panel-dev/1Panel/global"
)
type SettingRepo struct{}
type ISettingRepo interface {
Get(opts ...DBOption) ([]model.Setting, error)
Update(key, value string) error
}
func NewISettingService() ISettingRepo {
return &SettingRepo{}
}
func (u *SettingRepo) Get(opts ...DBOption) ([]model.Setting, error) {
var settings []model.Setting
db := global.DB.Model(&model.Setting{})
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&settings).Error
return settings, err
}
func (u *SettingRepo) Update(key, value string) error {
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error
}

View file

@ -9,6 +9,7 @@ type ServiceGroup struct {
CommandService
OperationService
FileService
SettingService
}
var ServiceGroupApp = new(ServiceGroup)
@ -20,4 +21,5 @@ var (
commandRepo = repo.RepoGroupApp.CommandRepo
operationRepo = repo.RepoGroupApp.OperationRepo
commonRepo = repo.RepoGroupApp.CommonRepo
settingRepo = repo.RepoGroupApp.SettingRepo
)

View file

@ -0,0 +1,43 @@
package service
import (
"encoding/json"
"github.com/1Panel-dev/1Panel/app/dto"
"github.com/1Panel-dev/1Panel/constant"
)
type SettingService struct{}
type ISettingService interface {
GetSettingInfo() (*dto.SettingInfo, error)
Update(key, value string) error
}
func NewISettingService() ISettingService {
return &SettingService{}
}
func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
setting, err := settingRepo.Get()
if err != nil {
return nil, constant.ErrRecordNotFound
}
settingMap := make(map[string]string)
for _, set := range setting {
settingMap[set.Key] = set.Value
}
var info dto.SettingInfo
arr, err := json.Marshal(settingMap)
if err != nil {
return nil, err
}
if err := json.Unmarshal(arr, &info); err != nil {
return nil, err
}
return &info, err
}
func (u *SettingService) Update(key, value string) error {
return settingRepo.Update(key, value)
}

View file

@ -13,7 +13,8 @@ func Init() {
migrations.AddData,
migrations.AddTableOperationLog,
migrations.AddTableHost,
migrations.AddTablemonitor,
migrations.AddTableMonitor,
migrations.AddTableSetting,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)

View file

@ -54,9 +54,75 @@ var AddTableHost = &gormigrate.Migration{
},
}
var AddTablemonitor = &gormigrate.Migration{
var AddTableMonitor = &gormigrate.Migration{
ID: "20200905-add-table-monitor",
Migrate: func(tx *gorm.DB) error {
return tx.AutoMigrate(&model.MonitorBase{}, &model.MonitorIO{}, &model.MonitorNetwork{})
},
}
var AddTableSetting = &gormigrate.Migration{
ID: "20200908-add-table-setting",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.Setting{}); err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "UserName", Value: "admin"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "Password", Value: "5WYEZ4XcitdomVvAyimt9WwJwBJJSbTTHncZoqyOraQ="}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "Email", Value: ""}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "PanelName", Value: "1Panel"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "Language", Value: "ch"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "Theme", Value: "auto"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "SessionTimeout", Value: "86400"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "ServerPort", Value: "4004"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "SecurityEntrance", Value: "/89dc6ae8"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "ComplexityVerification", Value: "enable"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "MFAStatus", Value: "disable"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "MonitorStatus", Value: "enable"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "MonitorStoreDays", Value: "30"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "MessageType", Value: "none"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "EmailVars", Value: ""}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "WeChatVars", Value: ""}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "DingVars", Value: ""}).Error; err != nil {
return err
}
return nil
},
}

View file

@ -46,6 +46,7 @@ func Routers() *gin.Engine {
systemRouter.InitMonitorRouter(PrivateGroup)
systemRouter.InitOperationLogRouter(PrivateGroup)
systemRouter.InitFileRouter(PrivateGroup)
systemRouter.InitSettingRouter(PrivateGroup)
}
return Router

View file

@ -9,6 +9,7 @@ type RouterGroup struct {
MonitorRouter
OperationLogRouter
FileRouter
SettingRouter
}
var RouterGroupApp = new(RouterGroup)

View file

@ -0,0 +1,17 @@
package router
import (
v1 "github.com/1Panel-dev/1Panel/app/api/v1"
"github.com/1Panel-dev/1Panel/middleware"
"github.com/gin-gonic/gin"
)
type SettingRouter struct{}
func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) {
monitorRouter := Router.Group("settings").Use(middleware.JwtAuth()).Use(middleware.SessionAuth())
baseApi := v1.ApiGroupApp.BaseApi
{
monitorRouter.POST("/search", baseApi.GetSettingInfo)
}
}

View file

@ -0,0 +1,26 @@
export namespace Setting {
export interface SettingInfo {
userName: string;
password: string;
email: string;
sessionTimeout: string;
panelName: string;
theme: string;
language: string;
serverPort: string;
securityEntrance: string;
complexityVerification: string;
mfaStatus: string;
monitorStatus: string;
monitorStoreDays: string;
messageType: string;
emailVars: string;
weChatVars: string;
dingVars: string;
}
}

View file

@ -0,0 +1,6 @@
import http from '@/api';
import { Setting } from '../interface/setting';
export const getSettingInfo = () => {
return http.post<Setting.SettingInfo>(`/settings/search`);
};

View file

@ -100,6 +100,7 @@ export default {
monitor: 'Monitor',
operations: 'Operation Records',
files: 'File Management',
settings: 'Setting',
},
home: {
welcome: 'Welcome',

View file

@ -100,6 +100,7 @@ export default {
monitor: '监控',
operations: '操作记录',
files: '文件管理',
settings: '系统设置',
},
home: {
welcome: '欢迎使用',

View file

@ -0,0 +1,25 @@
import { Layout } from '@/routers/constant';
const settingRouter = {
sort: 3,
path: '/settings',
component: Layout,
redirect: '/setting',
meta: {
title: 'menu.settings',
icon: 'Setting',
},
children: [
{
path: '/setting',
name: 'Setting',
component: () => import('@/views/setting/index.vue'),
meta: {
requiresAuth: true,
key: 'Setting',
},
},
],
};
export default settingRouter;

View file

@ -0,0 +1,150 @@
<template>
<div class="demo-collapse">
<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="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>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, reactive } from 'vue';
import { getSettingInfo } from '@/api/modules/setting';
import { Setting } from '@/api/interface/setting';
const activeNames = ref('all');
let form = reactive<Setting.SettingInfo>({
userName: '',
password: '',
email: '',
sessionTimeout: '',
panelName: '',
theme: '',
language: '',
serverPort: '',
securityEntrance: '',
complexityVerification: '',
mfaStatus: '',
monitorStatus: '',
monitorStoreDays: '',
messageType: '',
emailVars: '',
weChatVars: '',
dingVars: '',
});
const search = async () => {
const res = await getSettingInfo();
console.log(res);
form = res.data;
};
onMounted(() => {
search();
});
</script>
<style>
.topCard {
--el-card-border-color: var(--el-border-color-light);
--el-card-border-radius: 4px;
--el-card-padding: 0px;
--el-card-bg-color: var(--el-fill-color-blank);
}
.topButton .el-radio-button__inner {
display: inline-block;
line-height: 1;
white-space: nowrap;
vertical-align: middle;
background: var(--el-button-bg-color, var(--el-fill-color-blank));
border: 0;
font-weight: 350;
border-left: 0;
color: var(--el-button-text-color, var(--el-text-color-regular));
text-align: center;
box-sizing: border-box;
outline: 0;
margin: 0;
position: relative;
cursor: pointer;
transition: var(--el-transition-all);
-webkit-user-select: none;
user-select: none;
padding: 8px 15px;
font-size: var(--el-font-size-base);
border-radius: 0;
}
</style>