Compare commits

...

10 Commits

Author SHA1 Message Date
03142cf8f3 后端修改获取图标逻辑 2024-04-12 11:31:47 +08:00
58adc495ce 后端修改获取图标逻辑 2024-04-12 11:27:18 +08:00
36ed79167f update 2024-04-11 14:24:55 +08:00
51ac40758e 修改权限 2024-04-09 12:11:46 +08:00
ce06c5a0d4 允许uayu 2024-04-09 10:43:17 +08:00
57fe832e38 修改 2024-04-08 17:41:05 +08:00
1dde3de9fa 1 2024-04-03 11:45:51 +08:00
wintsa
c19235e07f
Update README.md 2024-03-20 12:02:38 +08:00
wintsa
ed39082bfe
Update README.md 2024-03-20 12:01:28 +08:00
wintsa
91b19c0eb5
Update README.md
添加docker地址
2024-03-20 12:00:33 +08:00
52 changed files with 1201 additions and 944 deletions

11
.env
View File

@ -14,4 +14,13 @@ VITE_GLOB_APP_PWA=false
VITE_APP_VERSION=20240319
VITE_APP_VERSION=20240409

BIN
.yarn/install-state.gz Normal file

Binary file not shown.

1
.yarnrc.yml Normal file
View File

@ -0,0 +1 @@
nodeLinker: node-modules

View File

@ -30,14 +30,15 @@ COPY ./service .
# 中国国内源
# RUN sed -i "s@dl-cdn.alpinelinux.org@mirrors.aliyun.com@g" /etc/apk/repositories \
# && go env -w GOPROXY=https://goproxy.cn,direct
RUN apk add --no-cache bash curl gcc git musl-dev
RUN go env -w GO111MODULE=on \
&& export PATH=$PATH:/go/bin \
&& go env -w GOPROXY=https://goproxy.cn,direct \
&& go install -a -v github.com/go-bindata/go-bindata/...@latest \
&& go install -a -v github.com/elazarl/go-bindata-assetfs/...@latest \
&& go install -a -v github.com/gin-contrib/cors/...@latest \
&& go-bindata-assetfs -o=assets/bindata.go -pkg=assets assets/... \
&& go build -o sun-panel --ldflags="-X sun-panel/global.RUNCODE=release -X sun-panel/global.ISDOCKER=docker" main.go
@ -61,4 +62,4 @@ RUN apk add --no-cache bash ca-certificates su-exec tzdata \
&& chmod +x ./sun-panel \
&& ./sun-panel -config
CMD ./sun-panel
CMD ./sun-panel

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 红烧猎人
Copyright (c) 2023 wintsa
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -28,6 +28,9 @@ A server, NAS navigation panel, Homepage, Browser homepage.
</div>
本项目基于原版修改添加ping功能更smart判断内外网。
<a href='https://hub.docker.com/repository/docker/wintsa/sun-panel'>docker地址</a>
由于提了pr但原作者一直没合并自己魔改发包吧以后再加一些下载器监控之类的功能
![](./doc/images/main-dark.png)
## 😎 Features

12
compose-dev.yaml Normal file
View File

@ -0,0 +1,12 @@
services:
app:
entrypoint:
- sleep
- infinity
image: docker/dev-environments-default:stable-1
init: true
volumes:
- type: bind
source: /var/run/docker.sock
target: /var/run/docker.sock

0
conf/conf.example.ini Normal file
View File

0
conf/conf.ini Normal file
View File

17
copy-static-files.js Normal file
View File

@ -0,0 +1,17 @@
const fs = require('fs-extra');
const path = require('path');
const sourceDir = path.join(__dirname, 'dist');
const targetDir = path.join(__dirname, './service/web');
// 检查目标目录是否存在
if (!fs.existsSync(targetDir)) {
fs.emptyDirSync(targetDir); // 如果不存在,创建一个空目录
}
try {
fs.copySync(sourceDir, targetDir);
console.log('Files copied successfully!');
} catch (err) {
console.error('Error copying files:', err);
}

View File

@ -2,8 +2,8 @@ version: "3.2"
services:
sun-panel:
image: 'hslr/sun-panel:latest'
container_name: sun-panel
image: 'wintsa/zwpanel:latest'
container_name: zwpanel
volumes:
- ./conf:/app/conf
- ./uploads:/app/uploads

View File

@ -8,7 +8,7 @@
<link rel="stylesheet" href="/custom/index.css">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
<title>Sun-Panel</title>
<title>ZW Panel</title>
</head>
<body class="dark:bg-black">

View File

