mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-10 16:00:31 +00:00
Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54b5cee466 | ||
|
|
8607acbb22 | ||
|
|
13f5ac77c2 | ||
|
|
354f0d0753 | ||
|
|
48d4a47ed1 | ||
|
|
0f3ea3f434 | ||
|
|
c90ad0f4ed | ||
|
|
61bbfac3cd | ||
|
|
fcca83b3e9 | ||
|
|
8244b679fe | ||
|
|
604949de18 | ||
|
|
7716df55f9 | ||
|
|
08fe607012 | ||
|
|
4222a985f9 | ||
|
|
0ed5ae71c5 | ||
|
|
a2bfa5acaa | ||
|
|
609aa04aba | ||
|
|
0b5b90d0c5 | ||
|
|
0449100e23 | ||
|
|
5f009152d3 |
@@ -518,7 +518,7 @@ func (a *AppInstallService) ChangeAppPort(req request.PortUpdate) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := updateInstallInfoInDB(req.Key, "", "port", true, strconv.FormatInt(req.Port, 10)); err != nil {
|
if err := updateInstallInfoInDB(req.Key, req.Name, "port", true, strconv.FormatInt(req.Port, 10)); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -316,11 +316,6 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerOperate) error {
|
|||||||
return buserr.New(constant.ErrContainerName)
|
return buserr.New(constant.ErrContainerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
config, hostConf, networkConf, err := loadConfigInfo(true, req, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
global.LOG.Infof("new container info %s has been made, now start to create", req.Name)
|
|
||||||
if !checkImageExist(client, req.Image) || req.ForcePull {
|
if !checkImageExist(client, req.Image) || req.ForcePull {
|
||||||
if err := pullImages(ctx, client, req.Image); err != nil {
|
if err := pullImages(ctx, client, req.Image); err != nil {
|
||||||
if !req.ForcePull {
|
if !req.ForcePull {
|
||||||
@@ -329,6 +324,21 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerOperate) error {
|
|||||||
global.LOG.Errorf("force pull image %s failed, err: %v", req.Image, err)
|
global.LOG.Errorf("force pull image %s failed, err: %v", req.Image, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
imageInfo, _, err := client.ImageInspectWithRaw(ctx, req.Image)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(req.Entrypoint) == 0 {
|
||||||
|
req.Entrypoint = imageInfo.Config.Entrypoint
|
||||||
|
}
|
||||||
|
if len(req.Cmd) == 0 {
|
||||||
|
req.Cmd = imageInfo.Config.Cmd
|
||||||
|
}
|
||||||
|
config, hostConf, networkConf, err := loadConfigInfo(true, req, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
global.LOG.Infof("new container info %s has been made, now start to create", req.Name)
|
||||||
container, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name)
|
container, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
|
_ = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
|
||||||
@@ -867,6 +877,10 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types
|
|||||||
config.Tty = req.Tty
|
config.Tty = req.Tty
|
||||||
|
|
||||||
if len(req.Network) != 0 {
|
if len(req.Network) != 0 {
|
||||||
|
switch req.Network {
|
||||||
|
case "host", "none", "bridge":
|
||||||
|
hostConf.NetworkMode = container.NetworkMode(req.Network)
|
||||||
|
}
|
||||||
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {}}
|
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {}}
|
||||||
} else {
|
} else {
|
||||||
networkConf = network.NetworkingConfig{}
|
networkConf = network.NetworkingConfig{}
|
||||||
@@ -881,6 +895,7 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types
|
|||||||
}
|
}
|
||||||
hostConf.NanoCPUs = int64(req.NanoCPUs * 1000000000)
|
hostConf.NanoCPUs = int64(req.NanoCPUs * 1000000000)
|
||||||
hostConf.Memory = int64(req.Memory * 1024 * 1024)
|
hostConf.Memory = int64(req.Memory * 1024 * 1024)
|
||||||
|
hostConf.MemorySwap = 0
|
||||||
hostConf.PortBindings = portMap
|
hostConf.PortBindings = portMap
|
||||||
hostConf.Binds = []string{}
|
hostConf.Binds = []string{}
|
||||||
config.Volumes = make(map[string]struct{})
|
config.Volumes = make(map[string]struct{})
|
||||||
|
|||||||
+92
-36
@@ -287,9 +287,9 @@ func (u *SSHService) LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error) {
|
|||||||
case constant.StatusSuccess:
|
case constant.StatusSuccess:
|
||||||
commandItem = fmt.Sprintf("cat %s | grep -a Accepted %s", file.Name, command)
|
commandItem = fmt.Sprintf("cat %s | grep -a Accepted %s", file.Name, command)
|
||||||
case constant.StatusFailed:
|
case constant.StatusFailed:
|
||||||
commandItem = fmt.Sprintf("cat %s | grep -a 'Connection closed by authenticating user' | grep -a 'preauth' %s", file.Name, command)
|
commandItem = fmt.Sprintf("cat %s | grep -aE 'Failed password for|Connection closed by authenticating user' | grep -a 'preauth' %s", file.Name, command)
|
||||||
default:
|
default:
|
||||||
commandItem = fmt.Sprintf("cat %s | grep -aE \"(Connection closed by authenticating user|Accepted)\" | grep -v 'invalid' %s", file.Name, command)
|
commandItem = fmt.Sprintf("cat %s | grep -aE \"(Failed password for|Connection closed by authenticating user|Accepted)\" | grep -v 'invalid' %s", file.Name, command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dataItem, successCount, failedCount := loadSSHData(commandItem, showCountFrom, showCountTo, file.Year, qqWry, nyc)
|
dataItem, successCount, failedCount := loadSSHData(commandItem, showCountFrom, showCountTo, file.Year, qqWry, nyc)
|
||||||
@@ -466,7 +466,7 @@ func loadSSHData(command string, showCountFrom, showCountTo, currentYear int, qq
|
|||||||
if len(itemData.Address) != 0 {
|
if len(itemData.Address) != 0 {
|
||||||
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
|
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
|
||||||
itemData.Area = qqWry.Find(itemData.Address).Area
|
itemData.Area = qqWry.Find(itemData.Address).Area
|
||||||
itemData.Date, _ = time.ParseInLocation("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s", currentYear, itemData.DateStr), nyc)
|
itemData.Date = loadDate(currentYear, itemData.DateStr, nyc)
|
||||||
datas = append(datas, itemData)
|
datas = append(datas, itemData)
|
||||||
}
|
}
|
||||||
failedCount++
|
failedCount++
|
||||||
@@ -476,7 +476,7 @@ func loadSSHData(command string, showCountFrom, showCountTo, currentYear int, qq
|
|||||||
if len(itemData.Address) != 0 {
|
if len(itemData.Address) != 0 {
|
||||||
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
|
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
|
||||||
itemData.Area = qqWry.Find(itemData.Address).Area
|
itemData.Area = qqWry.Find(itemData.Address).Area
|
||||||
itemData.Date, _ = time.ParseInLocation("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s", currentYear, itemData.DateStr), nyc)
|
itemData.Date = loadDate(currentYear, itemData.DateStr, nyc)
|
||||||
datas = append(datas, itemData)
|
datas = append(datas, itemData)
|
||||||
}
|
}
|
||||||
failedCount++
|
failedCount++
|
||||||
@@ -486,7 +486,7 @@ func loadSSHData(command string, showCountFrom, showCountTo, currentYear int, qq
|
|||||||
if len(itemData.Address) != 0 {
|
if len(itemData.Address) != 0 {
|
||||||
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
|
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
|
||||||
itemData.Area = qqWry.Find(itemData.Address).Area
|
itemData.Area = qqWry.Find(itemData.Address).Area
|
||||||
itemData.Date, _ = time.ParseInLocation("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s", currentYear, itemData.DateStr), nyc)
|
itemData.Date = loadDate(currentYear, itemData.DateStr, nyc)
|
||||||
datas = append(datas, itemData)
|
datas = append(datas, itemData)
|
||||||
}
|
}
|
||||||
successCount++
|
successCount++
|
||||||
@@ -540,16 +540,31 @@ func loadSSHDataForAnalysis(analysisMap map[string]dto.SSHLogAnalysis, commandIt
|
|||||||
func loadSuccessDatas(line string) dto.SSHHistory {
|
func loadSuccessDatas(line string) dto.SSHHistory {
|
||||||
var data dto.SSHHistory
|
var data dto.SSHHistory
|
||||||
parts := strings.Fields(line)
|
parts := strings.Fields(line)
|
||||||
if len(parts) < 14 {
|
t, err := time.Parse("2006-01-02T15:04:05.999999-07:00", parts[0])
|
||||||
return data
|
if err != nil {
|
||||||
}
|
if len(parts) < 14 {
|
||||||
data = dto.SSHHistory{
|
return data
|
||||||
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
|
}
|
||||||
AuthMode: parts[6],
|
data = dto.SSHHistory{
|
||||||
User: parts[8],
|
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
|
||||||
Address: parts[10],
|
AuthMode: parts[6],
|
||||||
Port: parts[12],
|
User: parts[8],
|
||||||
Status: constant.StatusSuccess,
|
Address: parts[10],
|
||||||
|
Port: parts[12],
|
||||||
|
Status: constant.StatusSuccess,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(parts) < 12 {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
data = dto.SSHHistory{
|
||||||
|
DateStr: t.Format("2006 Jan 2 15:04:05"),
|
||||||
|
AuthMode: parts[4],
|
||||||
|
User: parts[6],
|
||||||
|
Address: parts[8],
|
||||||
|
Port: parts[10],
|
||||||
|
Status: constant.StatusSuccess,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
@@ -557,16 +572,31 @@ func loadSuccessDatas(line string) dto.SSHHistory {
|
|||||||
func loadFailedAuthDatas(line string) dto.SSHHistory {
|
func loadFailedAuthDatas(line string) dto.SSHHistory {
|
||||||
var data dto.SSHHistory
|
var data dto.SSHHistory
|
||||||
parts := strings.Fields(line)
|
parts := strings.Fields(line)
|
||||||
if len(parts) < 14 {
|
t, err := time.Parse("2006-01-02T15:04:05.999999-07:00", parts[0])
|
||||||
return data
|
if err != nil {
|
||||||
}
|
if len(parts) < 14 {
|
||||||
data = dto.SSHHistory{
|
return data
|
||||||
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
|
}
|
||||||
AuthMode: parts[8],
|
data = dto.SSHHistory{
|
||||||
User: parts[10],
|
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
|
||||||
Address: parts[11],
|
AuthMode: parts[8],
|
||||||
Port: parts[13],
|
User: parts[10],
|
||||||
Status: constant.StatusFailed,
|
Address: parts[11],
|
||||||
|
Port: parts[13],
|
||||||
|
Status: constant.StatusFailed,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(parts) < 12 {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
data = dto.SSHHistory{
|
||||||
|
DateStr: t.Format("2006 Jan 2 15:04:05"),
|
||||||
|
AuthMode: parts[6],
|
||||||
|
User: parts[7],
|
||||||
|
Address: parts[9],
|
||||||
|
Port: parts[11],
|
||||||
|
Status: constant.StatusFailed,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if strings.Contains(line, ": ") {
|
if strings.Contains(line, ": ") {
|
||||||
data.Message = strings.Split(line, ": ")[1]
|
data.Message = strings.Split(line, ": ")[1]
|
||||||
@@ -577,21 +607,39 @@ func loadFailedAuthDatas(line string) dto.SSHHistory {
|
|||||||
func loadFailedSecureDatas(line string) dto.SSHHistory {
|
func loadFailedSecureDatas(line string) dto.SSHHistory {
|
||||||
var data dto.SSHHistory
|
var data dto.SSHHistory
|
||||||
parts := strings.Fields(line)
|
parts := strings.Fields(line)
|
||||||
if len(parts) < 14 {
|
t, err := time.Parse("2006-01-02T15:04:05.999999-07:00", parts[0])
|
||||||
return data
|
if err != nil {
|
||||||
}
|
if len(parts) < 14 {
|
||||||
data = dto.SSHHistory{
|
return data
|
||||||
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
|
}
|
||||||
AuthMode: parts[6],
|
data = dto.SSHHistory{
|
||||||
User: parts[8],
|
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
|
||||||
Address: parts[10],
|
AuthMode: parts[6],
|
||||||
Port: parts[12],
|
User: parts[8],
|
||||||
Status: constant.StatusFailed,
|
Address: parts[10],
|
||||||
|
Port: parts[12],
|
||||||
|
Status: constant.StatusFailed,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(parts) < 12 {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
index := 0
|
||||||
|
if strings.Contains(line, " invalid user") {
|
||||||
|
index = 2
|
||||||
|
}
|
||||||
|
data = dto.SSHHistory{
|
||||||
|
DateStr: t.Format("2006 Jan 2 15:04:05"),
|
||||||
|
AuthMode: parts[4],
|
||||||
|
User: parts[index+6],
|
||||||
|
Address: parts[index+8],
|
||||||
|
Port: parts[index+10],
|
||||||
|
Status: constant.StatusFailed,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if strings.Contains(line, ": ") {
|
if strings.Contains(line, ": ") {
|
||||||
data.Message = strings.Split(line, ": ")[1]
|
data.Message = strings.Split(line, ": ")[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,3 +658,11 @@ func loadServiceName() (string, error) {
|
|||||||
}
|
}
|
||||||
return "", errors.New("The ssh or sshd service is unavailable")
|
return "", errors.New("The ssh or sshd service is unavailable")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadDate(currentYear int, DateStr string, nyc *time.Location) time.Time {
|
||||||
|
itemDate, err := time.ParseInLocation("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s", currentYear, DateStr), nyc)
|
||||||
|
if err != nil {
|
||||||
|
itemDate, _ = time.ParseInLocation("2006 Jan 2 15:04:05", DateStr, nyc)
|
||||||
|
}
|
||||||
|
return itemDate
|
||||||
|
}
|
||||||
|
|||||||
@@ -133,3 +133,8 @@ var (
|
|||||||
var (
|
var (
|
||||||
ErrFirewall = "ErrFirewall"
|
ErrFirewall = "ErrFirewall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// cronjob
|
||||||
|
var (
|
||||||
|
ErrBashExecute = "ErrBashExecute"
|
||||||
|
)
|
||||||
|
|||||||
@@ -124,4 +124,7 @@ ErrConfigAlreadyExist: "A configuration file with the same name already exists"
|
|||||||
ErrUserFindErr: "Failed to find user {{ .name }} {{ .err }}"
|
ErrUserFindErr: "Failed to find user {{ .name }} {{ .err }}"
|
||||||
|
|
||||||
#ssh
|
#ssh
|
||||||
ErrFirewall: "No firewalld or ufw service is detected. Please check and try again!"
|
ErrFirewall: "No firewalld or ufw service is detected. Please check and try again!"
|
||||||
|
|
||||||
|
#cronjob
|
||||||
|
ErrBashExecute: "Script execution error, please check the specific information in the task output text area."
|
||||||
@@ -124,4 +124,7 @@ ErrConfigAlreadyExist: "已存在同名配置文件"
|
|||||||
ErrUserFindErr: "用戶 {{ .name }} 查找失敗 {{ .err }}"
|
ErrUserFindErr: "用戶 {{ .name }} 查找失敗 {{ .err }}"
|
||||||
|
|
||||||
#ssh
|
#ssh
|
||||||
ErrFirewall: "當前未檢測到系統 firewalld 或 ufw 服務,請檢查後重試!"
|
ErrFirewall: "當前未檢測到系統 firewalld 或 ufw 服務,請檢查後重試!"
|
||||||
|
|
||||||
|
#cronjob
|
||||||
|
ErrBashExecute: "腳本執行錯誤,請在任務輸出文本域中查看具體信息。"
|
||||||
@@ -125,3 +125,6 @@ ErrUserFindErr: "用户 {{ .name }} 查找失败 {{ .err }}"
|
|||||||
|
|
||||||
#ssh
|
#ssh
|
||||||
ErrFirewall: "当前未检测到系统 firewalld 或 ufw 服务,请检查后重试!"
|
ErrFirewall: "当前未检测到系统 firewalld 或 ufw 服务,请检查后重试!"
|
||||||
|
|
||||||
|
#cronjob
|
||||||
|
ErrBashExecute: "脚本执行错误,请在任务输出文本域中查看具体信息。"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -88,23 +89,16 @@ func ExecCronjobWithTimeOut(cmdStr string, workdir string, timeout time.Duration
|
|||||||
var stdout, stderr bytes.Buffer
|
var stdout, stderr bytes.Buffer
|
||||||
cmd.Stdout = &stdout
|
cmd.Stdout = &stdout
|
||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &stderr
|
||||||
|
output := new(bytes.Buffer)
|
||||||
|
cmd.Stdout = io.MultiWriter(output, cmd.Stdout)
|
||||||
|
cmd.Stderr = io.MultiWriter(output, cmd.Stderr)
|
||||||
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if ctx.Err() == context.DeadlineExceeded {
|
if ctx.Err() == context.DeadlineExceeded {
|
||||||
return "", buserr.New(constant.ErrCmdTimeout)
|
return "", buserr.New(constant.ErrCmdTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
errMsg := ""
|
return output.String(), err
|
||||||
if len(stderr.String()) != 0 {
|
|
||||||
errMsg = fmt.Sprintf("stderr:\n %s", stderr.String())
|
|
||||||
}
|
|
||||||
if len(stdout.String()) != 0 {
|
|
||||||
if len(errMsg) != 0 {
|
|
||||||
errMsg = fmt.Sprintf("%s \n\n; stdout:\n %s", errMsg, stdout.String())
|
|
||||||
} else {
|
|
||||||
errMsg = fmt.Sprintf("stdout:\n %s", stdout.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errMsg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Execf(cmdStr string, a ...interface{}) (string, error) {
|
func Execf(cmdStr string, a ...interface{}) (string, error) {
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
package encrypt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/init/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestStringEncrypt(t *testing.T) {
|
|
||||||
viper.Init()
|
|
||||||
p, err := StringEncrypt("1Panel@2022")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStringDecrypt(t *testing.T) {
|
|
||||||
viper.Init()
|
|
||||||
p, err := StringDecrypt("dXn5bVtea+KVLDrLJlpnPIJNfW8TAMmqX1QNMdSGp88=")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(p)
|
|
||||||
}
|
|
||||||
@@ -269,7 +269,7 @@ func (r *Local) SyncDB(version string) ([]SyncDBInfo, error) {
|
|||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if parts[0] == "SCHEMA_NAME" || parts[0] == "information_schema" || parts[0] == "mysql" || parts[0] == "performance_schema" || parts[0] == "sys" {
|
if parts[0] == "SCHEMA_NAME" || parts[0] == "information_schema" || parts[0] == "mysql" || parts[0] == "performance_schema" || parts[0] == "sys" || parts[0] == "__recycle_bin__" || parts[0] == "recycle_bin" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dataItem := SyncDBInfo{
|
dataItem := SyncDBInfo{
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ func (r *Remote) SyncDB(version string) ([]SyncDBInfo, error) {
|
|||||||
if err = rows.Scan(&dbName, &charsetName); err != nil {
|
if err = rows.Scan(&dbName, &charsetName); err != nil {
|
||||||
return datas, err
|
return datas, err
|
||||||
}
|
}
|
||||||
if dbName == "information_schema" || dbName == "mysql" || dbName == "performance_schema" || dbName == "sys" {
|
if dbName == "information_schema" || dbName == "mysql" || dbName == "performance_schema" || dbName == "sys" || dbName == "__recycle_bin__" || dbName == "recycle_bin" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dataItem := SyncDBInfo{
|
dataItem := SyncDBInfo{
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { FormItemRule } from 'element-plus';
|
import { FormItemRule } from 'element-plus';
|
||||||
|
|
||||||
|
const checkNoSpace = (rule: any, value: any, callback: any) => {
|
||||||
|
if (value.indexOf(' ') !== -1) {
|
||||||
|
return callback(new Error(i18n.global.t('setting.noSpace')));
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
|
||||||
const checkIp = (rule: any, value: any, callback: any) => {
|
const checkIp = (rule: any, value: any, callback: any) => {
|
||||||
if (value === '' || typeof value === 'undefined' || value == null) {
|
if (value === '' || typeof value === 'undefined' || value == null) {
|
||||||
callback(new Error(i18n.global.t('commons.rule.requiredInput')));
|
callback(new Error(i18n.global.t('commons.rule.requiredInput')));
|
||||||
@@ -431,6 +438,7 @@ interface CommonRule {
|
|||||||
requiredInput: FormItemRule;
|
requiredInput: FormItemRule;
|
||||||
requiredSelect: FormItemRule;
|
requiredSelect: FormItemRule;
|
||||||
requiredSelectBusiness: FormItemRule;
|
requiredSelectBusiness: FormItemRule;
|
||||||
|
noSpace: FormItemRule;
|
||||||
name: FormItemRule;
|
name: FormItemRule;
|
||||||
userName: FormItemRule;
|
userName: FormItemRule;
|
||||||
simpleName: FormItemRule;
|
simpleName: FormItemRule;
|
||||||
@@ -484,6 +492,11 @@ export const Rules: CommonRule = {
|
|||||||
message: i18n.global.t('commons.rule.requiredSelect'),
|
message: i18n.global.t('commons.rule.requiredSelect'),
|
||||||
trigger: 'change',
|
trigger: 'change',
|
||||||
},
|
},
|
||||||
|
noSpace: {
|
||||||
|
required: true,
|
||||||
|
validator: checkNoSpace,
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
simpleName: {
|
simpleName: {
|
||||||
required: true,
|
required: true,
|
||||||
validator: checkSimpleName,
|
validator: checkSimpleName,
|
||||||
|
|||||||
@@ -1050,6 +1050,7 @@ const message = {
|
|||||||
oldPassword: 'Original password',
|
oldPassword: 'Original password',
|
||||||
newPassword: 'New password',
|
newPassword: 'New password',
|
||||||
retryPassword: 'Confirm password',
|
retryPassword: 'Confirm password',
|
||||||
|
noSpace: 'Input information cannot include space characters',
|
||||||
duplicatePassword: 'The new password cannot be the same as the original password, please re-enter!',
|
duplicatePassword: 'The new password cannot be the same as the original password, please re-enter!',
|
||||||
diskClean: 'Cache Clean',
|
diskClean: 'Cache Clean',
|
||||||
|
|
||||||
@@ -1064,6 +1065,7 @@ const message = {
|
|||||||
SFTP: 'SFTP',
|
SFTP: 'SFTP',
|
||||||
OneDrive: 'Microsoft OneDrive',
|
OneDrive: 'Microsoft OneDrive',
|
||||||
backupDir: 'Backup dir',
|
backupDir: 'Backup dir',
|
||||||
|
codeWarning: 'The current authorization code format is incorrect, please confirm again!',
|
||||||
isCN: 'Domestic version',
|
isCN: 'Domestic version',
|
||||||
code: 'Auth code',
|
code: 'Auth code',
|
||||||
codeHelper:
|
codeHelper:
|
||||||
|
|||||||
@@ -1006,6 +1006,7 @@ const message = {
|
|||||||
oldPassword: '原密碼',
|
oldPassword: '原密碼',
|
||||||
newPassword: '新密碼',
|
newPassword: '新密碼',
|
||||||
retryPassword: '確認密碼',
|
retryPassword: '確認密碼',
|
||||||
|
noSpace: '輸入信息不能包括空格符號',
|
||||||
duplicatePassword: '新密碼不能與原始密碼一致,請重新輸入!',
|
duplicatePassword: '新密碼不能與原始密碼一致,請重新輸入!',
|
||||||
diskClean: '缓存清理',
|
diskClean: '缓存清理',
|
||||||
|
|
||||||
@@ -1019,6 +1020,7 @@ const message = {
|
|||||||
MINIO: 'MINIO',
|
MINIO: 'MINIO',
|
||||||
SFTP: 'SFTP',
|
SFTP: 'SFTP',
|
||||||
OneDrive: '微軟 OneDrive',
|
OneDrive: '微軟 OneDrive',
|
||||||
|
codeWarning: '當前授權碼格式錯誤,請重新確認!',
|
||||||
backupDir: '備份路徑',
|
backupDir: '備份路徑',
|
||||||
isCN: '國內版',
|
isCN: '國內版',
|
||||||
code: '授權碼',
|
code: '授權碼',
|
||||||
|
|||||||
@@ -1006,6 +1006,7 @@ const message = {
|
|||||||
oldPassword: '原密码',
|
oldPassword: '原密码',
|
||||||
newPassword: '新密码',
|
newPassword: '新密码',
|
||||||
retryPassword: '确认密码',
|
retryPassword: '确认密码',
|
||||||
|
noSpace: '输入信息不能包含空格符',
|
||||||
duplicatePassword: '新密码不能与原始密码一致,请重新输入!',
|
duplicatePassword: '新密码不能与原始密码一致,请重新输入!',
|
||||||
diskClean: '缓存清理',
|
diskClean: '缓存清理',
|
||||||
|
|
||||||
@@ -1019,6 +1020,7 @@ const message = {
|
|||||||
MINIO: 'MINIO',
|
MINIO: 'MINIO',
|
||||||
SFTP: 'SFTP',
|
SFTP: 'SFTP',
|
||||||
OneDrive: '微软 OneDrive',
|
OneDrive: '微软 OneDrive',
|
||||||
|
codeWarning: '当前授权码格式错误,请重新确认!',
|
||||||
backupDir: '备份路径',
|
backupDir: '备份路径',
|
||||||
isCN: '国内版',
|
isCN: '国内版',
|
||||||
code: '授权码',
|
code: '授权码',
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ const language = useI18n().locale.value;
|
|||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
cacheSizeKey: 'app-page-size',
|
cacheSizeKey: 'app-page-size',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 60,
|
pageSize: Number(localStorage.getItem('app-page-size')) || 60,
|
||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -219,6 +219,7 @@ const search = async (req: App.AppReq) => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
req.pageSize = paginationConfig.pageSize;
|
req.pageSize = paginationConfig.pageSize;
|
||||||
req.page = paginationConfig.currentPage;
|
req.page = paginationConfig.currentPage;
|
||||||
|
localStorage.setItem('app-page-size', req.pageSize + '');
|
||||||
await SearchApp(req)
|
await SearchApp(req)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
apps.value = res.data.items;
|
apps.value = res.data.items;
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ let timer: NodeJS.Timer | null = null;
|
|||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
cacheSizeKey: 'app-installed-page-size',
|
cacheSizeKey: 'app-installed-page-size',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 20,
|
pageSize: Number(localStorage.getItem('app-installed-page-size')) || 20,
|
||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
@@ -415,6 +415,7 @@ const search = () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
searchReq.page = paginationConfig.currentPage;
|
searchReq.page = paginationConfig.currentPage;
|
||||||
searchReq.pageSize = paginationConfig.pageSize;
|
searchReq.pageSize = paginationConfig.pageSize;
|
||||||
|
localStorage.setItem('app-installed', searchReq.pageSize + '');
|
||||||
SearchAppInstalled(searchReq)
|
SearchAppInstalled(searchReq)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
data.value = res.data.items;
|
data.value = res.data.items;
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ const search = async () => {
|
|||||||
let filterItem = filters.value;
|
let filterItem = filters.value;
|
||||||
let params = {
|
let params = {
|
||||||
name: '',
|
name: '',
|
||||||
|
state: 'all',
|
||||||
page: paginationConfig.currentPage,
|
page: paginationConfig.currentPage,
|
||||||
pageSize: paginationConfig.pageSize,
|
pageSize: paginationConfig.pageSize,
|
||||||
filters: filterItem,
|
filters: filterItem,
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('cronjob.cronSpec')" :min-width="120">
|
<el-table-column :label="$t('cronjob.cronSpec')" show-overflow-tooltip :min-width="120">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span v-if="row.specType.indexOf('N') === -1 || row.specType === 'perWeek'">
|
<span v-if="row.specType.indexOf('N') === -1 || row.specType === 'perWeek'">
|
||||||
{{ $t('cronjob.' + row.specType) }}
|
{{ $t('cronjob.' + row.specType) }}
|
||||||
@@ -159,7 +159,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<OperatrDialog @search="search" ref="dialogRef" />
|
<OperateDialog @search="search" ref="dialogRef" />
|
||||||
<Records @search="search" ref="dialogRecordRef" />
|
<Records @search="search" ref="dialogRecordRef" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import TableSetting from '@/components/table-setting/index.vue';
|
import TableSetting from '@/components/table-setting/index.vue';
|
||||||
import Tooltip from '@/components/tooltip/index.vue';
|
import Tooltip from '@/components/tooltip/index.vue';
|
||||||
import OperatrDialog from '@/views/cronjob/operate/index.vue';
|
import OperateDialog from '@/views/cronjob/operate/index.vue';
|
||||||
import Records from '@/views/cronjob/record/index.vue';
|
import Records from '@/views/cronjob/record/index.vue';
|
||||||
import { loadZero } from '@/utils/util';
|
import { loadZero } from '@/utils/util';
|
||||||
import { onMounted, reactive, ref } from 'vue';
|
import { onMounted, reactive, ref } from 'vue';
|
||||||
|
|||||||
@@ -125,25 +125,30 @@
|
|||||||
<template #main>
|
<template #main>
|
||||||
<div class="mainClass">
|
<div class="mainClass">
|
||||||
<el-row :gutter="20" v-show="hasRecords" class="mainRowClass">
|
<el-row :gutter="20" v-show="hasRecords" class="mainRowClass">
|
||||||
<el-col :span="8">
|
<el-col :span="6">
|
||||||
<div>
|
<div>
|
||||||
<ul class="infinite-list" style="overflow: auto">
|
<ul class="infinite-list" style="overflow: auto">
|
||||||
<li
|
<el-card
|
||||||
v-for="(item, index) in records"
|
v-for="(item, index) in records"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
:class="item.id === currentRecord.id ? 'select-card' : 'primary-card'"
|
||||||
@click="forDetail(item)"
|
@click="forDetail(item)"
|
||||||
class="infinite-list-item"
|
|
||||||
>
|
>
|
||||||
<el-icon v-if="item.status === 'Success'"><Select /></el-icon>
|
<el-tag v-if="item.status === 'Success'" type="success">
|
||||||
<el-icon v-if="item.status === 'Waiting'"><Loading /></el-icon>
|
{{ $t('commons.status.success') }}
|
||||||
<el-icon v-if="item.status === 'Failed'"><CloseBold /></el-icon>
|
</el-tag>
|
||||||
<span v-if="item.id === currentRecord.id" style="color: red">
|
<el-tag v-if="item.status === 'Waiting'" type="info">
|
||||||
|
{{ $t('commons.status.waiting') }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-if="item.status === 'Failed'" type="danger">
|
||||||
|
{{ $t('commons.status.failed') }}
|
||||||
|
</el-tag>
|
||||||
|
<span>
|
||||||
{{ dateFormat(0, 0, item.startTime) }}
|
{{ dateFormat(0, 0, item.startTime) }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>{{ dateFormat(0, 0, item.startTime) }}</span>
|
</el-card>
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<div style="margin-top: 10px; font-size: 12px; float: right">
|
<div class="page-item">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
:page-size="searchInfo.pageSize"
|
:page-size="searchInfo.pageSize"
|
||||||
:current-page="searchInfo.page"
|
:current-page="searchInfo.page"
|
||||||
@@ -158,7 +163,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="16">
|
<el-col :span="18">
|
||||||
<el-form label-position="top" :v-key="refresh">
|
<el-form label-position="top" :v-key="refresh">
|
||||||
<el-row type="flex" justify="center">
|
<el-row type="flex" justify="center">
|
||||||
<el-form-item class="descriptionWide" v-if="isBackup()">
|
<el-form-item class="descriptionWide" v-if="isBackup()">
|
||||||
@@ -714,36 +719,50 @@ defineExpose({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.infinite-list {
|
.infinite-list {
|
||||||
height: calc(100vh - 435px);
|
height: calc(100vh - 416px);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
.el-card {
|
||||||
.infinite-list .infinite-list-item {
|
border: var(--panel-border) !important;
|
||||||
display: flex;
|
&:hover {
|
||||||
align-items: center;
|
box-shadow: 2px 2px 2px #888888;
|
||||||
justify-content: center;
|
}
|
||||||
height: 30px;
|
|
||||||
background: var(--el-color-primary-light-9);
|
|
||||||
margin: 10px;
|
|
||||||
color: var(--el-color-primary);
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
height: 40px;
|
||||||
height: 30px;
|
font-size: 14px;
|
||||||
background: var(--el-color-primary-light-9);
|
margin: 5px;
|
||||||
margin: 10px;
|
cursor: pointer;
|
||||||
font-weight: 500;
|
}
|
||||||
color: red;
|
.select-card {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
border: 1px solid var(--el-color-primary) !important;
|
||||||
|
box-shadow: 2px 2px 2px #888888;
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
width: 3px;
|
||||||
|
height: 40px;
|
||||||
|
content: '';
|
||||||
|
background: $primary-color;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-tag {
|
||||||
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.descriptionWide {
|
.descriptionWide {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
}
|
}
|
||||||
.description {
|
.description {
|
||||||
width: 30%;
|
width: 30%;
|
||||||
}
|
}
|
||||||
|
.page-item {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 1000px) {
|
@media only screen and (max-width: 1000px) {
|
||||||
.mainClass {
|
.mainClass {
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ const data = ref();
|
|||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
cacheSizeKey: 'mysql-page-size',
|
cacheSizeKey: 'mysql-page-size',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 10,
|
pageSize: Number(localStorage.getItem('mysql-page-size')) || 10,
|
||||||
total: 0,
|
total: 0,
|
||||||
orderBy: 'created_at',
|
orderBy: 'created_at',
|
||||||
order: 'null',
|
order: 'null',
|
||||||
|
|||||||
@@ -59,32 +59,22 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.router_card {
|
.router_card {
|
||||||
--el-card-border-radius: 8px;
|
--el-card-padding: 0;
|
||||||
--el-card-padding: 0 !important;
|
|
||||||
padding: 0px;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
padding-top: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.router_card_button {
|
.router_card_button {
|
||||||
margin-left: 2px;
|
|
||||||
.el-radio-button__inner {
|
.el-radio-button__inner {
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border: 0 !important;
|
background-color: var(--panel-button-active) !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: 2px solid transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-radio-button__original-radio:checked + .el-radio-button__inner {
|
.el-radio-button__original-radio:checked + .el-radio-button__inner {
|
||||||
border-radius: 3px;
|
|
||||||
color: $primary-color;
|
color: $primary-color;
|
||||||
background-color: var(--panel-button-active);
|
border-color: $primary-color !important;
|
||||||
box-shadow: 0 0 0 2px $primary-color !important;
|
border-radius: 4px;
|
||||||
}
|
|
||||||
|
|
||||||
.el-radio-button:first-child .el-radio-button__inner {
|
|
||||||
border-radius: 3px;
|
|
||||||
color: $primary-color;
|
|
||||||
background-color: var(--panel-button-active);
|
|
||||||
box-shadow: 0 0 0 2px $primary-color !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -52,13 +52,20 @@
|
|||||||
v-if="dialogData.rowData!.type === 'OneDrive'"
|
v-if="dialogData.rowData!.type === 'OneDrive'"
|
||||||
:label="$t('setting.code')"
|
:label="$t('setting.code')"
|
||||||
prop="varsJson.code"
|
prop="varsJson.code"
|
||||||
:rules="Rules.requiredInput"
|
:rules="rules.driveCode"
|
||||||
>
|
>
|
||||||
<el-input clearable v-model.trim="dialogData.rowData!.varsJson['code']">
|
<div style="width: 100%">
|
||||||
<template #append>
|
<el-input
|
||||||
<el-button @click="jumpAzure">{{ $t('setting.loadCode') }}</el-button>
|
style="width: calc(100% - 80px)"
|
||||||
</template>
|
:autosize="{ minRows: 3, maxRows: 15 }"
|
||||||
</el-input>
|
type="textarea"
|
||||||
|
clearable
|
||||||
|
v-model.trim="dialogData.rowData!.varsJson['code']"
|
||||||
|
/>
|
||||||
|
<el-button class="append-button" @click="jumpAzure">
|
||||||
|
{{ $t('setting.loadCode') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
<span class="input-help">
|
<span class="input-help">
|
||||||
{{ $t('setting.codeHelper') }}
|
{{ $t('setting.codeHelper') }}
|
||||||
<el-link
|
<el-link
|
||||||
@@ -247,7 +254,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import { Rules } from '@/global/form-rules';
|
import { Rules } from '@/global/form-rules';
|
||||||
import FileList from '@/components/file-list/index.vue';
|
import FileList from '@/components/file-list/index.vue';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
@@ -265,6 +272,16 @@ const buckets = ref();
|
|||||||
const errBuckets = ref();
|
const errBuckets = ref();
|
||||||
|
|
||||||
const endpoints = ref('http');
|
const endpoints = ref('http');
|
||||||
|
const rules = reactive({
|
||||||
|
driveCode: [{ validator: checkDriveCode, required: true, trigger: 'blur' }],
|
||||||
|
});
|
||||||
|
function checkDriveCode(rule: any, value: any, callback: any) {
|
||||||
|
const reg = /^[A-Za-z0-9_.-]+$/;
|
||||||
|
if (!reg.test(value)) {
|
||||||
|
return callback(new Error(i18n.global.t('setting.codeWarning')));
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||||
|
|
||||||
@@ -411,3 +428,11 @@ defineExpose({
|
|||||||
acceptParams,
|
acceptParams,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.append-button {
|
||||||
|
width: 80px;
|
||||||
|
background-color: var(--el-fill-color-light);
|
||||||
|
color: var(--el-color-info);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -16,30 +16,22 @@
|
|||||||
label-position="left"
|
label-position="left"
|
||||||
label-width="160px"
|
label-width="160px"
|
||||||
>
|
>
|
||||||
<el-form-item :label="$t('setting.oldPassword')" prop="oldPassword">
|
<el-form-item :label="$t('setting.oldPassword')" prop="oldPass">
|
||||||
<el-input type="password" show-password clearable v-model="passForm.oldPassword" />
|
<el-input type="password" show-password clearable v-model.trim="passForm.oldPass" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item v-if="!isComplexity" :label="$t('setting.newPassword')" prop="newPass">
|
||||||
v-if="settingForm?.complexityVerification === 'disable'"
|
<el-input type="password" show-password clearable v-model.trim="passForm.newPass" />
|
||||||
:label="$t('setting.newPassword')"
|
|
||||||
prop="newPassword"
|
|
||||||
>
|
|
||||||
<el-input type="password" show-password clearable v-model="passForm.newPassword" />
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item v-if="isComplexity" :label="$t('setting.newPassword')" prop="newPassComplexity">
|
||||||
v-if="settingForm?.complexityVerification === 'enable'"
|
|
||||||
:label="$t('setting.newPassword')"
|
|
||||||
prop="newPasswordComplexity"
|
|
||||||
>
|
|
||||||
<el-input
|
<el-input
|
||||||
type="password"
|
type="password"
|
||||||
show-password
|
show-password
|
||||||
clearable
|
clearable
|
||||||
v-model="passForm.newPasswordComplexity"
|
v-model.trim="passForm.newPassComplexity"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('setting.retryPassword')" prop="retryPassword">
|
<el-form-item :label="$t('setting.retryPassword')" prop="rePass">
|
||||||
<el-input type="password" show-password clearable v-model="passForm.retryPassword" />
|
<el-input type="password" show-password clearable v-model.trim="passForm.rePass" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="submitChangePassword(passFormRef)">
|
<el-button type="primary" @click="submitChangePassword(passFormRef)">
|
||||||
@@ -61,30 +53,31 @@ import i18n from '@/lang';
|
|||||||
import { Rules } from '@/global/form-rules';
|
import { Rules } from '@/global/form-rules';
|
||||||
import router from '@/routers';
|
import router from '@/routers';
|
||||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||||
let settingForm = ref();
|
|
||||||
|
let isComplexity = ref(false);
|
||||||
|
|
||||||
type FormInstance = InstanceType<typeof ElForm>;
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
const passFormRef = ref<FormInstance>();
|
const passFormRef = ref<FormInstance>();
|
||||||
const passRules = reactive({
|
const passRules = reactive({
|
||||||
oldPassword: [Rules.requiredInput],
|
oldPass: [Rules.noSpace, Rules.requiredInput],
|
||||||
newPassword: [
|
newPass: [
|
||||||
Rules.requiredInput,
|
Rules.requiredInput,
|
||||||
|
Rules.noSpace,
|
||||||
{ min: 6, message: i18n.global.t('commons.rule.commonPassword'), trigger: 'blur' },
|
{ min: 6, message: i18n.global.t('commons.rule.commonPassword'), trigger: 'blur' },
|
||||||
],
|
],
|
||||||
newPasswordComplexity: [Rules.requiredInput, Rules.password],
|
newPassComplexity: [Rules.requiredInput, Rules.noSpace, Rules.password],
|
||||||
retryPassword: [Rules.requiredInput, { validator: checkPassword, trigger: 'blur' }],
|
rePass: [Rules.requiredInput, Rules.noSpace, { validator: checkPasswordSame, trigger: 'blur' }],
|
||||||
});
|
});
|
||||||
const passForm = reactive({
|
const passForm = reactive({
|
||||||
oldPassword: '',
|
oldPass: '',
|
||||||
newPassword: '',
|
newPass: '',
|
||||||
newPasswordComplexity: '',
|
newPassComplexity: '',
|
||||||
retryPassword: '',
|
rePass: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
function checkPassword(rule: any, value: any, callback: any) {
|
function checkPasswordSame(rule: any, value: any, callback: any) {
|
||||||
let password =
|
let password = !isComplexity.value ? passForm.newPass : passForm.newPassComplexity;
|
||||||
settingForm.value.complexityVerification === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
|
if (password !== passForm.rePass) {
|
||||||
if (password !== passForm.retryPassword) {
|
|
||||||
return callback(new Error(i18n.global.t('commons.rule.rePassword')));
|
return callback(new Error(i18n.global.t('commons.rule.rePassword')));
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
@@ -94,22 +87,20 @@ const submitChangePassword = async (formEl: FormInstance | undefined) => {
|
|||||||
if (!formEl) return;
|
if (!formEl) return;
|
||||||
formEl.validate(async (valid) => {
|
formEl.validate(async (valid) => {
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
let password =
|
let password = !isComplexity.value ? passForm.newPass : passForm.newPassComplexity;
|
||||||
settingForm.value.complexityVerification === 'disable'
|
if (password === passForm.oldPass) {
|
||||||
? passForm.newPassword
|
|
||||||
: passForm.newPasswordComplexity;
|
|
||||||
if (password === passForm.oldPassword) {
|
|
||||||
MsgError(i18n.global.t('setting.duplicatePassword'));
|
MsgError(i18n.global.t('setting.duplicatePassword'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await handleExpired({ oldPassword: passForm.oldPassword, newPassword: password });
|
await handleExpired({ oldPassword: passForm.oldPass, newPassword: password });
|
||||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
router.push({ name: 'home' });
|
router.push({ name: 'home' });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
const res = await getSettingInfo();
|
const res = await getSettingInfo();
|
||||||
settingForm.value = res.data;
|
let settingForm = res.data;
|
||||||
|
isComplexity.value = settingForm?.complexityVerification === 'enable';
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -8,14 +8,14 @@
|
|||||||
<el-row type="flex" justify="center">
|
<el-row type="flex" justify="center">
|
||||||
<el-col :span="22">
|
<el-col :span="22">
|
||||||
<el-form-item :label="$t('setting.oldPassword')" prop="oldPassword">
|
<el-form-item :label="$t('setting.oldPassword')" prop="oldPassword">
|
||||||
<el-input type="password" show-password clearable v-model="passForm.oldPassword" />
|
<el-input type="password" show-password clearable v-model.trim="passForm.oldPassword" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="complexityVerification === 'disable'"
|
v-if="complexityVerification === 'disable'"
|
||||||
:label="$t('setting.newPassword')"
|
:label="$t('setting.newPassword')"
|
||||||
prop="newPassword"
|
prop="newPassword"
|
||||||
>
|
>
|
||||||
<el-input type="password" show-password clearable v-model="passForm.newPassword" />
|
<el-input type="password" show-password clearable v-model.trim="passForm.newPassword" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="complexityVerification === 'enable'"
|
v-if="complexityVerification === 'enable'"
|
||||||
@@ -26,11 +26,11 @@
|
|||||||
type="password"
|
type="password"
|
||||||
show-password
|
show-password
|
||||||
clearable
|
clearable
|
||||||
v-model="passForm.newPasswordComplexity"
|
v-model.trim="passForm.newPasswordComplexity"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('setting.retryPassword')" prop="retryPassword">
|
<el-form-item :label="$t('setting.retryPassword')" prop="retryPassword">
|
||||||
<el-input type="password" show-password clearable v-model="passForm.retryPassword" />
|
<el-input type="password" show-password clearable v-model.trim="passForm.retryPassword" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -64,14 +64,16 @@ import { logOutApi } from '@/api/modules/auth';
|
|||||||
const globalStore = GlobalStore();
|
const globalStore = GlobalStore();
|
||||||
const passFormRef = ref<FormInstance>();
|
const passFormRef = ref<FormInstance>();
|
||||||
const passRules = reactive({
|
const passRules = reactive({
|
||||||
oldPassword: [Rules.requiredInput],
|
oldPassword: [Rules.noSpace, Rules.requiredInput],
|
||||||
newPassword: [
|
newPassword: [
|
||||||
Rules.requiredInput,
|
Rules.requiredInput,
|
||||||
|
Rules.noSpace,
|
||||||
{ min: 6, message: i18n.global.t('commons.rule.commonPassword'), trigger: 'blur' },
|
{ min: 6, message: i18n.global.t('commons.rule.commonPassword'), trigger: 'blur' },
|
||||||
],
|
],
|
||||||
newPasswordComplexity: [Rules.requiredInput, Rules.password],
|
newPasswordComplexity: [Rules.requiredInput, Rules.noSpace, Rules.password],
|
||||||
retryPassword: [Rules.requiredInput, { validator: checkPassword, trigger: 'blur' }],
|
retryPassword: [Rules.requiredInput, Rules.noSpace, { validator: checkPassword, trigger: 'blur' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const passwordVisible = ref<boolean>(false);
|
const passwordVisible = ref<boolean>(false);
|
||||||
const passForm = reactive({
|
const passForm = reactive({
|
||||||
|
|||||||
@@ -4,11 +4,18 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<DrawerHeader :header="$t('commons.login.username')" :back="handleClose" />
|
<DrawerHeader :header="$t('commons.login.username')" :back="handleClose" />
|
||||||
</template>
|
</template>
|
||||||
<el-form ref="formRef" label-position="top" :model="form" @submit.prevent v-loading="loading">
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
label-position="top"
|
||||||
|
:model="form"
|
||||||
|
@submit.prevent
|
||||||
|
v-loading="loading"
|
||||||
|
:rules="rules"
|
||||||
|
>
|
||||||
<el-row type="flex" justify="center">
|
<el-row type="flex" justify="center">
|
||||||
<el-col :span="22">
|
<el-col :span="22">
|
||||||
<el-form-item :label="$t('commons.login.username')" prop="userName" :rules="Rules.userName">
|
<el-form-item :label="$t('commons.login.username')" prop="userName">
|
||||||
<el-input clearable v-model="form.userName" />
|
<el-input clearable v-model.trim="form.userName" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -46,7 +53,9 @@ const loading = ref();
|
|||||||
const form = reactive({
|
const form = reactive({
|
||||||
userName: '',
|
userName: '',
|
||||||
});
|
});
|
||||||
|
const rules = reactive({
|
||||||
|
userName: [Rules.userName, Rules.noSpace],
|
||||||
|
});
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
|
|
||||||
const acceptParams = (params: DialogProps): void => {
|
const acceptParams = (params: DialogProps): void => {
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ let groups = ref<Group.GroupInfo[]>([]);
|
|||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
cacheSizeKey: 'website-page-size',
|
cacheSizeKey: 'website-page-size',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 10,
|
pageSize: Number(localStorage.getItem('website-page-size')) || 10,
|
||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
let req = reactive({
|
let req = reactive({
|
||||||
|
|||||||
Reference in New Issue
Block a user