mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-23 18:49:21 +08:00
feat: 面板关于信息实现
This commit is contained in:
parent
f99a2ae656
commit
99edb9c7ad
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,3 +15,4 @@
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
/pkg/
|
||||
backend/__debug_bin
|
||||
|
Binary file not shown.
@ -98,7 +98,7 @@ func (b *BaseApi) SafeEntrance(c *gin.Context) {
|
||||
}
|
||||
codeWithMD5 := encrypt.Md5(code)
|
||||
cookieValue, _ := encrypt.StringEncrypt(codeWithMD5)
|
||||
c.SetCookie(codeWithMD5, cookieValue, 86400, "", "", false, false)
|
||||
c.SetCookie(codeWithMD5, cookieValue, 604800, "", "", false, false)
|
||||
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
@ -88,25 +88,12 @@ func (b *BaseApi) UpdateBackup(c *gin.Context) {
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
func (b *BaseApi) PageBackup(c *gin.Context) {
|
||||
var req dto.PageInfo
|
||||
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
|
||||
}
|
||||
|
||||
total, list, err := backupService.Page(req)
|
||||
func (b *BaseApi) ListBackup(c *gin.Context) {
|
||||
data, err := backupService.List()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, dto.PageResult{
|
||||
Items: list,
|
||||
Total: total,
|
||||
})
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package dto
|
||||
import "time"
|
||||
|
||||
type BackupOperate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
Bucket string `json:"bucket"`
|
||||
Credential string `json:"credential"`
|
||||
@ -13,7 +12,6 @@ type BackupOperate struct {
|
||||
type BackupInfo struct {
|
||||
ID uint `json:"id"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Bucket string `json:"bucket"`
|
||||
Vars string `json:"vars"`
|
||||
|
@ -2,10 +2,8 @@ package model
|
||||
|
||||
type BackupAccount struct {
|
||||
BaseModel
|
||||
Name string `gorm:"type:varchar(64);not null" json:"name"`
|
||||
Type string `gorm:"type:varchar(64)" json:"type"`
|
||||
Type string `gorm:"type:varchar(64);unique;not null" json:"type"`
|
||||
Bucket string `gorm:"type:varchar(256)" json:"bucket"`
|
||||
Credential string `gorm:"type:varchar(256)" json:"credential"`
|
||||
Vars string `gorm:"type:longText" json:"vars"`
|
||||
Status string `gorm:"type:varchar(64)" json:"status"`
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ import (
|
||||
type BackupRepo struct{}
|
||||
|
||||
type IBackupRepo interface {
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.BackupAccount, error)
|
||||
Get(opts ...DBOption) (model.BackupAccount, error)
|
||||
List(opts ...DBOption) ([]model.BackupAccount, error)
|
||||
Create(backup *model.BackupAccount) error
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
@ -28,7 +29,7 @@ func (u *BackupRepo) Get(opts ...DBOption) (model.BackupAccount, error) {
|
||||
return backup, err
|
||||
}
|
||||
|
||||
func (u *BackupRepo) Page(page, size int, opts ...DBOption) (int64, []model.BackupAccount, error) {
|
||||
func (u *BackupRepo) List(opts ...DBOption) ([]model.BackupAccount, error) {
|
||||
var ops []model.BackupAccount
|
||||
db := global.DB.Model(&model.BackupAccount{})
|
||||
for _, opt := range opts {
|
||||
@ -36,8 +37,8 @@ func (u *BackupRepo) Page(page, size int, opts ...DBOption) (int64, []model.Back
|
||||
}
|
||||
count := int64(0)
|
||||
db = db.Count(&count)
|
||||
err := db.Limit(size).Offset(size * (page - 1)).Find(&ops).Error
|
||||
return count, ops, err
|
||||
err := db.Find(&ops).Error
|
||||
return ops, err
|
||||
}
|
||||
|
||||
func (u *BackupRepo) Create(backup *model.BackupAccount) error {
|
||||
|
@ -26,6 +26,12 @@ func (c *CommonRepo) WithByName(name string) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommonRepo) WithByType(name string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("type = ?", name)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommonRepo) WithLikeName(name string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("name like ?", "%"+name+"%")
|
||||
|
@ -102,7 +102,7 @@ func (u *AuthService) generateSession(c *gin.Context, name, authMethod string) (
|
||||
sessionUser, err := global.SESSION.Get(sID)
|
||||
if err != nil {
|
||||
sID = uuid.NewV4().String()
|
||||
c.SetCookie(constant.SessionName, sID, lifeTime, "", "", false, false)
|
||||
c.SetCookie(constant.SessionName, sID, 604800, "", "", false, false)
|
||||
err := global.SESSION.Set(sID, sessionUser, lifeTime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
type BackupService struct{}
|
||||
|
||||
type IBackupService interface {
|
||||
Page(search dto.PageInfo) (int64, interface{}, error)
|
||||
List() ([]dto.BackupInfo, error)
|
||||
Create(backupDto dto.BackupOperate) error
|
||||
GetBuckets(backupDto dto.ForBuckets) ([]interface{}, error)
|
||||
Update(id uint, upMap map[string]interface{}) error
|
||||
@ -24,21 +24,21 @@ func NewIBackupService() IBackupService {
|
||||
return &BackupService{}
|
||||
}
|
||||
|
||||
func (u *BackupService) Page(search dto.PageInfo) (int64, interface{}, error) {
|
||||
total, ops, err := backupRepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc"))
|
||||
func (u *BackupService) List() ([]dto.BackupInfo, error) {
|
||||
ops, err := backupRepo.List(commonRepo.WithOrderBy("created_at desc"))
|
||||
var dtobas []dto.BackupInfo
|
||||
for _, group := range ops {
|
||||
var item dto.BackupInfo
|
||||
if err := copier.Copy(&item, &group); err != nil {
|
||||
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
}
|
||||
dtobas = append(dtobas, item)
|
||||
}
|
||||
return total, dtobas, err
|
||||
return dtobas, err
|
||||
}
|
||||
|
||||
func (u *BackupService) Create(backupDto dto.BackupOperate) error {
|
||||
backup, _ := backupRepo.Get(commonRepo.WithByName(backupDto.Name))
|
||||
backup, _ := backupRepo.Get(commonRepo.WithByType(backupDto.Type))
|
||||
if backup.ID != 0 {
|
||||
return constant.ErrRecordExist
|
||||
}
|
||||
|
@ -50,17 +50,6 @@ func (u *SettingService) Update(c *gin.Context, key, value string) error {
|
||||
if err := settingRepo.Update(key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
switch key {
|
||||
case "UserName":
|
||||
sID, _ := c.Cookie(constant.SessionName)
|
||||
if sID != "" {
|
||||
c.SetCookie(constant.SessionName, sID, -1, "", "", false, false)
|
||||
err := global.SESSION.Delete(sID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return settingRepo.Update(key, value)
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ var AddTableSetting = &gormigrate.Migration{
|
||||
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 {
|
||||
if err := tx.Create(&model.Setting{Key: "SecurityEntrance", Value: "onepanel"}).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 {
|
||||
@ -127,10 +127,8 @@ var AddTableBackupAccount = &gormigrate.Migration{
|
||||
return err
|
||||
}
|
||||
item := &model.BackupAccount{
|
||||
Name: "Default Local",
|
||||
Type: "LOCAL",
|
||||
Status: "VALID",
|
||||
Vars: "{\"dir\":\"/opt/1Panel/backup\"}",
|
||||
Type: "LOCAL",
|
||||
Vars: "{\"dir\":\"/opt/1Panel/backup\"}",
|
||||
}
|
||||
if err := tx.Create(item).Error; err != nil {
|
||||
return err
|
||||
|
@ -1,7 +1,10 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/constant"
|
||||
"github.com/1Panel-dev/1Panel/global"
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -17,10 +20,18 @@ func SessionAuth() gin.HandlerFunc {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrTypeNotLogin, nil)
|
||||
return
|
||||
}
|
||||
if _, err := global.SESSION.Get(sId); err != nil {
|
||||
psession, err := global.SESSION.Get(sId)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrTypeNotLogin, nil)
|
||||
return
|
||||
}
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
setting, err := settingRepo.Get(settingRepo.WithByKey("SessionTimeout"))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("create operation record failed, err: %v", err)
|
||||
}
|
||||
lifeTime, _ := strconv.Atoi(setting.Value)
|
||||
_ = global.SESSION.Set(sId, psession, lifeTime)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ func (s *BackupRouter) InitBackupRouter(Router *gin.RouterGroup) {
|
||||
withRecordRouter := Router.Group("backups").Use(middleware.JwtAuth()).Use(middleware.SessionAuth()).Use(middleware.OperationRecord())
|
||||
baseApi := v1.ApiGroupApp.BaseApi
|
||||
{
|
||||
baRouter.POST("/search", baseApi.PageBackup)
|
||||
baRouter.GET("/search", baseApi.ListBackup)
|
||||
baRouter.POST("/buckets", baseApi.ListBuckets)
|
||||
withRecordRouter.POST("", baseApi.CreateBackup)
|
||||
withRecordRouter.POST("/del", baseApi.DeleteBackup)
|
||||
|
@ -1,7 +1,6 @@
|
||||
export namespace Backup {
|
||||
export interface BackupInfo {
|
||||
id: number;
|
||||
name: string;
|
||||
type: string;
|
||||
bucket: string;
|
||||
vars: string;
|
||||
@ -9,7 +8,6 @@ export namespace Backup {
|
||||
}
|
||||
export interface BackupOperate {
|
||||
id: number;
|
||||
name: string;
|
||||
type: string;
|
||||
bucket: string;
|
||||
credential: string;
|
||||
|
@ -1,9 +1,8 @@
|
||||
import http from '@/api';
|
||||
import { Backup } from '../interface/backup';
|
||||
import { ResPage, ReqPage } from '../interface';
|
||||
|
||||
export const getBackupList = (params: ReqPage) => {
|
||||
return http.post<ResPage<Backup.BackupInfo>>(`/backups/search`, params);
|
||||
export const getBackupList = () => {
|
||||
return http.get<Array<Backup.BackupInfo>>(`/backups/search`);
|
||||
};
|
||||
|
||||
export const addBackup = (params: Backup.BackupOperate) => {
|
||||
|
@ -1,9 +1,9 @@
|
||||
@font-face {
|
||||
font-family: "panel"; /* Project id 3575356 */
|
||||
src: url('iconfont.woff2?t=1662692062751') format('woff2'),
|
||||
url('iconfont.woff?t=1662692062751') format('woff'),
|
||||
url('iconfont.ttf?t=1662692062751') format('truetype'),
|
||||
url('iconfont.svg?t=1662692062751#panel') format('svg');
|
||||
src: url('iconfont.woff2?t=1663584463212') format('woff2'),
|
||||
url('iconfont.woff?t=1663584463212') format('woff'),
|
||||
url('iconfont.ttf?t=1663584463212') format('truetype'),
|
||||
url('iconfont.svg?t=1663584463212#panel') format('svg');
|
||||
}
|
||||
|
||||
.panel {
|
||||
@ -14,6 +14,38 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.p-taolun:before {
|
||||
content: "\e602";
|
||||
}
|
||||
|
||||
.p-StarStar:before {
|
||||
content: "\e635";
|
||||
}
|
||||
|
||||
.p-bug:before {
|
||||
content: "\e616";
|
||||
}
|
||||
|
||||
.p-SFTP:before {
|
||||
content: "\e647";
|
||||
}
|
||||
|
||||
.p-huaban88:before {
|
||||
content: "\e67c";
|
||||
}
|
||||
|
||||
.p-oss:before {
|
||||
content: "\e607";
|
||||
}
|
||||
|
||||
.p-s3:before {
|
||||
content: "\e8e4";
|
||||
}
|
||||
|
||||
.p-minio:before {
|
||||
content: "\e63c";
|
||||
}
|
||||
|
||||
.p-logout:before {
|
||||
content: "\e8fe";
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
247
frontend/src/assets/iconfont/iconfont.json
Normal file
247
frontend/src/assets/iconfont/iconfont.json
Normal file
@ -0,0 +1,247 @@
|
||||
{
|
||||
"id": "3575356",
|
||||
"name": "panel",
|
||||
"font_family": "panel",
|
||||
"css_prefix_text": "p-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "1760690",
|
||||
"name": "讨论",
|
||||
"font_class": "taolun",
|
||||
"unicode": "e602",
|
||||
"unicode_decimal": 58882
|
||||
},
|
||||
{
|
||||
"icon_id": "5192988",
|
||||
"name": "Star Star",
|
||||
"font_class": "StarStar",
|
||||
"unicode": "e635",
|
||||
"unicode_decimal": 58933
|
||||
},
|
||||
{
|
||||
"icon_id": "6642940",
|
||||
"name": "bug",
|
||||
"font_class": "bug",
|
||||
"unicode": "e616",
|
||||
"unicode_decimal": 58902
|
||||
},
|
||||
{
|
||||
"icon_id": "13532955",
|
||||
"name": "SFTP",
|
||||
"font_class": "SFTP",
|
||||
"unicode": "e647",
|
||||
"unicode_decimal": 58951
|
||||
},
|
||||
{
|
||||
"icon_id": "15337722",
|
||||
"name": "Logo GitHub",
|
||||
"font_class": "huaban88",
|
||||
"unicode": "e67c",
|
||||
"unicode_decimal": 59004
|
||||
},
|
||||
{
|
||||
"icon_id": "16268521",
|
||||
"name": "oss",
|
||||
"font_class": "oss",
|
||||
"unicode": "e607",
|
||||
"unicode_decimal": 58887
|
||||
},
|
||||
{
|
||||
"icon_id": "17895439",
|
||||
"name": "Amazon S3上传",
|
||||
"font_class": "s3",
|
||||
"unicode": "e8e4",
|
||||
"unicode_decimal": 59620
|
||||
},
|
||||
{
|
||||
"icon_id": "20290513",
|
||||
"name": "minio",
|
||||
"font_class": "minio",
|
||||
"unicode": "e63c",
|
||||
"unicode_decimal": 58940
|
||||
},
|
||||
{
|
||||
"icon_id": "924436",
|
||||
"name": "logout",
|
||||
"font_class": "logout",
|
||||
"unicode": "e8fe",
|
||||
"unicode_decimal": 59646
|
||||
},
|
||||
{
|
||||
"icon_id": "837256",
|
||||
"name": "terminal",
|
||||
"font_class": "terminal2",
|
||||
"unicode": "e82a",
|
||||
"unicode_decimal": 59434
|
||||
},
|
||||
{
|
||||
"icon_id": "8358944",
|
||||
"name": "英文5",
|
||||
"font_class": "yingwen",
|
||||
"unicode": "e6c3",
|
||||
"unicode_decimal": 59075
|
||||
},
|
||||
{
|
||||
"icon_id": "8358949",
|
||||
"name": "中文5",
|
||||
"font_class": "zhongwen",
|
||||
"unicode": "e6c8",
|
||||
"unicode_decimal": 59080
|
||||
},
|
||||
{
|
||||
"icon_id": "11487994",
|
||||
"name": "calendar",
|
||||
"font_class": "plan",
|
||||
"unicode": "e746",
|
||||
"unicode_decimal": 59206
|
||||
},
|
||||
{
|
||||
"icon_id": "11488064",
|
||||
"name": "integral",
|
||||
"font_class": "database",
|
||||
"unicode": "e754",
|
||||
"unicode_decimal": 59220
|
||||
},
|
||||
{
|
||||
"icon_id": "11488108",
|
||||
"name": "rejected-order",
|
||||
"font_class": "rejected-order",
|
||||
"unicode": "e75e",
|
||||
"unicode_decimal": 59230
|
||||
},
|
||||
{
|
||||
"icon_id": "11488148",
|
||||
"name": "tool",
|
||||
"font_class": "toolbox",
|
||||
"unicode": "e769",
|
||||
"unicode_decimal": 59241
|
||||
},
|
||||
{
|
||||
"icon_id": "4765743",
|
||||
"name": "earth",
|
||||
"font_class": "website",
|
||||
"unicode": "e781",
|
||||
"unicode_decimal": 59265
|
||||
},
|
||||
{
|
||||
"icon_id": "4765891",
|
||||
"name": "setting",
|
||||
"font_class": "config",
|
||||
"unicode": "e78e",
|
||||
"unicode_decimal": 59278
|
||||
},
|
||||
{
|
||||
"icon_id": "4765962",
|
||||
"name": "app store",
|
||||
"font_class": "appstore1",
|
||||
"unicode": "e792",
|
||||
"unicode_decimal": 59282
|
||||
},
|
||||
{
|
||||
"icon_id": "4765971",
|
||||
"name": "detail",
|
||||
"font_class": "log",
|
||||
"unicode": "e793",
|
||||
"unicode_decimal": 59283
|
||||
},
|
||||
{
|
||||
"icon_id": "4766440",
|
||||
"name": "sever",
|
||||
"font_class": "host",
|
||||
"unicode": "e7b1",
|
||||
"unicode_decimal": 59313
|
||||
},
|
||||
{
|
||||
"icon_id": "4766685",
|
||||
"name": "home",
|
||||
"font_class": "home",
|
||||
"unicode": "e7c6",
|
||||
"unicode_decimal": 59334
|
||||
},
|
||||
{
|
||||
"icon_id": "19688849",
|
||||
"name": "应用商店",
|
||||
"font_class": "appstore",
|
||||
"unicode": "eb65",
|
||||
"unicode_decimal": 60261
|
||||
},
|
||||
{
|
||||
"icon_id": "3876424",
|
||||
"name": "docker",
|
||||
"font_class": "docker",
|
||||
"unicode": "e659",
|
||||
"unicode_decimal": 58969
|
||||
},
|
||||
{
|
||||
"icon_id": "15838431",
|
||||
"name": "arrow-right",
|
||||
"font_class": "arrow-right",
|
||||
"unicode": "e665",
|
||||
"unicode_decimal": 58981
|
||||
},
|
||||
{
|
||||
"icon_id": "6172786",
|
||||
"name": "terminal",
|
||||
"font_class": "terminal",
|
||||
"unicode": "e864",
|
||||
"unicode_decimal": 59492
|
||||
},
|
||||
{
|
||||
"icon_id": "14772948",
|
||||
"name": "terminal",
|
||||
"font_class": "terminal1",
|
||||
"unicode": "e663",
|
||||
"unicode_decimal": 58979
|
||||
},
|
||||
{
|
||||
"icon_id": "7533292",
|
||||
"name": "中英文",
|
||||
"font_class": "language",
|
||||
"unicode": "e605",
|
||||
"unicode_decimal": 58885
|
||||
},
|
||||
{
|
||||
"icon_id": "22551111",
|
||||
"name": "主题",
|
||||
"font_class": "theme",
|
||||
"unicode": "e638",
|
||||
"unicode_decimal": 58936
|
||||
},
|
||||
{
|
||||
"icon_id": "22735864",
|
||||
"name": "文件类型-文件夹",
|
||||
"font_class": "file-folder",
|
||||
"unicode": "66",
|
||||
"unicode_decimal": 102
|
||||
},
|
||||
{
|
||||
"icon_id": "22761833",
|
||||
"name": "文件类型-未知文件",
|
||||
"font_class": "file-unknown",
|
||||
"unicode": "233",
|
||||
"unicode_decimal": 563
|
||||
},
|
||||
{
|
||||
"icon_id": "22761837",
|
||||
"name": "文件类型-Txt",
|
||||
"font_class": "file-txt",
|
||||
"unicode": "74",
|
||||
"unicode_decimal": 116
|
||||
},
|
||||
{
|
||||
"icon_id": "19671156",
|
||||
"name": "txt-1",
|
||||
"font_class": "file-normal",
|
||||
"unicode": "e7ac",
|
||||
"unicode_decimal": 59308
|
||||
},
|
||||
{
|
||||
"icon_id": "22761832",
|
||||
"name": "文件类型-压缩包",
|
||||
"font_class": "file-zip",
|
||||
"unicode": "e606",
|
||||
"unicode_decimal": 58886
|
||||
}
|
||||
]
|
||||
}
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 45 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
frontend/src/assets/images/ko_image.png
Normal file
BIN
frontend/src/assets/images/ko_image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
@ -262,6 +262,7 @@ export default {
|
||||
downloading: 'Downloading...',
|
||||
},
|
||||
setting: {
|
||||
all: 'All',
|
||||
panel: 'Panel',
|
||||
emailHelper: 'For password retrieval',
|
||||
title: 'Panel alias',
|
||||
@ -282,6 +283,8 @@ export default {
|
||||
|
||||
backup: 'Backup',
|
||||
serverDisk: 'Server disks',
|
||||
OSS: 'Ali OSS',
|
||||
S3: 'Amazon S3',
|
||||
backupAccount: 'Backup account',
|
||||
loadBucket: 'Get bucket',
|
||||
accountName: 'Account name',
|
||||
@ -298,11 +301,11 @@ export default {
|
||||
'The recommended port range is 8888 to 65535. Note: If the server has a security group, permit the new port from the security group in advance',
|
||||
safeEntrance: 'Security entrance',
|
||||
safeEntranceHelper:
|
||||
'Panel management portal. You can log in to the panel only through a specified security portal, for example, / 89DC6AE8',
|
||||
passwordTimeout: 'Password expiration Time',
|
||||
'Panel management portal. You can log in to the panel only through a specified security portal, for example: onepanel',
|
||||
passwordTimeout: 'Expiration Time',
|
||||
timeoutHelper:
|
||||
'[ {0} days ] The panel password is about to expire. After the expiration, you need to reset the password',
|
||||
complexity: 'Password complexity verification',
|
||||
complexity: 'Complexity verification',
|
||||
complexityHelper:
|
||||
'The password must contain at least eight characters and contain at least three uppercase letters, lowercase letters, digits, and special characters',
|
||||
mfa: 'MFA',
|
||||
@ -324,5 +327,12 @@ export default {
|
||||
emailAddr: 'Service address',
|
||||
emailSMTP: 'SMTP code',
|
||||
secret: 'Secret',
|
||||
|
||||
about: 'About',
|
||||
project: 'Project Address',
|
||||
issue: 'Feedback',
|
||||
chat: 'Community Discussion',
|
||||
star: 'Star',
|
||||
description: 'A modern Linux panel tool',
|
||||
},
|
||||
};
|
||||
|
@ -259,6 +259,7 @@ export default {
|
||||
downloading: '正在下载...',
|
||||
},
|
||||
setting: {
|
||||
all: '全部',
|
||||
panel: '面板',
|
||||
emailHelper: '用于密码找回',
|
||||
title: '面板别名',
|
||||
@ -278,6 +279,8 @@ export default {
|
||||
|
||||
backup: '备份',
|
||||
serverDisk: '服务器磁盘',
|
||||
OSS: '阿里云 OSS',
|
||||
S3: '亚马逊 S3 云存储',
|
||||
backupAccount: '备份账号',
|
||||
loadBucket: '获取桶',
|
||||
accountName: '账户名称',
|
||||
@ -292,7 +295,7 @@ export default {
|
||||
panelPort: '面板端口',
|
||||
portHelper: '建议端口范围8888 - 65535,注意:有安全组的服务器请提前在安全组放行新端口',
|
||||
safeEntrance: '安全入口',
|
||||
safeEntranceHelper: '面板管理入口,设置后只能通过指定安全入口登录面板,如: 89dc6ae8',
|
||||
safeEntranceHelper: '面板管理入口,设置后只能通过指定安全入口登录面板,如: onepanel',
|
||||
passwordTimeout: '密码过期时间',
|
||||
timeoutHelper: '【 {0} 天后 】面板密码即将过期,过期后需要重新设置密码',
|
||||
complexity: '密码复杂度验证',
|
||||
@ -318,5 +321,10 @@ export default {
|
||||
secret: '密钥',
|
||||
|
||||
about: '关于',
|
||||
project: '项目地址',
|
||||
issue: '问题反馈',
|
||||
chat: '参与讨论',
|
||||
star: '点亮 Star',
|
||||
description: '一个现代化的 Linux 面板工具',
|
||||
},
|
||||
};
|
||||
|
@ -410,23 +410,23 @@ onBeforeMount(() => {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.terminal-tabs {
|
||||
:deep(.el-tabs__header) {
|
||||
:deep .el-tabs__header {
|
||||
padding: 0;
|
||||
position: relative;
|
||||
margin: 0 0 3px 0;
|
||||
}
|
||||
:deep(.el-tabs__nav) {
|
||||
::deep .el-tabs__nav {
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
transition: transform var(--el-transition-duration);
|
||||
float: left;
|
||||
z-index: calc(var(--el-index-normal) + 1);
|
||||
}
|
||||
:deep(.el-tabs__item) {
|
||||
:deep .el-tabs__item {
|
||||
color: #575758;
|
||||
padding: 0 0px;
|
||||
}
|
||||
:deep(.el-tabs__item.is-active) {
|
||||
:deep .el-tabs__item.is-active {
|
||||
color: #ebeef5;
|
||||
background-color: #575758;
|
||||
}
|
||||
@ -441,7 +441,7 @@ onBeforeMount(() => {
|
||||
.fullScreen {
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
top: 6px;
|
||||
top: 86px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
@ -2,18 +2,27 @@
|
||||
<div>
|
||||
<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="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="about">关于</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="all">{{ $t('setting.all') }}</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="panel">
|
||||
{{ $t('setting.panel') }}
|
||||
</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="safe">{{ $t('setting.safe') }}</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="backup">
|
||||
{{ $t('setting.backup') }}
|
||||
</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="monitor">
|
||||
{{ $t('menu.monitor') }}
|
||||
</el-radio-button>
|
||||
<el-radio-button class="topButton" size="large" label="about">
|
||||
{{ $t('setting.about') }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-card>
|
||||
<Panel v-if="activeNames === 'all' || activeNames === 'panel'" :settingInfo="form" @on-save="SaveSetting" />
|
||||
<Safe v-if="activeNames === 'all' || activeNames === 'safe'" :settingInfo="form" @on-save="SaveSetting" />
|
||||
<Backup v-if="activeNames === 'all' || activeNames === 'backup'" :settingInfo="form" @on-save="SaveSetting" />
|
||||
<Monitor v-if="activeNames === 'all' || activeNames === 'monitor'" :settingInfo="form" @on-save="SaveSetting" />
|
||||
<About v-if="activeNames === 'all' || activeNames === 'about'" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -25,6 +34,7 @@ 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 About from '@/views/setting/tabs/about.vue';
|
||||
import { GlobalStore } from '@/store';
|
||||
import { useTheme } from '@/hooks/use-theme';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<el-card style="margin-top: 20px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>{{ $t('setting.about') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<div style="text-align: center">
|
||||
<div style="justify-self: center">
|
||||
<img style="width: 80px" src="@/assets/images/ko_image.png" />
|
||||
</div>
|
||||
<h1>1Panel</h1>
|
||||
<h3>{{ $t('setting.description') }}</h3>
|
||||
<h3>v0.0.1</h3>
|
||||
<div style="margin-top: 10px">
|
||||
<svg-icon style="font-size: 9px" iconName="p-huaban88"></svg-icon>
|
||||
<el-link @click="toGithub">
|
||||
<span>{{ $t('setting.project') }}</span>
|
||||
</el-link>
|
||||
<svg-icon style="font-size: 9px; margin-left: 15px" iconName="p-bug"></svg-icon>
|
||||
<el-link @click="toIssue">
|
||||
<span>{{ $t('setting.issue') }}</span>
|
||||
</el-link>
|
||||
<svg-icon style="font-size: 9px; margin-left: 15px" iconName="p-taolun"></svg-icon>
|
||||
<el-link @click="toTalk">
|
||||
<span>{{ $t('setting.chat') }}</span>
|
||||
</el-link>
|
||||
<svg-icon style="font-size: 9px; margin-left: 15px" iconName="p-StarStar"></svg-icon>
|
||||
<el-link @click="toGithubStar">
|
||||
<span>{{ $t('setting.star') }}</span>
|
||||
</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const toGithub = () => {
|
||||
window.open('https://github.com/1Panel-dev/1Panel', '_blank');
|
||||
};
|
||||
const toIssue = () => {
|
||||
window.open('https://github.com/1Panel-dev/1Panel/issues', '_blank');
|
||||
};
|
||||
const toTalk = () => {
|
||||
window.open('https://github.com/1Panel-dev/1Panel', '_blank');
|
||||
};
|
||||
const toGithubStar = () => {
|
||||
window.open('https://github.com/1Panel-dev/1Panel', '_blank');
|
||||
};
|
||||
</script>
|
@ -13,8 +13,9 @@
|
||||
<el-card class="el-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<svg-icon style="font-size: 7px" :iconName="loadIconName(item.type)"></svg-icon>
|
||||
<span style="font-size: 16px; font-weight: 500">
|
||||
[{{ item.type === 'LOCAL' ? $t('setting.serverDisk') : item.type }}] {{ item.name }}
|
||||
{{ loadBackupName(item.type) }}
|
||||
</span>
|
||||
<div style="float: right">
|
||||
<el-button @click="onEdit(item)">{{ $t('commons.button.edit') }}</el-button>
|
||||
@ -25,7 +26,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form label-position="left" label-width="130px">
|
||||
<el-form-item v-if="item.type === 'LOCAL'" label="Dir">
|
||||
<el-form-item v-if="item.type === 'LOCAL'" label="Directory">
|
||||
{{ item.varsJson['dir'] }}
|
||||
</el-form-item>
|
||||
<el-form-item v-if="hasBucket(item.type)" label="Access Key ID">
|
||||
@ -59,9 +60,6 @@
|
||||
|
||||
<el-dialog @close="search" v-model="backupVisiable" :title="$t('setting.backupAccount')" width="30%">
|
||||
<el-form ref="formRef" label-position="left" :model="form" label-width="160px">
|
||||
<el-form-item :label="$t('commons.table.name')" prop="name" :rules="Rules.name">
|
||||
<el-input v-model="form.name" :disabled="operation === 'edit'" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.type')" prop="type" :rules="Rules.requiredSelect">
|
||||
<el-select style="width: 100%" v-model="form.type" :disabled="operation === 'edit'">
|
||||
<el-option
|
||||
@ -74,7 +72,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.type === 'LOCAL'"
|
||||
label="Dir"
|
||||
label="Directory"
|
||||
prop="varsJson['dir']"
|
||||
:rules="Rules.requiredInput"
|
||||
>
|
||||
@ -94,7 +92,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="hasBucket(form.type)"
|
||||
label="Secret Access Key"
|
||||
label="Access Key Secret"
|
||||
prop="credential"
|
||||
:rules="Rules.requiredInput"
|
||||
>
|
||||
@ -182,19 +180,8 @@ const selects = ref<any>([]);
|
||||
const backupVisiable = ref<boolean>(false);
|
||||
const operation = ref<string>('create');
|
||||
|
||||
const paginationConfig = reactive({
|
||||
currentPage: 1,
|
||||
pageSize: 5,
|
||||
total: 0,
|
||||
});
|
||||
const backSearch = reactive({
|
||||
page: 1,
|
||||
pageSize: 5,
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
id: 0,
|
||||
name: '',
|
||||
type: 'LOCAL',
|
||||
bucket: '',
|
||||
credential: '',
|
||||
@ -203,31 +190,22 @@ const form = reactive({
|
||||
});
|
||||
type FormInstance = InstanceType<typeof ElForm>;
|
||||
const formRef = ref<FormInstance>();
|
||||
const typeOptions = ref([
|
||||
{ label: i18n.global.t('setting.serverDisk'), value: 'LOCAL' },
|
||||
{ label: 'OSS', value: 'OSS' },
|
||||
{ label: 'S3', value: 'S3' },
|
||||
{ label: 'SFTP', value: 'SFTP' },
|
||||
{ label: 'MINIO', value: 'MINIO' },
|
||||
]);
|
||||
const typeOptions = ref();
|
||||
const buckets = ref();
|
||||
|
||||
const search = async () => {
|
||||
backSearch.page = paginationConfig.currentPage;
|
||||
backSearch.pageSize = paginationConfig.pageSize;
|
||||
const res = await getBackupList(backSearch);
|
||||
data.value = res.data.items;
|
||||
const res = await getBackupList();
|
||||
data.value = res.data;
|
||||
for (const bac of data.value) {
|
||||
bac.varsJson = JSON.parse(bac.vars);
|
||||
}
|
||||
paginationConfig.total = res.data.total;
|
||||
};
|
||||
|
||||
const onCreate = () => {
|
||||
loadOption();
|
||||
operation.value = 'create';
|
||||
form.id = 0;
|
||||
form.name = '';
|
||||
form.type = 'LOCAL';
|
||||
form.type = typeOptions.value[0].value;
|
||||
form.bucket = '';
|
||||
form.credential = '';
|
||||
form.vars = '';
|
||||
@ -250,9 +228,15 @@ const onBatchDelete = async (row: Backup.BackupInfo | null) => {
|
||||
};
|
||||
|
||||
const onEdit = (row: Backup.BackupInfo) => {
|
||||
typeOptions.value = [
|
||||
{ label: i18n.global.t('setting.serverDisk'), value: 'LOCAL' },
|
||||
{ label: i18n.global.t('setting.OSS'), value: 'OSS' },
|
||||
{ label: i18n.global.t('setting.S3'), value: 'S3' },
|
||||
{ label: 'SFTP', value: 'SFTP' },
|
||||
{ label: 'MinIO', value: 'MINIO' },
|
||||
];
|
||||
restForm();
|
||||
form.id = row.id;
|
||||
form.name = row.name;
|
||||
form.type = row.type;
|
||||
form.bucket = row.bucket;
|
||||
form.varsJson = JSON.parse(row.vars);
|
||||
@ -296,6 +280,57 @@ const loadDir = async (path: string) => {
|
||||
console.log(path);
|
||||
form.varsJson['dir'] = path;
|
||||
};
|
||||
const loadOption = () => {
|
||||
let options = [
|
||||
{ label: i18n.global.t('setting.serverDisk'), value: 'LOCAL' },
|
||||
{ label: i18n.global.t('setting.OSS'), value: 'OSS' },
|
||||
{ label: i18n.global.t('setting.S3'), value: 'S3' },
|
||||
{ label: 'SFTP', value: 'SFTP' },
|
||||
{ label: 'MinIO', value: 'MINIO' },
|
||||
];
|
||||
for (const item of data.value) {
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
if (item.type === options[i].value) {
|
||||
options.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
typeOptions.value = options;
|
||||
};
|
||||
const loadIconName = (type: string) => {
|
||||
switch (type) {
|
||||
case 'OSS':
|
||||
return 'p-oss';
|
||||
break;
|
||||
case 'S3':
|
||||
return 'p-s3';
|
||||
break;
|
||||
case 'SFTP':
|
||||
return 'p-SFTP';
|
||||
break;
|
||||
case 'MINIO':
|
||||
return 'p-minio';
|
||||
break;
|
||||
case 'LOCAL':
|
||||
return 'p-file-folder';
|
||||
break;
|
||||
}
|
||||
};
|
||||
const loadBackupName = (type: string) => {
|
||||
switch (type) {
|
||||
case 'OSS':
|
||||
return i18n.global.t('setting.OSS');
|
||||
break;
|
||||
case 'S3':
|
||||
return i18n.global.t('setting.S3');
|
||||
break;
|
||||
case 'LOCAL':
|
||||
return i18n.global.t('setting.serverDisk');
|
||||
break;
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
|
@ -21,6 +21,7 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('auth.password')" :rules="Rules.requiredInput" prop="settingInfo.password">
|
||||
<el-input type="password" clearable disabled v-model="form.settingInfo.password">
|
||||
<template #append>
|
||||
@ -30,6 +31,7 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('auth.email')" :rules="Rules.email" prop="settingInfo.email">
|
||||
<el-input clearable v-model="form.settingInfo.email">
|
||||
<template #append>
|
||||
@ -45,6 +47,7 @@
|
||||
<span class="input-help">{{ $t('setting.emailHelper') }}</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
:label="$t('setting.title')"
|
||||
:rules="Rules.requiredInput"
|
||||
@ -61,6 +64,7 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('setting.theme')" :rules="Rules.requiredSelect" prop="settingInfo.theme">
|
||||
<el-radio-group
|
||||
@change="onSave(panelFormRef, 'Theme', form.settingInfo.theme)"
|
||||
@ -76,12 +80,14 @@
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
:label="$t('setting.language')"
|
||||
:rules="Rules.requiredSelect"
|
||||
prop="settingInfo.language"
|
||||
>
|
||||
<el-radio-group
|
||||
style="width: 100%"
|
||||
@change="onSave(panelFormRef, 'Language', form.settingInfo.language)"
|
||||
v-model="form.settingInfo.language"
|
||||
>
|
||||
@ -94,6 +100,7 @@
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
:label="$t('setting.sessionTimeout')"
|
||||
:rules="Rules.number"
|
||||
@ -115,6 +122,7 @@
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('setting.syncTime')">
|
||||
<el-input disabled v-model="form.settingInfo.localTime">
|
||||
<template #append>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form :model="form" ref="panelFormRef" label-position="left" label-width="160px">
|
||||
<el-card style="margin-top: 10px">
|
||||
<el-card style="margin-top: 20px">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>{{ $t('setting.safe') }}</span>
|
||||
@ -86,6 +86,7 @@
|
||||
:rules="Rules.requiredSelect"
|
||||
>
|
||||
<el-radio-group
|
||||
style="width: 100%"
|
||||
@change="
|
||||
onSave(
|
||||
panelFormRef,
|
||||
|
Loading…
Reference in New Issue
Block a user