feat: complete settings

This commit is contained in:
engigu
2023-12-31 21:31:56 +08:00
parent 77af985b76
commit 66b3a30a62
25 changed files with 595 additions and 37 deletions
+8
View File
@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+6
View File
@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/message-nest.iml" filepath="$PROJECT_DIR$/.idea/message-nest.iml" />
</modules>
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
+1
View File
@@ -12,6 +12,7 @@ require (
github.com/go-playground/validator/v10 v10.16.0
github.com/google/uuid v1.5.0
github.com/jinzhu/gorm v0.0.0-20180213101209-6e1387b44c64
github.com/robfig/cron/v3 v3.0.1
github.com/sirupsen/logrus v1.9.3
github.com/unknwon/com v1.0.1
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
+2
View File
@@ -86,6 +86,8 @@ github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOS
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+4
View File
@@ -4,6 +4,8 @@ import (
"fmt"
"log"
"message-nest/pkg/table"
"message-nest/service/cron_service"
"message-nest/service/env_service"
"net/http"
"github.com/gin-gonic/gin"
@@ -21,6 +23,8 @@ func init() {
logging.Setup()
util.Setup()
table.Setup()
env_service.Setup()
cron_service.Setup()
}
// @title Golang Gin API
+8 -5
View File
@@ -13,11 +13,14 @@ import (
var db *gorm.DB
//type Model struct {
// ID int `gorm:"primary_key" json:"id"`
// CreatedOn util.Time `json:"created_on"`
// ModifiedOn util.Time `json:"modified_on"`
//}
type IDModel struct {
ID int `gorm:"primary_key" json:"id"`
CreatedBy string `json:"created_by"`
ModifiedBy string `json:"modified_by"`
CreatedOn util.Time `json:"created_on"`
ModifiedOn util.Time `json:"modified_on"`
}
type UUIDModel struct {
ID uuid.UUID `gorm:"primary_key" json:"id"`
+24 -4
View File
@@ -44,13 +44,13 @@ func GetSendLogs(pageNum int, pageSize int, name string, taskId string, maps int
query := db.
Table(logt).
Select(fmt.Sprintf("%s.*, %s.name as task_name", logt, taskt)).
Joins(fmt.Sprintf("JOIN %s ON %s.task_id = %s.id", taskt, logt, taskt))
Joins(fmt.Sprintf("LEFT JOIN %s ON %s.task_id = %s.id", taskt, logt, taskt))
if name != "" {
query = query.Where(fmt.Sprintf("%s.name like ?", taskt), fmt.Sprintf("%%%s%%", name))
}
if taskId != "" {
query = query.Where(fmt.Sprintf("%s.id = ?", taskt), taskId)
query = query.Where(fmt.Sprintf("%s.task_id = ?", logt), taskId)
}
query = query.Order("created_on DESC")
if pageSize > 0 || pageNum > 0 {
@@ -68,13 +68,33 @@ func GetSendLogsTotal(name string, taskId string, maps interface{}) (int, error)
taskt := table.TasksTableName
query := db.
Table(logt).
Joins(fmt.Sprintf("JOIN %s ON %s.task_id = %s.id", taskt, logt, taskt))
Joins(fmt.Sprintf("LEFT JOIN %s ON %s.task_id = %s.id", taskt, logt, taskt))
if name != "" {
query = query.Where(fmt.Sprintf("%s.name like ?", taskt), fmt.Sprintf("%%%s%%", name))
}
if taskId != "" {
query = query.Where(fmt.Sprintf("%s.id = ?", taskt), taskId)
query = query.Where(fmt.Sprintf("%s.task_id = ?", logt), taskId)
}
query.Count(&total)
return total, nil
}
// GetSendLogsTotal 获取所有日志总数
func DeleteOutDateLogs(keepNum int) error {
logt := table.LogsTableName
sql := fmt.Sprintf(`DELETE FROM %s
WHERE id NOT IN (
SELECT id FROM (
SELECT id
FROM %s
ORDER BY created_on DESC
LIMIT %d
) tmp
);`, logt, logt, keepNum)
result := db.Exec(sql)
if result.Error != nil {
return result.Error
}
return nil
}
+58
View File
@@ -0,0 +1,58 @@
package models
import (
"errors"
"github.com/jinzhu/gorm"
"message-nest/pkg/table"
)
type Settings struct {
IDModel
Section string `json:"section"`
Key string `json:"key"`
Value string `json:"value"`
}
// AddOneSetting 添加一条设置
func AddOneSetting(setting Settings) error {
if err := db.Create(&setting).Error; err != nil {
return err
}
return nil
}
// EditSetting 编辑设置
func EditSetting(id int, data interface{}) error {
if err := db.Model(&Settings{}).Where("id = ? ", id).Updates(data).Error; err != nil {
return err
}
return nil
}
// DeleteMsgTaskIns 删除一条设置
func DeleteSettingByKey(section string, key string) error {
if err := db.Where("`section` = ? and `key` = ? ", section, key).Delete(&Settings{}).Error; err != nil {
return err
}
return nil
}
func GetSettingByKey(section string, key string) (Settings, error) {
var setting Settings
err := db.Where("`section` = ? and `key` = ? ", section, key).Find(&setting).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
return setting, err
}
return setting, nil
}
func GetSettingBySection(section string) ([]Settings, error) {
var settings []Settings
err := db.Table(table.SettingsTableName).Where("`section` = ? ", section).Scan(&settings).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
return settings, err
}
return settings, nil
}
+28
View File
@@ -0,0 +1,28 @@
package constant
var CleanLogsTaskId = "00000000-0000-0000-0000-000000000001"
var SiteSettingSectionName = "site_config"
//var SiteSettingTitleKeyName = "title"
//var SiteSettingSloganKeyName = "slogan"
//var SiteSettingLogoKeyName = "logo"
// 站点信息默认值
var SiteSiteDefaultValueMap = map[string]string{
"title": "Message Nest",
"slogan": "A Message Way Hosted Site",
"logo": "<svg t=\"1702547210136\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"1861\" width=\"200\" height=\"200\"><path d=\"M970.091313 224.033616a14.201535 14.201535 0 0 0-14.100687-3.631838c-88.419556-13.429657-142.919111-12.953859-248.242424 23.762747-69.454869 24.217859-109.056 79.873293-135.267556 116.712728-6.692202 9.403475-18.949172 26.625293-23.77309 29.509818-5.70699-1.303273-21.929374-16.036202-31.762101-24.965172-28.626747-25.994343-64.252121-58.353778-106.767516-58.757172-0.312889-0.005172-0.627071-0.005172-0.939959-0.005171-29.62101 0-54.798222 13.434828-72.857859 38.89907-13.222788 18.651798-17.914828 37.388929-18.106182 38.176323a14.31402 14.31402 0 0 0 2.893576 12.515556 14.336 14.336 0 0 0 11.782465 5.095434l0.409858-0.024565c19.192242-1.152 59.141172-3.545212 65.807516 81.857939 4.288646 54.899071 29.742545 108.631919 69.833697 147.419798 45.499475 44.025535 106.237414 67.298263 175.650909 67.298263 98.97503 0 166.222869-24.480323 205.207272-45.015919 43.172202-22.742626 62.621737-45.918384 63.429819-46.898425a14.170505 14.170505 0 0 0 1.529535-15.874586 14.191192 14.191192 0 0 0-14.166626-7.337373c-37.924202 4.443798-92.767677 6.09099-138.666667-11.298909-7.580444-2.872889-13.878303-5.893172-18.959515-8.691071 20.273131-9.964606 51.000889-28.383677 83.621495-59.93503 34.186343-33.065374 37.722505-69.908687 40.838464-102.423273 2.297535-23.919192 4.666182-48.651636 18.500526-73.091879 28.807758-50.883232 66.645333-74.489535 74.560646-79.035475a14.201535 14.201535 0 0 0 12.135434-7.776969 14.193778 14.193778 0 0 0-2.59103-16.484849z\" fill=\"\" p-id=\"1862\"></path><path d=\"M674.834101 716.481939c-33.422222 4.90796-74.989899 16.884364-117.22602-8.102787-34.843152-20.613172-53.056646-20.993293-77.783919-18.49794-0.156444 0.015515-0.312889 0.015515-0.469334 0.034909-0.274101 0.033616-0.548202 0.060768-0.822303 0.094384-4.697212 0.487434-9.65301 1.065374-14.995394 1.62004-6.702545 0.649051-13.414141 1.19596-20.133495 1.634263-75.333818 4.102465-136.860444-5.381172-163.012525-10.404202-49.488162-9.872808-86.57196-23.921778-108.946101-33.970424-59.832889-26.868364-87.080081-56.671677-87.080081-72.989738 0-1.873455 0.384-2.222545 0.787394-2.585858 2.196687-1.974303 10.616242-6.520242 41.302626-6.004364 24.793212 0.418909 56.970343 3.858101 94.308849 7.853253 40.722101 4.348121 86.873212 9.283232 136.348444 11.686788 6.913293 0.333576 13.959758 0.625778 20.93899 0.858505 9.510788 0.307717 17.545051-7.182222 17.868283-16.707233 0.319354-9.535354-7.175758-17.550222-16.705939-17.868282a1386.24 1386.24 0 0 1-20.419233-0.839112c-48.521051-2.358303-94.161455-7.236525-134.434909-11.544565-90.868364-9.712485-139.353212-13.818828-162.333737 6.833131-8.02004 7.21196-12.262141 17.004606-12.262141 28.317737 0 0.672323 0.029737 1.348525 0.065939 2.026021l0.005172 0.100848c-0.045253 0.524929-0.071111 1.039515-0.071111 1.539879 0 41.464242 9.561212 81.661414 28.414707 119.484768 17.493333 35.088808 42.251636 66.663434 73.583192 93.927434 9.169455-6.551273 20.155475-13.604202 32.524929-20.050748 49.737697-25.921939 97.838545-29.339152 139.099798-9.884444 101.590626 47.906909 142.060606 47.837091 206.198949-0.364606 5.70699-4.287354 13.814949-3.140525 18.103596 2.567758 4.289939 5.708283 3.140525 13.813657-2.567757 18.103595-38.425859 28.877576-69.968162 41.279354-105.143596 41.280647-0.484848 0-0.969697-0.002586-1.457132-0.007758-32.760242-0.316768-69.311354-11.381657-126.16404-38.190545-51.905939-24.47903-106.215434 1.008485-139.548444 23.465374 64.611556 47.922424 146.341495 74.101657 232.704 74.101656 117.55701 0 226.204444-48.934788 292.761858-131.362909l0.002586-0.002586c18.79402-14.959192 12.028121-41.362101-23.442101-36.152889z\" fill=\"\" p-id=\"1863\"></path></svg>",
}
// 日志清理自定义
var LogsCleanSectionName = "log_config"
var LogsCleanCronKeyName = "cron"
var LogsCleanKeepKeyName = "keep_num"
// 日志清理默认值
var LogsCleanDefaultValueMap = map[string]string{
"cron": "1 0 * * *",
"keep_num": "1000",
}
var AboutSectionName = "about"
+15
View File
@@ -0,0 +1,15 @@
package constant
var LatestVersion = map[string]string{}
//var info map[string]string
var V1Version = "v1.0.0"
var V1VersionDesc = `1. 支持邮件消息发送
2. 支持日志定时删除
3. 支持账号密码重置`
func init() {
LatestVersion["version"] = V1Version
LatestVersion["desc"] = V1VersionDesc
}
+5 -5
View File
@@ -27,8 +27,8 @@ type App struct {
LogFileExt string
TimeFormat string
LogKeepNum int
CleanTaskLogID string
//LogKeepNum int
//CleanTaskLogID string
}
var AppSetting = &App{}
@@ -83,9 +83,9 @@ func Setup() {
ServerSetting.WriteTimeout = ServerSetting.WriteTimeout * time.Second
RedisSetting.IdleTimeout = RedisSetting.IdleTimeout * time.Second
// 默认值
AppSetting.LogKeepNum = 1000
AppSetting.CleanTaskLogID = "00000000-0000-0000-0000-000000000001"
//// 默认值
//AppSetting.LogKeepNum = 1000
//AppSetting.CleanTaskLogID = "00000000-0000-0000-0000-000000000001"
}
// mapTo map section
+2
View File
@@ -9,10 +9,12 @@ var InsTableName string
var WayTableName string
var LogsTableName string
var TasksTableName string
var SettingsTableName string
func Setup() {
InsTableName = fmt.Sprintf("%ssend_tasks_ins", setting.DatabaseSetting.TablePrefix)
WayTableName = fmt.Sprintf("%ssend_ways", setting.DatabaseSetting.TablePrefix)
LogsTableName = fmt.Sprintf("%ssend_tasks_logs", setting.DatabaseSetting.TablePrefix)
TasksTableName = fmt.Sprintf("%ssend_tasks", setting.DatabaseSetting.TablePrefix)
SettingsTableName = fmt.Sprintf("%ssettings", setting.DatabaseSetting.TablePrefix)
}
+63 -4
View File
@@ -9,7 +9,30 @@ import (
"net/http"
)
type EditUserPasswd struct {
type GetSettingReq struct {
Section string `json:"section" validate:"required,max=50" label:"节点"`
}
// GetUserSetting 用户重设密码
func GetUserSetting(c *gin.Context) {
var (
appG = app.Gin{C: c}
)
section := c.Query("section")
settingService := settings_service.UserSettings{}
settings, err := settingService.GetUserSetting(section)
if err != nil {
appG.CResponse(http.StatusBadRequest, fmt.Sprintf("获取失败!错误原因:%s", err), nil)
return
}
appG.CResponse(http.StatusOK, "获取成功!", settings)
}
// EditUserPasswdReq 编辑设置请求
type EditUserPasswdReq struct {
OldPassword string `json:"old_passwd" validate:"required,max=50" label:"旧密码"`
NewPassword string `json:"new_passwd" validate:"required,max=50" label:"新密码"`
}
@@ -18,7 +41,7 @@ type EditUserPasswd struct {
func EditPasswd(c *gin.Context) {
var (
appG = app.Gin{C: c}
req EditUserPasswd
req EditUserPasswdReq
)
currentUser := app.GetCurrentUserName(c)
@@ -28,12 +51,12 @@ func EditPasswd(c *gin.Context) {
return
}
sendTaskService := settings_service.UserSettings{
settingService := settings_service.UserSettings{
UserName: currentUser,
OldPassword: req.OldPassword,
NewPassword: req.NewPassword,
}
err := sendTaskService.EditUserPasswd()
err := settingService.EditUserPasswd()
if err != nil {
appG.CResponse(http.StatusBadRequest, fmt.Sprintf("修改密码失败!错误原因:%s", err), nil)
return
@@ -42,3 +65,39 @@ func EditPasswd(c *gin.Context) {
appG.CResponse(http.StatusOK, "修改成功!", nil)
}
type SettingReq struct {
Section string `json:"section" validate:"required,max=50" label:"一级分类"`
Data map[string]string
}
// EditSettings 编辑设置
func EditSettings(c *gin.Context) {
var (
appG = app.Gin{C: c}
req SettingReq
)
errCode, errStr := app.BindJsonAndPlayValid(c, &req)
if errCode != e.SUCCESS {
appG.CResponse(errCode, errStr, nil)
return
}
currentUser := app.GetCurrentUserName(c)
settingService := settings_service.UserSettings{}
diffStr := settingService.ValidateDiffSetting(req.Section, req.Data)
if diffStr != "" {
appG.CResponse(http.StatusBadRequest, diffStr, nil)
return
}
for key, value := range req.Data {
err := settingService.EditSettings(req.Section, key, value, currentUser)
if err != nil {
appG.CResponse(http.StatusBadRequest, fmt.Sprintf("修改密码失败!错误原因:%s", err), nil)
return
}
}
appG.CResponse(http.StatusOK, "修改成功!", nil)
}
+2
View File
@@ -46,6 +46,8 @@ func InitRouter() *gin.Engine {
// settings
apiv1.POST("/settings/setpasswd", v1.EditPasswd)
apiv1.POST("/settings/set", v1.EditSettings)
apiv1.GET("/settings/getsetting", v1.GetUserSetting)
}
+78
View File
@@ -0,0 +1,78 @@
package cron_service
import (
"fmt"
"github.com/robfig/cron/v3"
"github.com/unknwon/com"
"message-nest/models"
"message-nest/pkg/constant"
"message-nest/pkg/logging"
"message-nest/service/send_message_service"
)
type CronService struct {
}
var ClearLogsTaskId cron.EntryID
// 清除日志的定时任务
func ClearLogs() {
var logOutput []string
var errStr string
status := 1
sm := send_message_service.SendMessageService{TaskID: constant.CleanLogsTaskId}
logging.Logger.Error("开始清除日志")
logOutput = append(logOutput, "开始清除日志")
setting, err := models.GetSettingByKey(constant.LogsCleanSectionName, constant.LogsCleanKeepKeyName)
if err != nil {
errStr = fmt.Sprintf("获取日志的保留数失败,原因:%s", err)
logging.Logger.Error(errStr)
sm.MarkStatus(errStr, &status)
logOutput = append(logOutput, errStr)
}
keepNum := com.StrTo(setting.Value).MustInt()
err = models.DeleteOutDateLogs(keepNum)
if err != nil {
errStr = fmt.Sprintf("删除日志失败,原因:%s", err)
logging.Logger.Error(errStr)
sm.MarkStatus(errStr, &status)
logOutput = append(logOutput, errStr)
} else {
errStr = fmt.Sprintf("删除日志成功,保留数目:%d", keepNum)
logging.Logger.Error(errStr)
logOutput = append(logOutput, errStr)
}
sm.RecordSendLog(logOutput, status)
}
// 启动注册清除任务定时任务
func (cs *CronService) InitLogsCronRun() {
setting, err := models.GetSettingByKey(constant.LogsCleanSectionName, constant.LogsCleanCronKeyName)
if err != nil {
logging.Logger.Error(fmt.Sprintf("获取日志的cron失败,原因:%s", err))
}
ClearLogsTaskId = AddTask(ScheduledTask{
Schedule: setting.Value,
Job: ClearLogs,
})
}
// 更新清除任务定时任务
func (cs *CronService) UpdateLogsCronRun(cron string) {
RemoveTask(ClearLogsTaskId)
ClearLogsTaskId = AddTask(ScheduledTask{
Schedule: cron,
Job: ClearLogs,
})
logging.Logger.Error(fmt.Sprintf("更新日志的cron成功,%s", cron))
logging.Logger.Info(fmt.Sprintf("所有的定时任务: %s", TaskList))
}
func Setup() {
cs := CronService{}
cs.InitLogsCronRun()
}
+52
View File
@@ -0,0 +1,52 @@
package cron_service
import (
"fmt"
"github.com/robfig/cron/v3"
"message-nest/pkg/logging"
"sync"
)
type ScheduledTask struct {
//ID int
Schedule string
Job func()
}
var (
CronInstance *cron.Cron
TaskList map[cron.EntryID]*ScheduledTask
mutex sync.Mutex
)
func init() {
CronInstance = cron.New()
CronInstance.Start()
TaskList = make(map[cron.EntryID]*ScheduledTask)
}
// 添加定时任务
func AddTask(task ScheduledTask) cron.EntryID {
mutex.Lock()
defer mutex.Unlock()
taskId, err := CronInstance.AddFunc(task.Schedule, task.Job)
if err != nil {
// 处理错误
logging.Logger.Error(fmt.Sprintf("添加定时任务失败,原因:%s", err))
} else {
TaskList[taskId] = &task
logging.Logger.Error(fmt.Sprintf("添加日志清除任务成功,entryID %d", taskId))
}
return taskId
}
// 删除定时任务
func RemoveTask(taskID cron.EntryID) {
mutex.Lock()
defer mutex.Unlock()
if _, ok := TaskList[taskID]; ok {
CronInstance.Remove(taskID)
delete(TaskList, taskID)
}
}
+48
View File
@@ -0,0 +1,48 @@
package env_service
import (
"message-nest/models"
"message-nest/pkg/constant"
"message-nest/pkg/logging"
)
type EnvService struct {
}
func (es *EnvService) CommonAdd(section string, key string, value string) {
setting, _ := models.GetSettingByKey(section, key)
if setting.ID <= 0 {
err := models.AddOneSetting(models.Settings{
Section: section,
Key: key,
Value: value,
})
if err != nil {
logging.Logger.Error("初始化%s:%s失败", section, key)
} else {
logging.Logger.Infof("初始化%s:%s成功", section, key)
}
}
}
// InitSiteConfig 初始化、重置站点信息设置
func (es *EnvService) InitSiteConfig() {
section := constant.SiteSettingSectionName
for key, value := range constant.SiteSiteDefaultValueMap {
es.CommonAdd(section, key, value)
}
}
// InitLogConfig 初始化日志清理设置
func (es *EnvService) InitLogConfig() {
section := constant.LogsCleanSectionName
for key, value := range constant.LogsCleanDefaultValueMap {
es.CommonAdd(section, key, value)
}
}
func Setup() {
es := EnvService{}
es.InitSiteConfig()
es.InitLogConfig()
}
+90
View File
@@ -2,7 +2,12 @@ package settings_service
import (
"errors"
"fmt"
"github.com/robfig/cron/v3"
"message-nest/models"
"message-nest/pkg/app"
"message-nest/pkg/constant"
"message-nest/service/cron_service"
)
type UserSettings struct {
@@ -21,3 +26,88 @@ func (us *UserSettings) EditUserPasswd() error {
user["password"] = us.NewPassword
return models.EditUser(us.UserName, user)
}
// GetUserSetting 获取用户设置
func (us *UserSettings) GetUserSetting(section string) (map[string]string, error) {
result := make(map[string]string)
settings, err := models.GetSettingBySection(section)
if err != nil {
return result, err
}
for _, setting := range settings {
result[setting.Key] = setting.Value
}
// 版本信息单独获取
if section == constant.AboutSectionName {
result = constant.LatestVersion
}
return result, nil
}
// EditSettings 便捷自定义设置
func (us *UserSettings) EditSettings(section string, key string, value string, currentUser string) error {
setting, _ := models.GetSettingByKey(section, key)
if setting.ID <= 0 {
err := models.AddOneSetting(models.Settings{
IDModel: models.IDModel{
CreatedBy: currentUser,
ModifiedBy: currentUser,
},
Section: section,
Key: key,
Value: value,
})
return err
} else {
if value == "" {
return nil
}
data := make(map[string]interface{})
data["section"] = section
data["key"] = key
data["value"] = value
data["modified_by"] = currentUser
err := models.EditSetting(setting.ID, data)
if key == constant.LogsCleanCronKeyName {
cronService := cron_service.CronService{}
cronService.UpdateLogsCronRun(value)
}
return err
}
}
// 站点自定义的结构
type SiteConfig struct {
Title string `json:"title" validate:"omitempty,min=1,max=50" label:"网站标题"`
Slogan string `json:"slogan" validate:"omitempty,min=1,max=50" label:"网站slogan"`
Logo string `json:"logo" validate:"omitempty,min=1" label:"logo"`
}
type LogConfig struct {
Cron string `json:"cron" validate:"required,cron" label:"日志定时表达式"`
KeepNum string `json:"keep_num" validate:"required,min=1,max=50" label:"日志保留数"`
}
// ValidateDiffSetting 校验不同的设置
func (us *UserSettings) ValidateDiffSetting(section string, data map[string]string) string {
if section == constant.SiteSettingSectionName {
var config SiteConfig
config.Title = data["title"]
config.Slogan = data["slogan"]
config.Logo = data["logo"]
_, errStr := app.CommonPlaygroundValid(config)
return errStr
}
if section == constant.LogsCleanSectionName {
var config LogConfig
config.Cron = data["cron"]
config.KeepNum = data["keep_num"]
_, err := cron.ParseStandard(config.Cron)
if err != nil {
return fmt.Sprintf("%s 不是合法的corn表达式", config.Cron)
}
_, errStr := app.CommonPlaygroundValid(config)
return errStr
}
return fmt.Sprintf("未知的section%s", section)
}
@@ -10,9 +10,9 @@
<el-menu-item index="logCleanSetting">
日志清理
</el-menu-item>
<el-menu-item index="siteCustomSetting">
<!-- <el-menu-item index="siteCustomSetting">
站点设置
</el-menu-item>
</el-menu-item> -->
<el-menu-item index="aboutSetting">
站点关于
</el-menu-item>
@@ -1,14 +1,12 @@
<template>
<div class="setting-container">
<el-text size="small">当前版本v1.0.0</el-text>
<el-text size="small">当前版本{{ version }}</el-text>
<div class="buttom">
<div class="tips">
<el-text size="small">版本功能说明</el-text>
<el-tooltip placement="top">
<template #content>
logo请输入svg文本替换后登录页面ico导航栏logo将全部一起更换
<br />
*将在下一次登录的时候生效
<div v-html="desc"></div>
</template>
<el-icon>
<QuestionFilled />
@@ -20,7 +18,7 @@
</template>
<script>
import { defineComponent, reactive, toRefs } from 'vue';
import { defineComponent, reactive, toRefs, onMounted } from 'vue';
import { ElMessage } from 'element-plus'
import { request } from '@/api/api'
import { QuestionFilled } from '@element-plus/icons-vue'
@@ -35,8 +33,8 @@ export default defineComponent({
},
setup() {
const state = reactive({
oldPasswd: '',
newPasswd: '',
version: '',
desc: '',
});
const handleChange = async () => {
@@ -47,6 +45,21 @@ export default defineComponent({
ElMessage({ message: msg, type: 'success' })
}
}
const getAbout = async () => {
let params = { params: { section: "about" } };
const rsp = await request.get('/settings/getsetting', params);
if (await rsp.data.code == 200) {
let data = await rsp.data.data;
state.version = data.version;
state.desc = data.desc.replace(/\n/g, '<br />');
}
}
onMounted(() => {
getAbout();
})
return {
...toRefs(state), handleChange
}
@@ -4,7 +4,7 @@
<el-input v-model="cron" size="small" placeholder="请输入定时日志清除的Cron表达式">
<template size="small" #prepend>cron://</template>
</el-input>
<el-input v-model.number="keepNum" size="small" placeholder="请输入要保留的最近的日志条数" style="margin-top: 15px;">
<el-input v-model="keepNum" size="small" placeholder="请输入要保留的最近的日志条数" style="margin-top: 15px;">
<template size="small" #prepend>保留数</template>
</el-input>
</div>
@@ -29,7 +29,7 @@
</template>
<script>
import { defineComponent, reactive, toRefs } from 'vue';
import { defineComponent, reactive, toRefs, onMounted } from 'vue';
import { ElMessage } from 'element-plus'
import { QuestionFilled } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router';
@@ -47,13 +47,20 @@ export default defineComponent({
setup() {
const router = useRouter();
const state = reactive({
section: 'log_config',
cron: '',
keepNum: 1000,
keepNum: '1000',
});
const handleSubmit = async () => {
let postData = { old_passwd: state.oldPasswd, new_passwd: state.newPasswd };
const rsp = await request.post('/settings/setpasswd', postData);
let postData = {
section: state.section,
data: {
cron: state.cron.trim(),
keep_num: state.keepNum.trim(),
},
};
const rsp = await request.post('/settings/set', postData);
if (await rsp.data.code == 200) {
let msg = await rsp.data.msg;
ElMessage({ message: msg, type: 'success' })
@@ -62,6 +69,21 @@ export default defineComponent({
const handleView = async () => {
router.push('/sendlogs?taskid=' + CONSTANT.LOG_TASK_ID, { replace: true });
}
const getSiteConfig = async () => {
let params = { params: { section: "log_config" } };
const rsp = await request.get('/settings/getsetting', params);
if (await rsp.data.code == 200) {
let data = await rsp.data.data;
state.cron = data.cron;
state.keepNum = data.keep_num;
}
}
onMounted(() => {
getSiteConfig();
})
return {
...toRefs(state), handleSubmit, handleView
}
@@ -17,7 +17,7 @@
<el-tooltip placement="top">
<template #content>
1. logo请输入svg文本替换后登录页面ico导航栏logo将全部一起更换
<br />
<br />
2. slogan将在登录页面展示
<br />
*将在下一次登录的时候生效
@@ -27,14 +27,14 @@
</el-icon>
</el-tooltip>
</div>
<el-button @click="handleView" size="small">查看日志</el-button>
<el-button @click="handleView" size="small">恢复默认</el-button>
<el-button @click="handleSubmit" size="small" type="primary">确定</el-button>
</div>
</div>
</template>
<script>
import { defineComponent, reactive, toRefs } from 'vue';
import { defineComponent, reactive, toRefs, onMounted } from 'vue';
import { ElMessage } from 'element-plus'
import { QuestionFilled } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router';
@@ -55,11 +55,19 @@ export default defineComponent({
title: '',
slogan: '',
logo: '',
section: 'site_config',
});
const handleSubmit = async () => {
let postData = { old_passwd: state.oldPasswd, new_passwd: state.newPasswd };
const rsp = await request.post('/settings/setpasswd', postData);
let postData = {
section: state.section,
data: {
title: state.title.trim(),
slogan: state.slogan.trim(),
logo: state.logo.trim(),
},
};
const rsp = await request.post('/settings/set', postData);
if (await rsp.data.code == 200) {
let msg = await rsp.data.msg;
ElMessage({ message: msg, type: 'success' })
@@ -68,6 +76,22 @@ export default defineComponent({
const handleView = async () => {
router.push('/sendlogs?taskid=' + CONSTANT.LOG_TASK_ID, { replace: true });
}
const getSiteConfig = async () => {
let params = { params: { section: "site_config" } };
const rsp = await request.get('/settings/getsetting', params);
if (await rsp.data.code == 200) {
let data = await rsp.data.data;
state.title = data.title;
state.logo = data.logo;
state.slogan = data.slogan;
}
}
onMounted(() => {
getSiteConfig();
})
return {
...toRefs(state), handleSubmit, handleView
}