@ -1,7 +1,6 @@
{
"name": "sun-panel",
"version": "0.0.1",
"private": false,
"description": "Sun-Panel Web",
"author": "BraisedHunter <95302870@qq.com>",
"keywords": [
@ -19,7 +18,9 @@
"lint:fix": "eslint . --fix",
"bootstrap": "pnpm install && pnpm run common:prepare",
"common:cleanup": "rimraf node_modules && rimraf pnpm-lock.yaml",
"common:prepare": "husky install"
"common:prepare": "husky install",
"devBuild": " yarn run build && node copy-static-files.js && cd service && go run main.go",
"gobindaata":"go-bindata -o assets/assets.go -pkg assets assets/"
},
"dependencies": {
"@traptitech/markdown-it-katex": "^3.6.0",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -1 +1,2 @@
<svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 566.93 566.93"><defs><style>.cls-1{fill:#4fb3bb;}</style></defs><path class="cls-1" d="M99.37,502.4H345.56A156.16,156.16,0,0,0,501.72,346.25h0A156.16,156.16,0,0,0,345.56,190.1h-123A33.54,33.54,0,0,0,189,223.61v1a33.54,33.54,0,0,0,33.54,33.56H344.44c48.51,0,88.77,38.74,89.24,87.25a88.22,88.22,0,0,1-88.12,89s-163.09.37-245.94-.27a34.15,34.15,0,0,0-34.41,34.15h0A34.15,34.15,0,0,0,99.37,502.4Z"/><path class="cls-1" d="M467.56,64.53H221.37A156.15,156.15,0,0,0,65.21,220.68h0A156.15,156.15,0,0,0,221.37,376.83h123a33.54,33.54,0,0,0,33.54-33.51v-1a33.54,33.54,0,0,0-33.54-33.56H222.49c-48.52,0-88.77-38.74-89.24-87.25a88.22,88.22,0,0,1,88.12-89s163.09-.37,245.94.27a34.15,34.15,0,0,0,34.41-34.15h0A34.15,34.15,0,0,0,467.56,64.53Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve"> <image id="image0" width="48" height="48" x="0" y="0" xlink:href="data:image/png;base64,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"/>
</svg>

Before

Width:  |  Height:  |  Size: 823 B

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -88,7 +88,8 @@ func Error(ctx *gin.Context, errMsg string) {
// 返回错误 需要个性化定义的错误|带返回数据的错误
func ErrorNoAccess(ctx *gin.Context) {
ErrorCode(ctx, 1005, global.Lang.Get("common.no_access"), nil)
ErrorCode(ctx, 1005, "noAccess", nil)
}
// 返回错误 参数错误

View File

@ -80,7 +80,11 @@ func validateTransInit(validate *validator.Validate) ut.Translator {
}
func GetCurrentUserInfo(c *gin.Context) (userInfo models.User, exist bool) {
if value, exist := c.Get("userInfo"); exist {
value, exist := c.Get("userInfo")
fmt.Println("exist", exist)
fmt.Println("value", value)
if exist {
if v, ok := value.(models.User); ok {
return v, exist
}

View File

@ -43,14 +43,13 @@ func (a *ItemIconGroup) Edit(c *gin.Context) {
apiReturn.SuccessData(c, req)
}
func (a *ItemIconGroup) GetList(c *gin.Context) {
userInfo, _ := base.GetCurrentUserInfo(c)
groups := []models.ItemIconGroup{}
err := global.Db.Transaction(func(tx *gorm.DB) error {
if err := tx.Order("sort ,created_at").Where("user_id=?", userInfo.ID).Find(&groups).Error; err != nil {
if err := tx.Order("sort ,created_at").Find(&groups).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return err
}
@ -68,7 +67,7 @@ func (a *ItemIconGroup) GetList(c *gin.Context) {
}
// 并将当前账号下所有无分组的图标更新到当前组
if err := tx.Model(&models.ItemIcon{}).Where("user_id=?", userInfo.ID).Update("item_icon_group_id", defaultGroup.ID).Error; err != nil {
if err := tx.Model(&models.ItemIcon{}).Update("item_icon_group_id", defaultGroup.ID).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return err
}

View File

@ -6,6 +6,7 @@ import (
"net/url"
"os"
"path"
"path/filepath"
"strings"
"sun-panel/api/api_v1/common/apiData/commonApiStructs"
"sun-panel/api/api_v1/common/apiData/panelApiStructs"
@ -48,6 +49,11 @@ func (a *ItemIcon) Edit(c *gin.Context) {
}
if req.ID != 0 {
if userInfo.Role != 1 {
apiReturn.ErrorNoAccess(c)
c.Abort()
return
}
// 修改
updateField := []string{"IconJson", "Icon", "Title", "Url", "LanUrl", "Description", "OpenMethod", "GroupId", "UserId", "ItemIconGroupId"}
if req.Sort != 0 {
@ -131,10 +137,9 @@ func (a *ItemIcon) GetListByGroupId(c *gin.Context) {
return
}
userInfo, _ := base.GetCurrentUserInfo(c)
itemIcons := []models.ItemIcon{}
if err := global.Db.Order("sort ,created_at").Find(&itemIcons, "item_icon_group_id = ? AND user_id=?", req.ItemIconGroupId, userInfo.ID).Error; err != nil {
if err := global.Db.Order("sort ,created_at").Find(&itemIcons, "item_icon_group_id = ? ", req.ItemIconGroupId).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return
}
@ -154,8 +159,25 @@ func (a *ItemIcon) Deletes(c *gin.Context) {
return
}
userInfo, _ := base.GetCurrentUserInfo(c)
if err := global.Db.Delete(&models.ItemIcon{}, "id in ? AND user_id=?", req.Ids, userInfo.ID).Error; err != nil {
userInfo, exist := base.GetCurrentUserInfo(c)
if exist != true {
// 处理获取用户信息失败的情况
// 这里可以根据实际情况返回错误或进行其他处理
// 例如,返回一个 HTTP 错误响应或记录错误日志
apiReturn.ErrorNoAccess(c)
return
}
if userInfo.Role != 1 {
// 如果 userInfo 为空或者 userInfo 的 Role 不等于 1
// 可以根据实际情况返回错误或进行其他处理
// 例如,返回一个 HTTP 错误响应或记录错误日志
apiReturn.ErrorNoAccess(c)
return
}
if err := global.Db.Delete(&models.ItemIcon{}, "id in ? ", req.Ids).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return
}
@ -172,12 +194,28 @@ func (a *ItemIcon) SaveSort(c *gin.Context) {
return
}
userInfo, _ := base.GetCurrentUserInfo(c)
userInfo, exist := base.GetCurrentUserInfo(c)
if exist != true {
// 处理获取用户信息失败的情况
// 这里可以根据实际情况返回错误或进行其他处理
// 例如,返回一个 HTTP 错误响应或记录错误日志
apiReturn.ErrorNoAccess(c)
return
}
if userInfo.Role != 1 {
// 如果 userInfo 为空或者 userInfo 的 Role 不等于 1
// 可以根据实际情况返回错误或进行其他处理
// 例如,返回一个 HTTP 错误响应或记录错误日志
apiReturn.ErrorNoAccess(c)
return
}
transactionErr := global.Db.Transaction(func(tx *gorm.DB) error {
// 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db'
for _, v := range req.SortItems {
if err := tx.Model(&models.ItemIcon{}).Where("user_id=? AND id=? AND item_icon_group_id=?", userInfo.ID, v.Id, req.ItemIconGroupId).Update("sort", v.Sort).Error; err != nil {
if err := tx.Model(&models.ItemIcon{}).Where("id=? AND item_icon_group_id=?", v.Id, req.ItemIconGroupId).Update("sort", v.Sort).Error; err != nil {
// 返回任何错误都会回滚事务
return err
}
@ -206,12 +244,7 @@ func (a *ItemIcon) GetSiteFavicon(c *gin.Context) {
}
resp := panelApiStructs.ItemIconGetSiteFaviconResp{}
fullUrl := ""
if iconUrl, err := siteFavicon.GetOneFaviconURL(req.Url); err != nil {
apiReturn.Error(c, "acquisition failed: get ico error:"+err.Error())
return
} else {
fullUrl = iconUrl
}
fullUrl = siteFavicon.GetOneFaviconURL(req.Url)
parsedURL, err := url.Parse(req.Url)
if err != nil {
@ -230,17 +263,7 @@ func (a *ItemIcon) GetSiteFavicon(c *gin.Context) {
// 如果URL既不以http://开头也不以https://开头则默认为http协议
fullUrl = "http://" + fullUrl
}
global.Logger.Debug("fullUrl:", fullUrl)
// 去除图标的get参数
{
parsedIcoURL, err := url.Parse(fullUrl)
if err != nil {
apiReturn.Error(c, "acquisition failed: parsed ico URL :"+err.Error())
return
}
fullUrl = parsedIcoURL.Scheme + "://" + parsedIcoURL.Host + parsedIcoURL.Path
}
global.Logger.Debug("fullUrl:", fullUrl)
global.Logger.Debug("fullUrl111:", fullUrl)
// 生成保存目录
configUpload := global.Config.GetValueString("base", "source_path")
@ -253,13 +276,64 @@ func (a *ItemIcon) GetSiteFavicon(c *gin.Context) {
// 下载
var imgInfo *os.File
{
var err error
if imgInfo, err = siteFavicon.DownloadImage(fullUrl, savePath, 1024*1024); err != nil {
apiReturn.Error(c, "acquisition failed: download"+err.Error())
return
{
imgInfo, err = siteFavicon.DownloadImage(fullUrl, savePath, 1024*1024)
if err != nil {
u, err := url.Parse(fullUrl)
if err != nil {
// 处理 URL 解析错误
return
}
// 获取主机名
hostname := u.Hostname()
// 去掉子域名前缀
parts := strings.Split(hostname, ".")
if len(parts) > 2 {
hostname = strings.Join(parts[1:], ".")
}
// 构建新的 URL
newUrl := u.Scheme + "://" + hostname + u.RequestURI()
imgInfo, err = siteFavicon.DownloadImage(newUrl, savePath, 1024*1024)
// 重新尝试下载
if err != nil {
if iconUrl, err := siteFavicon.GetOneFaviconURLByhead(req.Url); err != nil {
apiReturn.Error(c, "acquisition failed: get ico error:"+err.Error())
return
} else {
fullUrl = iconUrl
u, err := url.Parse(fullUrl)
if err != nil {
// 处理 URL 解析错误
apiReturn.Error(c, "acquisition failed: get ico error:"+err.Error())
return
}
// 获取主机名
hostname := u.Hostname()
absolutePath := filepath.Clean(u.RequestURI())
// 构建新的 URL
newUrl := u.Scheme + "://" + hostname + absolutePath
newUrl = strings.ReplaceAll(newUrl, "\\", "/")
fmt.Println(newUrl)
imgInfo, err = siteFavicon.DownloadImage(newUrl, savePath, 1024*1024)
if err != nil {
fmt.Println(err)
apiReturn.Error(c, "acquisition failed: get ico error:"+err.Error())
return
}
}
}
}
}
}
// 保存到数据库
ext := path.Ext(fullUrl)
mFile := models.File{}

View File

@ -16,9 +16,9 @@ type UserConfig struct {
}
func (a *UserConfig) Get(c *gin.Context) {
userInfo, _ := base.GetCurrentUserInfo(c)
// userInfo, _ := base.GetCurrentUserInfo(c)
cfg := models.UserConfig{}
if err := global.Db.First(&cfg, "user_id=?", userInfo.ID).Error; err != nil {
if err := global.Db.First(&cfg).Error; err != nil {
if err == gorm.ErrRecordNotFound {
apiReturn.ErrorDataNotFound(c)
return

View File

@ -101,9 +101,9 @@ func (a *FileApi) UploadFiles(c *gin.Context) {
func (a *FileApi) GetList(c *gin.Context) {
list := []models.File{}
userInfo, _ := base.GetCurrentUserInfo(c)
// userInfo, _ := base.GetCurrentUserInfo(c)
var count int64
if err := global.Db.Order("created_at desc").Find(&list, "user_id=?", userInfo.ID).Count(&count).Error; err != nil {
if err := global.Db.Order("created_at desc").Find(&list).Count(&count).Error; err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return
}
@ -124,7 +124,7 @@ func (a *FileApi) GetList(c *gin.Context) {
func (a *FileApi) Deletes(c *gin.Context) {
req := commonApiStructs.RequestDeleteIds[uint]{}
userInfo, _ := base.GetCurrentUserInfo(c)
// userInfo, _ := base.GetCurrentUserInfo(c)
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
apiReturn.ErrorParamFomat(c, err.Error())
return
@ -133,7 +133,7 @@ func (a *FileApi) Deletes(c *gin.Context) {
global.Db.Transaction(func(tx *gorm.DB) error {
files := []models.File{}
if err := tx.Order("created_at desc").Find(&files, "user_id=? AND id in ?", userInfo.ID, req.Ids).Error; err != nil {
if err := tx.Order("created_at desc").Find(&files, " id in ?", req.Ids).Error; err != nil {
return err
}
@ -141,7 +141,7 @@ func (a *FileApi) Deletes(c *gin.Context) {
os.Remove(v.Src)
}
if err := tx.Order("created_at desc").Delete(&files, "user_id=? AND id in ?", userInfo.ID, req.Ids).Error; err != nil {
if err := tx.Order("created_at desc").Delete(&files, "id in ?", req.Ids).Error; err != nil {
return err
}

View File

@ -1,6 +1,10 @@
package system
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"sun-panel/api/api_v1/common/apiReturn"
@ -25,6 +29,9 @@ type LoginLoginVerify struct {
VCode string `json:"vcode" validate:"max=6"`
Email string `json:"email"`
}
type getTokenVerify struct {
Username string `json:"username" validate:"required"`
}
// @Summary 登录账号
// @Accept application/json
@ -32,6 +39,7 @@ type LoginLoginVerify struct {
// @Param LoginLoginVerify body LoginLoginVerify true "登陆验证信息"
// @Tags user
// @Router /login [post]
func (l LoginApi) Login(c *gin.Context) {
param := LoginLoginVerify{}
if err := c.ShouldBindJSON(&param); err != nil {
@ -111,3 +119,166 @@ func (l *LoginApi) Logout(c *gin.Context) {
global.CUserToken.Delete(cToken)
apiReturn.Success(c)
}
/**
* @Author: wintsa
* @Date: 2024-04-09 11:01:55
* @LastEditors: wintsa
* @Description: token生成
* @return {*}
*/
func (l LoginApi) GetToken(c *gin.Context) {
param := getTokenVerify{}
if err := c.ShouldBindJSON(&param); err != nil {
apiReturn.ErrorParamFomat(c, err.Error())
return
}
if errMsg, err := base.ValidateInputStruct(param); err != nil {
apiReturn.ErrorParamFomat(c, errMsg)
return
}
fmt.Print("-----------2")
settings := systemSetting.ApplicationSetting{}
global.SystemSetting.GetValueByInterface("system_application", &settings)
fmt.Print("-----------2")
mUser := models.User{}
var (
err error
info models.User
)
bToken := ""
param.Username = strings.TrimSpace(param.Username)
info, err = mUser.GetUserInfoByUsername(param.Username)
if err != nil {
// 未找到记录 账号
if err == gorm.ErrRecordNotFound {
fmt.Print("-----------2")
client := &http.Client{}
data := url.Values{}
data.Set("appid", "a2a6cab8-42e2-46d0-b0d2-4013e6708103")
data.Set("loginid", param.Username)
// 创建 HTTP 请求
req, err := http.NewRequest("POST", "https://oa.zwgczx.com/ssologin/getToken", strings.NewReader(data.Encode()))
if err != nil {
panic(err)
}
// 设置请求头
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
// 发送POST请求
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
// 读取响应
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
if strings.Contains(string(body), "Token获取失败") {
fmt.Println("请求失败: Token获取失败")
apiReturn.ErrorNoAccess(c)
panic("请求失败: Token获取失败")
return
}
mUser := models.User{
Username: strings.TrimSpace(param.Username),
Password: cmn.PasswordEncryption("zw.123456"),
Name: param.Username,
HeadImage: "",
Status: 1,
Role: 2,
// Mail: param.Username, 不再保存邮箱账号字段
}
userInfo, err := mUser.CreateOne()
if err != nil {
apiReturn.ErrorDatabase(c, err.Error())
return
}
info = userInfo
} else {
// 未知错误
apiReturn.Error(c, err.Error())
return
}
}
// 停用或未激活
if info.Status != 1 {
apiReturn.ErrorByCode(c, 1004)
return
}
bToken = info.Token
if info.Token == "" {
// 生成token
buildTokenOver := false
for !buildTokenOver {
bToken = cmn.BuildRandCode(32, cmn.RAND_CODE_MODE2)
if _, err := mUser.GetUserInfoByToken(bToken); err != nil {
// 保存token
mUser.UpdateUserInfoByUserId(info.ID, map[string]interface{}{
"token": bToken,
})
buildTokenOver = true
}
}
info.Token = bToken
}
info.Password = ""
info.ReferralCode = ""
// global.UserToken.SetDefault(bToken, info)
cToken := uuid.NewString() + "-" + cmn.Md5(cmn.Md5("userId"+strconv.Itoa(int(info.ID))))
global.CUserToken.SetDefault(cToken, bToken)
global.Logger.Debug("token:", cToken, "|", bToken)
global.Logger.Debug(global.CUserToken.Get(cToken))
fmt.Println("info", info)
// 设置当前用户信息
c.Set("userInfo", info)
apiReturn.SuccessData(c, cToken)
}
/**
* @Author: wintsa
* @Date: 2024-04-09 11:02:30
* @LastEditors: wintsa
* @Description: token验证
* @return {*}
*/
func (l LoginApi) VerifyToken(c *gin.Context) {
// 从请求参数中获取 token
token := c.Query("token")
fmt.Println("---------------------------", token)
// 检查 token 的有效性(这里仅做示例,实际需要根据业务逻辑来验证)
if bToken, err := global.CUserToken.Get(token); err != false {
// Token 有效,返回验证成功的响应
mUser := models.User{}
userInfo, err := mUser.GetUserInfoByToken(bToken)
if err != nil {
apiReturn.ErrorNoAccess(c)
return
}
apiReturn.SuccessData(c, userInfo)
} else {
// Token 无效,返回验证失败的响应
apiReturn.ErrorNoAccess(c)
}
}

View File

@ -5,11 +5,11 @@
# Web run port. Default:3002
http_port=3002
# Database driver [mysql/sqlite(Default)]
database_drive=sqlite
database_drive=mysql
# Cache driver [redis/memory(Default)]
cache_drive=memory
cache_drive=redis
# Queue driver [redis/memory(Default)]
queue_drive=memory
queue_drive=redis
# File cache path (Please start with the current path './')
# Warning: The files that have been uploaded after the modification cannot be accessed
source_path=./uploads
@ -20,11 +20,11 @@ source_temp_path=./runtime/temp
# Mysql database driver
# ======================
[mysql]
host=127.0.0.1
host=192.168.2.222
port=3306
username=root
password=root
db_name=sun_panel
password=12300114
db_name=navpanel
wait_timeout=100
# ======================

View File

@ -5,10 +5,11 @@ go 1.20
require (
github.com/PuerkitoBio/goquery v1.8.1
github.com/fatih/color v1.15.0
github.com/gin-gonic/gin v1.9.0
github.com/gin-contrib/cors v1.7.1
github.com/gin-gonic/gin v1.9.1
github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.11.2
github.com/go-playground/validator/v10 v10.19.0
github.com/google/uuid v1.3.0
github.com/mojocn/base64Captcha v1.3.5
github.com/patrickmn/go-cache v2.1.0+incompatible
@ -26,43 +27,47 @@ require (
require (
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/bytedance/sonic v1.8.0 // indirect
github.com/bytedance/sonic v1.11.3 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.18 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pelletier/go-toml/v2 v2.2.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/shoenig/go-m1cpu v0.1.4 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/arch v0.7.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@ -6,24 +6,36 @@ github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLj
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA=
github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/cors v1.7.1 h1:s9SIppU/rk8enVvkzwiC2VK3UZ/0NNGsWfUKvV55rqs=
github.com/gin-contrib/cors v1.7.1/go.mod h1:n/Zj7B4xyrgk/cX1WCX2dkzFfaNm/xJb6oIUk7WTtps=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
@ -31,16 +43,14 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@ -53,31 +63,35 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0=
github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -97,22 +111,24 @@ github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnj
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
@ -125,12 +141,13 @@ go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 h1:TbGuee8sSq15Iguxu4deQ7+Bqq/d2rsQejGcEtADAMQ=
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@ -139,8 +156,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -155,8 +172,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@ -165,16 +182,15 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -193,4 +209,5 @@ gorm.io/driver/sqlite v1.5.4/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -135,13 +135,13 @@ func NotFoundAndCreateUser(db *gorm.DB) error {
if err != gorm.ErrRecordNotFound {
return err
}
username := "admin@sun.cc"
username := "zwgczx"
fUser.Mail = username
fUser.Username = username
fUser.Name = username
fUser.Status = 1
fUser.Role = 1
fUser.Password = cmn.PasswordEncryption("12345678")
fUser.Password = cmn.PasswordEncryption("1QAZ2WSX.com")
if errCreate := db.Create(&fUser).Error; errCreate != nil {
return errCreate

View File

@ -11,8 +11,9 @@ import (
"sort"
"strconv"
"strings"
"sun-panel/assets"
"time"
"sun-panel/assets"
)
const (

View File

@ -26,7 +26,14 @@ func IsHTTPURL(url string) bool {
return match
}
func GetOneFaviconURL(urlStr string) (string, error) {
func GetOneFaviconURL(urlStr string) string {
urlInfo, _ := url.Parse(urlStr)
fullUrl := urlInfo.Scheme + "://" + urlInfo.Host + "/favicon.ico"
return fullUrl
}
func GetOneFaviconURLByhead(urlStr string) (string, error) {
iconURLs, err := getFaviconURL(urlStr)
if err != nil {
return "", err

View File

@ -14,6 +14,7 @@ func main() {
panic(err)
}
httpPort := global.Config.GetValueStringOrDefault("base", "http_port")
log.Println("初始化:", httpPort)
if err := router.InitRouters(":" + httpPort); err != nil {
panic(err)

View File

@ -40,7 +40,6 @@ func (m *ModuleConfig) Save(db *gorm.DB) error {
m.ValueJson = string(jb)
}
// 保存操作
if err := db.First(&ModuleConfig{}, "user_id=? AND name=?", m.UserId, m.Name).Error; err != nil {
if err == gorm.ErrRecordNotFound {
// 新增

View File

@ -7,16 +7,18 @@ import (
"sun-panel/router/panel"
"sun-panel/router/system"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
)
// 初始化总路由
func InitRouters(addr string) error {
router := gin.Default()
router.Use(cors.Default())
rootRouter := router.Group("/")
routerGroup := rootRouter.Group("api")
// 接口
system.Init(routerGroup)
panel.Init(routerGroup)
openness.Init(routerGroup)

View File

@ -11,10 +11,11 @@ func InitItemIcon(router *gin.RouterGroup) {
itemIcon := api_v1.ApiGroupApp.ApiPanel.ItemIcon
r := router.Group("", middleware.LoginInterceptor)
{
r.POST("/panel/itemIcon/edit", itemIcon.Edit)
r.POST("/panel/itemIcon/deletes", itemIcon.Deletes)
r.POST("/panel/itemIcon/saveSort", itemIcon.SaveSort)
r.POST("/panel/itemIcon/addMultiple", itemIcon.AddMultiple)
r.POST("/panel/itemIcon/deletes", middleware.AdminInterceptor, itemIcon.Deletes)
r.POST("/panel/itemIcon/saveSort", middleware.AdminInterceptor, itemIcon.SaveSort)
r.POST("/panel/itemIcon/addMultiple", middleware.AdminInterceptor, itemIcon.AddMultiple)
r.POST("/panel/itemIcon/getSiteFavicon", itemIcon.GetSiteFavicon)
}

View File

@ -11,9 +11,9 @@ func InitItemIconGroup(router *gin.RouterGroup) {
itemIconGroup := api_v1.ApiGroupApp.ApiPanel.ItemIconGroup
r := router.Group("", middleware.LoginInterceptor)
{
r.POST("/panel/itemIconGroup/edit", itemIconGroup.Edit)
r.POST("/panel/itemIconGroup/deletes", itemIconGroup.Deletes)
r.POST("/panel/itemIconGroup/saveSort", itemIconGroup.SaveSort)
r.POST("/panel/itemIconGroup/edit", middleware.AdminInterceptor, itemIconGroup.Edit)
r.POST("/panel/itemIconGroup/deletes", middleware.AdminInterceptor, itemIconGroup.Deletes)
r.POST("/panel/itemIconGroup/saveSort", middleware.AdminInterceptor, itemIconGroup.SaveSort)
}
// 公开模式

View File

@ -12,5 +12,7 @@ func InitLogin(router *gin.RouterGroup) {
router.POST("/login", loginApi.Login)
router.POST("/logout", middleware.LoginInterceptor, loginApi.Logout)
router.POST("/getToken", loginApi.GetToken)
router.GET("/verifyToken", loginApi.VerifyToken)
}

View File

@ -1,4 +1,4 @@
import { post } from '@/utils/request'
import { post,get } from '@/utils/request'
// 登录相关
@ -8,7 +8,12 @@ export function login<T>(data: Login.LoginReqest) {
data,
})
}
//验证
export function verifyToken<T>(token: string) {
return get({
url: `/verifyToken?token=${token}`,
})
}
export function logout<T>() {
return post<T>({
url: '/logout',

View File

@ -14,6 +14,7 @@ export function edit<T>(req: Panel.ItemInfo) {
})
}
// export function getInfo<T>(id: number) {
// return post<T>({
// url: '/aiApplet/getInfo',

View File

@ -1 +1,2 @@
<svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 566.93 566.93"><defs><style>.cls-1{fill:#4fb3bb;}</style></defs><path class="cls-1" d="M99.37,502.4H345.56A156.16,156.16,0,0,0,501.72,346.25h0A156.16,156.16,0,0,0,345.56,190.1h-123A33.54,33.54,0,0,0,189,223.61v1a33.54,33.54,0,0,0,33.54,33.56H344.44c48.51,0,88.77,38.74,89.24,87.25a88.22,88.22,0,0,1-88.12,89s-163.09.37-245.94-.27a34.15,34.15,0,0,0-34.41,34.15h0A34.15,34.15,0,0,0,99.37,502.4Z"/><path class="cls-1" d="M467.56,64.53H221.37A156.15,156.15,0,0,0,65.21,220.68h0A156.15,156.15,0,0,0,221.37,376.83h123a33.54,33.54,0,0,0,33.54-33.51v-1a33.54,33.54,0,0,0-33.54-33.56H222.49c-48.52,0-88.77-38.74-89.24-87.25a88.22,88.22,0,0,1,88.12-89s163.09-.37,245.94.27a34.15,34.15,0,0,0,34.41-34.15h0A34.15,34.15,0,0,0,467.56,64.53Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve"> <image id="image0" width="48" height="48" x="0" y="0" xlink:href="data:image/png;base64,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"/>
</svg>

Before

Width:  |  Height:  |  Size: 823 B

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -2,24 +2,16 @@
import { NDivider, NGradientText, NTag } from 'naive-ui'
import { onMounted, ref } from 'vue'
import { get } from '@/api/system/about'
import { useAppStore } from '@/store'
import srcSvglogo from '@/assets/logo.svg'
import srcGitee from '@/assets/about_image/gitee.png'
import srcGithub from '@/assets/about_image/github.png'
import srcDocker from '@/assets/about_image/docker.png'
import srcBilibili from '@/assets/about_image/bilibili.png'
import srcYoutube from '@/assets/about_image/youtube.png'
import srcQQGroupQR from '@/assets/about_image/qq_group_qr2.png'
import { RoundCardModal } from '@/components/common'
interface Version {
versionName: string
versionCode: number
}
const appStore = useAppStore()
const versionName = ref('')
const qqGroupQRShow = ref(false)
const frontVersion = import.meta.env.VITE_APP_VERSION || 'unknown'
onMounted(() => {
@ -39,12 +31,10 @@ onMounted(() => {
</div>
<div class="text-xl">
<NGradientText type="info">
<a href="https://github.com/hslr-s/sun-panel/releases" class="font-semibold" :title="$t('apps.about.viewUpdateLog')" target="_blank">v{{ versionName }}</a>
<a href="" class="font-semibold" :title="$t('apps.about.viewUpdateLog')" >v{{ versionName }}</a>
</NGradientText>
</div>
<div class="mt-2">
<a href="https://github.com/hslr-s/sun-panel/releases" target="_blank" class="link">{{ $t('apps.about.checkUpdate') }}</a>
</div>
</div>
<NDivider style="margin:10px 0">
@ -52,45 +42,14 @@ onMounted(() => {
</NDivider>
<div class="flex flex-col items-center justify-center text-base">
<div>
{{ $t('apps.about.author') }}<a href="https://github.com/hslr-s" target="_blank" class="link">红烧猎人</a> | <a href="https://github.com/hslr-s/sun-panel/blob/master/doc/donate.md" target="_blank" class="text-red-600 hover:text-red-900">{{ $t('apps.about.donate') }}</a>
{{ $t('apps.about.author') }}<a href="https://github.com/wintsa" target="_blank" class="link">wintsa</a>
</div>
<div>
{{ $t('apps.about.issue') }}<a href="https://github.com/hslr-s/sun-panel/issues" target="_blank" class="link">Github Issues</a>
</div>
<div>
{{ $t('apps.about.discussions') }}<a href="https://github.com/hslr-s/sun-panel/discussions" target="_blank" class="link">Github Discussions</a>
</div>
<div>
{{ $t('apps.about.QQGroup') }}<a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=K6UII6aEPZUeDRIPOEpOSJZH-Vmr_RPu&authKey=jEXhnVekLbDDx5UkQzKtd3bRmhZggkGBxmvW4NT5LLIAFP7toMmqABwvkANGHbLb&noverify=0&group_code=831615449" target="_blank" class="link">{{ $t("apps.about.addQQGroupUrl") }}</a>
|
<span class="link cursor-pointer" @click="qqGroupQRShow = !qqGroupQRShow">
{{ $t('apps.about.QR') }}
</span>
{{ $t('apps.about.issue') }}<a href="" class="link">联系信息开发部</a>
</div>
<div class="flex mt-[10px] flex-wrap justify-center">
<div class="flex items-center mx-[10px]">
<img class="w-[20px] h-[20px] mr-[5px]" :src="srcGithub" alt="">
<a href="https://github.com/hslr-s/sun-panel" target="_blank" class="link">Github</a>
</div>
<div class="flex items-center mx-[10px]">
<img class="w-[20px] h-[20px] mr-[5px]" :src="srcGitee" alt="">
<a href="https://gitee.com/hslr/sun-panel" target="_blank" class="link">Gitee</a>
</div>
<div class="flex items-center mx-[10px]">
<img class="w-[20px] h-[20px] mr-[5px]" :src="srcDocker" alt="">
<a href="https://hub.docker.com/r/hslr/sun-panel" target="_blank" class="link">Docker</a>
</div>
<div class="flex items-center mx-[10px]">
<img class="w-[20px] h-[20px] mr-[5px]" :src="srcBilibili" alt="">
<!-- <a href="https://space.bilibili.com/27407696/channel/collectiondetail?sid=2023810" target="_blank" class="link">Bilibili</a> -->
<a href="https://space.bilibili.com/27407696/channel/collectiondetail?sid=2023810" target="_blank" class="link">Bilibili</a>
</div>
<div v-if="appStore.language !== 'zh-CN'" class="flex items-center mx-[10px]">
<img class="w-[20px] h-[20px] mr-[5px]" :src="srcYoutube" alt="">
<a href="https://www.youtube.com/channel/UCKwbFmKU25R602z6P2fgPYg" target="_blank" class="link">YouTube</a>
</div>
</div>
<div class="mt-5">
<NTag :bordered="false" size="small">
@ -98,14 +57,7 @@ onMounted(() => {
</NTag>
</div>
<RoundCardModal v-model:show="qqGroupQRShow" title="交流群二维码" style="width: 300px;">
<div class="text-center">
- 如果失效请返回联系作者 -
</div>
<div class="flex justify-center">
<img :src="srcQQGroupQR" class="h-[260px]">
</div>
</RoundCardModal>
</div>
</div>
</template>

View File

@ -51,7 +51,7 @@ const defaultSearchEngineList = ref<DeskModule.SearchBox.SearchEngine[]>([
])
const defaultState: State = {
currentSearchEngine: defaultSearchEngineList.value[0],
currentSearchEngine: defaultSearchEngineList.value[1],
searchEngineList: [] || defaultSearchEngineList,
newWindowOpen: false,
}
@ -68,7 +68,7 @@ const onBlur = (): void => {
function handleEngineClick() {
// 访
if (authStore.visitMode === VisitMode.VISIT_MODE_PUBLIC)
if (authStore.visitMode === VisitMode.VISIT_MODE_PUBLIC &&authStore.userInfo?.role!=1)
return
searchSelectListShow.value = !searchSelectListShow.value
}

View File

@ -184,7 +184,7 @@ function handleRightMenuSelect(key: string | number) {
{{ $t('deskModule.systemMonitor.systemState') }}
</span>
<div
v-if="allowEdit"
v-if="allowEdit"
class="system-monitor-buttons ml-2 delay-100 transition-opacity flex"
:class="monitorGroup.hoverStatus ? 'opacity-100' : 'opacity-0'"
>

View File

@ -131,7 +131,7 @@
"action": "Action",
"add": "Add",
"addSuccess": "Added successfully",
"appName": "Sun-Panel",
"appName": "ZW-Panel",
"backgroundColor": "Background color",
"cancel": "Cancel",
"confirm": "Confirm",

View File

@ -131,7 +131,7 @@
"action": "操作",
"add": "添加",
"addSuccess": "添加成功",
"appName": "Sun-Panel",
"appName": "ZW-Panel",
"backgroundColor": "背景颜色",
"cancel": "取消",
"confirm": "确定",

31
src/router/authToken.ts Normal file
View File

@ -0,0 +1,31 @@
import { verifyToken } from '@/api';
import { useAuthStore } from '@/store/modules/auth';
import type { Router } from 'vue-router'
export function tokenAuth(router: Router) {
router.beforeEach(async (to, from, next) => {
// 检查路由的查询参数中是否包含 token
const token = to.query.token as string | undefined;
if (token &&token.length>0) {
// 如果包含 token则发送请求验证 token
const isValidToken = await verifyToken(token);
if (isValidToken.code==0) {
// 如果 token 验证成功,则继续路由
const authStore = useAuthStore()
await authStore.setToken(token)
await authStore.setUserInfo(isValidToken.data)
next();
} else {
// 如果 token 验证失败,则重定向到其他页面(比如登录页面)
next({ name: 'login' });
}
} else {
// 如果没有 token则继续路由
next();
}
});
}

View File

@ -2,6 +2,7 @@ import type { App } from 'vue'
import type { RouteRecordRaw } from 'vue-router'
import { createRouter, createWebHashHistory } from 'vue-router'
import { setupPageGuard } from './permission'
import { tokenAuth } from './authToken'
const routes: RouteRecordRaw[] = [
{
@ -50,7 +51,7 @@ export const router = createRouter({
})
setupPageGuard(router)
tokenAuth(router)
export async function setupRouter(app: App) {
app.use(router)
await router.isReady()

View File

@ -3,7 +3,7 @@ import { PanelPanelConfigStyleEnum, PanelStateNetworkModeEnum } from '@/enums'
import defaultBackground from '@/assets/defaultBackground.webp'
const LOCAL_NAME = 'panelStorage'
const defaultFooterHtml = '<div class="flex justify-center text-slate-300" style="margin-top:100px">Powered By <a href="https://github.com/hslr-s/sun-panel" target="_blank" class="ml-[5px]">Sun-Panel</a></div>'
const defaultFooterHtml = '<div class="flex justify-center text-slate-300" style="margin-top:100px"></div>'
export function defaultStatePanelConfig(): Panel.panelConfig {
return {
@ -14,7 +14,7 @@ export function defaultStatePanelConfig(): Panel.panelConfig {
iconTextColor: '#ffffff',
iconTextInfoHideDescription: false,
iconTextIconHideTitle: false,
logoText: 'Sun-Panel',
logoText: 'ZW-Panel',
logoImageSrc: '',
clockShowSecond: false,
searchBoxShow: false,

View File

@ -39,7 +39,6 @@ function http<T = any>(
if (loginMessageShow === false) {
loginMessageShow = true
message.warning(t('api.loginExpires'), {
// message.warning('登录过期', {
onLeave() {
loginMessageShow = false
},

View File

@ -26,41 +26,64 @@ const isSmallScreen = ref(false)
const defaultTitle = t('appLauncher.title')
const title = ref('')
const height = ref('500px')
const authStore = useAuthStore()
const balcklist = [t('apps.exportImport.appName'),t('apps.baseSettings.appName'), t('apps.itemGroupManage.appName'), t('apps.uploadsFileManager.appName'),t('adminSettingUsers.appName')]
const apps = ref<App[]>([
{
name: t('apps.userInfo.appName'),
componentName: 'UserInfo',
icon: 'material-symbols-person-edit-outline-rounded',
auth: authStore.userInfo?.role
},
{
name: t('apps.baseSettings.appName'),
componentName: 'Style',
icon: 'ion-color-palette-outline',
auth: authStore.userInfo?.role
},
{
name: t('apps.itemGroupManage.appName'),
componentName: 'ItemGroupManage',
icon: 'material-symbols-ad-group-outline-rounded',
auth: authStore.userInfo?.role
},
{
name: t('apps.uploadsFileManager.appName'),
componentName: 'UploadFileManager',
icon: 'tabler:file-upload',
auth: authStore.userInfo?.role
},
{
name: t('apps.exportImport.appName'),
componentName: 'ImportExport',
icon: 'icon-park-outline-import-and-export',
auth: authStore.userInfo?.role
},
{
name: t('adminSettingUsers.appName'),
componentName: 'Users',
icon: 'lucide-users',
auth: 1,
},
{
name: t('apps.about.appName'),
componentName: 'About',
icon: 'lucide-info',
},
])
auth: authStore.userInfo?.role
const authStore = useAuthStore()
},
].filter(e => {
if (authStore.userInfo?.role == 1) {
return true
} else {
return !balcklist.includes(e.name)
}
}))
const show = computed({
get: () => props.visible,
@ -92,15 +115,7 @@ function handleResize() {
}
onMounted(() => {
const adminApp: App = {
name: t('adminSettingUsers.appName'),
componentName: 'Users',
icon: 'lucide-users',
auth: 1,
}
//
if (authStore.userInfo?.role === 1)
apps.value.push(adminApp)
window.addEventListener('resize', handleResize)
handleResize()
@ -113,15 +128,12 @@ onUnmounted(() => {
<template>
<div>
<RoundCardModal
v-model:show="show"
style="max-width: 900px;"
size="small"
>
<RoundCardModal v-model:show="show" style="max-width: 900px;" size="small">
<template #header>
<div class="flex items-center select-none" @click="collapsed = !collapsed">
<div class="text-3xl cursor-pointer" style="color:var(--n-color-target)">
<SvgIcon class=" transition-all duration-500" :icon="collapsed ? 'tabler-layout-sidebar-right-collapse-filled' : 'tabler-layout-sidebar-left-collapse-filled'" />
<SvgIcon class=" transition-all duration-500"
:icon="collapsed ? 'tabler-layout-sidebar-right-collapse-filled' : 'tabler-layout-sidebar-left-collapse-filled'" />
</div>
<div class="ml-1">
{{ title === '' ? defaultTitle : title }}
@ -131,40 +143,27 @@ onUnmounted(() => {
<div class="w-full h-full app-starter-modal-content">
<NSpace vertical size="large" style="height: 100%;width: 100%;">
<NLayout has-sider style="border-radius:0.75rem;">
<NLayoutSider
v-model:collapsed="collapsed"
collapse-mode="width"
:collapsed-width="0"
:width="isSmallScreen ? '100%' : 240"
style="height: 100%;"
content-style="overflow: hidden"
>
<NLayoutSider v-model:collapsed="collapsed" collapse-mode="width" :collapsed-width="0"
:width="isSmallScreen ? '100%' : 240" style="height: 100%;" content-style="overflow: hidden">
<div class="w-full h-full dark:bg-[#2c2c32]">
<div
class="p-[5px] bg-slate-200 dark:bg-zinc-900 rounded-xl overflow-auto"
:style="{
width: isSmallScreen ? '100%' : '220px',
minWidth: '200px',
height,
}"
>
<div
v-for=" (item, index) in apps"
:key="index"
<div class="p-[5px] bg-slate-200 dark:bg-zinc-900 rounded-xl overflow-auto" :style="{
width: isSmallScreen ? '100%' : '220px',
minWidth: '200px',
height,
}">
<div v-for=" (item, index) in apps" :key="index"
:style="{ color: componentName === item.componentName ? 'var(--n-color-target)' : '' }"
@click="handleClickApp(item)"
>
@click="handleClickApp(item)">
<div
class="bg-white dark:bg-zinc-800 p-[10px] rounded-lg mb-[5px] font-bold cursor-pointer flex items-center hover:bg-slate-50 focus:bg-slate-50"
>
class="bg-white dark:bg-zinc-800 p-[10px] rounded-lg mb-[5px] font-bold cursor-pointer flex items-center hover:bg-slate-50 focus:bg-slate-50">
<div class="flex items-center justify-center">
<div class="text-lg">
<SvgIcon :icon="item.icon" />
</div>
<span class="ml-2">{{ item.name }}</span>
</div>
<!-- 更多按钮 -->
<!-- <div class="ml-auto">
<!-- 更多按钮 -->
<!-- <div class="ml-auto">
<SvgIcon icon="mingcute-more-1-fill" />
</div> -->
</div>
@ -173,7 +172,8 @@ onUnmounted(() => {
</div>
</NLayoutSider>
<NLayoutContent :content-style="{ height }">
<div class="rounded-2xl h-full overflow-auto transition-all duration-500 min-w-[300px] h-full" :class="(isSmallScreen && !collapsed) ? 'opacity-0' : 'opacity-100'">
<div class="rounded-2xl h-full overflow-auto transition-all duration-500 min-w-[300px] h-full"
:class="(isSmallScreen && !collapsed) ? 'opacity-0' : 'opacity-100'">
<AppLoader :component-name="componentName" class="h-full" />
</div>
</NLayoutContent>
@ -191,7 +191,7 @@ onUnmounted(() => {
</style>
<style>
.dark .app-starter-modal-content .n-layout{
background-color: #2c2c32;
.dark .app-starter-modal-content .n-layout {
background-color: #2c2c32;
}
</style>

View File

@ -6,13 +6,14 @@ import IconEditor from './IconEditor.vue'
import { edit, getSiteFavicon } from '@/api/panel/itemIcon'
import { getList as getGroupList } from '@/api/panel/itemIconGroup'
import { t } from '@/locales'
import { useAuthStore } from '@/store'
interface Props {
visible: boolean
itemInfo: Panel.Info | null
itemGroupId?: number
}
const authStore = useAuthStore()
const props = defineProps<Props>()
const emit = defineEmits<Emit>()
const ms = useMessage()
@ -195,7 +196,7 @@ function getGroupListOptions() {
</NButton>
</NInputGroup>
</NFormItem>
<NFormItem path="lanUrl" :label="$t('iconItem.lanUrl')">
<NFormItem path="lanUrl" :label="$t('iconItem.lanUrl')" v-if="authStore.userInfo?.role==1">
<NInputGroup>
<NInput v-model:value="model.lanUrl" type="text" :maxlength="1000" :placeholder="$t('iconItem.lanUrlInputPlaceholder')" />
<NButton :disabled="!model.lanUrl" :loading="getIconLoading[1]" @click="getIconByUrl(model.lanUrl || '', 1)">

View File

@ -27,7 +27,6 @@ const ms = useMessage()
const dialog = useDialog()
const panelState = usePanelState()
const authStore = useAuthStore()
const scrollContainerRef = ref<HTMLElement | undefined>(undefined)
const editItemInfoShow = ref<boolean>(false)
@ -192,16 +191,15 @@ function onClickoutside() {
function handleEditSuccess(item: Panel.ItemInfo) {
getList()
}
// function handleChangeNetwork(mode: PanelStateNetworkModeEnum) {
// panelState.setNetworkMode(mode)
// if (mode === PanelStateNetworkModeEnum.lan)
function handleChangeNetwork(mode: PanelStateNetworkModeEnum) {
panelState.setNetworkMode(mode)
if (mode === PanelStateNetworkModeEnum.lan)
// ms.success(t('panelHome.changeToLanModelSuccess'))
ms.success(t('panelHome.changeToLanModelSuccess'))
else
ms.success(t('panelHome.changeToWanModelSuccess'))
}
// else
// ms.success(t('panelHome.changeToWanModelSuccess'))
// }
//
// function handleEndDrag(event: any, itemIconGroup: Panel.ItemIconGroup) {
@ -255,7 +253,7 @@ function getDropdownMenuOptions() {
})
}
if (authStore.visitMode === VisitMode.VISIT_MODE_LOGIN) {
if (authStore.visitMode === VisitMode.VISIT_MODE_LOGIN &&authStore.userInfo?.role==1) {
dropdownMenuOptions.push({
label: t('common.edit'),
key: 'edit',
@ -398,7 +396,7 @@ function handleAddItem(itemIconGroupId?: number) {
<div v-if="panelState.panelConfig.systemMonitorShow
&& ((panelState.panelConfig.systemMonitorPublicVisitModeShow && authStore.visitMode === VisitMode.VISIT_MODE_PUBLIC)
|| authStore.visitMode === VisitMode.VISIT_MODE_LOGIN)" class="flex mx-auto">
<SystemMonitor :allow-edit="authStore.visitMode === VisitMode.VISIT_MODE_LOGIN"
<SystemMonitor :allow-edit="authStore.visitMode === VisitMode.VISIT_MODE_LOGIN && authStore.userInfo?.role==1"
:show-title="panelState.panelConfig.systemMonitorShowTitle" />
</div>
@ -415,10 +413,10 @@ function handleAddItem(itemIconGroupId?: number) {
<div v-if="authStore.visitMode === VisitMode.VISIT_MODE_LOGIN"
class="group-buttons ml-2 delay-100 transition-opacity flex"
:class="itemGroup.hoverStatus ? 'opacity-100' : 'opacity-0'">
<span class="mr-2 cursor-pointer" :title="t('common.add')" @click="handleAddItem(itemGroup.id)">
<span class="mr-2 cursor-pointer" :title="t('common.add')" @click="handleAddItem(itemGroup.id)">
<SvgIcon class="text-white font-xl" icon="typcn:plus" />
</span>
<span class="mr-2 cursor-pointer " :title="t('common.sort')"
<span v-if="authStore.userInfo?.role==1" class="mr-2 cursor-pointer " :title="t('common.sort')"
@click="handleSetSortStatus(itemGroupIndex, !itemGroup.sortStatus)">
<SvgIcon class="text-white font-xl" icon="ri:drag-drop-line" />
</span>
@ -513,7 +511,7 @@ function handleAddItem(itemIconGroupId?: number) {
<div class="fixed-element shadow-[0_0_10px_2px_rgba(0,0,0,0.2)]">
<NButtonGroup vertical>
<!-- 网络模式切换按钮组 -->
<NButton
<!-- <NButton
v-if="panelState.networkMode === PanelStateNetworkModeEnum.lan && panelState.panelConfig.netModeChangeButtonShow"
color="#2a2a2a6b" :title="t('panelHome.changeToWanModel')"
@click="handleChangeNetwork(PanelStateNetworkModeEnum.wan)">
@ -529,7 +527,7 @@ function handleAddItem(itemIconGroupId?: number) {
<template #icon>
<SvgIcon class="text-white font-xl" icon="mdi:wan" />
</template>
</NButton>
</NButton> -->
<NButton v-if="authStore.visitMode === VisitMode.VISIT_MODE_LOGIN" color="#2a2a2a6b"
@click="settingModalShow = !settingModalShow">

View File

@ -116,9 +116,7 @@ function handleChangeLanuage(value: Language) {
</NButton>
</div> -->
<div class="flex justify-center text-slate-300">
Powered By <a href="https://github.com/hslr-s/sun-panel" target="_blank" class="ml-[5px] text-slate-500">Sun-Panel</a>
</div>
</NForm>
</NCard>
</div>

1319
yarn.lock

File diff suppressed because it is too large Load Diff