Merge branch 'dev'
This commit is contained in:
commit
31fd128633
1
.gitignore
vendored
1
.gitignore
vendored
@ -41,3 +41,4 @@ service/lang
|
||||
service/database
|
||||
service/web
|
||||
service/uploads
|
||||
service/plugins
|
@ -4,7 +4,9 @@ const moment = require('moment')
|
||||
|
||||
// git 最新标签
|
||||
// const latestTag = execSync('git describe --tags --abbrev=0').toString().trim()
|
||||
const packDate = moment().format('YYYYMMDD-HH')
|
||||
|
||||
// 设置默认时区为 'Asia/Shanghai'
|
||||
const packDate = moment().utc().format('YYYYMMDD')
|
||||
|
||||
// 要追加的内容
|
||||
const contentToAppend = `\nVITE_APP_VERSION=${packDate}`
|
||||
|
@ -2,13 +2,20 @@ package panel
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"sun-panel/api/api_v1/common/apiData/commonApiStructs"
|
||||
"sun-panel/api/api_v1/common/apiData/panelApiStructs"
|
||||
"sun-panel/api/api_v1/common/apiReturn"
|
||||
"sun-panel/api/api_v1/common/base"
|
||||
"sun-panel/global"
|
||||
"sun-panel/lib/cmn"
|
||||
"sun-panel/lib/siteFavicon"
|
||||
"sun-panel/models"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
@ -188,7 +195,9 @@ func (a *ItemIcon) SaveSort(c *gin.Context) {
|
||||
apiReturn.Success(c)
|
||||
}
|
||||
|
||||
// 支持获取并直接下载对方网站图标到服务器
|
||||
func (a *ItemIcon) GetSiteFavicon(c *gin.Context) {
|
||||
userInfo, _ := base.GetCurrentUserInfo(c)
|
||||
req := panelApiStructs.ItemIconGetSiteFaviconReq{}
|
||||
|
||||
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
|
||||
@ -196,10 +205,68 @@ func (a *ItemIcon) GetSiteFavicon(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
resp := panelApiStructs.ItemIconGetSiteFaviconResp{}
|
||||
if iconUrl, ok := siteFavicon.GetOneFaviconURL(req.Url); ok {
|
||||
resp.IconUrl = iconUrl
|
||||
apiReturn.SuccessData(c, resp)
|
||||
fullUrl := ""
|
||||
if iconUrl, err := siteFavicon.GetOneFaviconURL(req.Url); err != nil {
|
||||
apiReturn.Error(c, "acquisition failed: get ico error:"+err.Error())
|
||||
return
|
||||
} else {
|
||||
fullUrl = iconUrl
|
||||
}
|
||||
|
||||
parsedURL, err := url.Parse(req.Url)
|
||||
if err != nil {
|
||||
apiReturn.Error(c, "acquisition failed:"+err.Error())
|
||||
return
|
||||
}
|
||||
apiReturn.Error(c, "acquisition failed")
|
||||
|
||||
protocol := parsedURL.Scheme
|
||||
global.Logger.Debug("protocol:", protocol)
|
||||
global.Logger.Debug("fullUrl:", fullUrl)
|
||||
|
||||
// 如果URL以双斜杠(//)开头,则使用当前页面协议
|
||||
if strings.HasPrefix(fullUrl, "//") {
|
||||
fullUrl = protocol + "://" + fullUrl[2:]
|
||||
} else if !strings.HasPrefix(fullUrl, "http://") && !strings.HasPrefix(fullUrl, "https://") {
|
||||
// 如果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)
|
||||
|
||||
// 生成保存目录
|
||||
configUpload := global.Config.GetValueString("base", "source_path")
|
||||
savePath := fmt.Sprintf("%s/%d/%d/%d/", configUpload, time.Now().Year(), time.Now().Month(), time.Now().Day())
|
||||
isExist, _ := cmn.PathExists(savePath)
|
||||
if !isExist {
|
||||
os.MkdirAll(savePath, os.ModePerm)
|
||||
}
|
||||
|
||||
// 下载
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 保存到数据库
|
||||
ext := path.Ext(fullUrl)
|
||||
mFile := models.File{}
|
||||
if _, err := mFile.AddFile(userInfo.ID, parsedURL.Host, ext, imgInfo.Name()); err != nil {
|
||||
apiReturn.ErrorDatabase(c, err.Error())
|
||||
return
|
||||
}
|
||||
resp.IconUrl = imgInfo.Name()[1:]
|
||||
apiReturn.SuccessData(c, resp)
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
9|1.3.0-beta24-01-25
|
||||
10|1.3.0
|
@ -2,11 +2,17 @@ package siteFavicon
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sun-panel/lib/cmn"
|
||||
"time"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
)
|
||||
@ -20,7 +26,91 @@ func IsHTTPURL(url string) bool {
|
||||
return match
|
||||
}
|
||||
|
||||
func GetOneFaviconURL(urlStr string) (string, bool) {
|
||||
func GetOneFaviconURL(urlStr string) (string, error) {
|
||||
iconURLs, err := getFaviconURL(urlStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, v := range iconURLs {
|
||||
// 标准的路径地址
|
||||
if IsHTTPURL(v) {
|
||||
return v, nil
|
||||
} else {
|
||||
urlInfo, _ := url.Parse(urlStr)
|
||||
fullUrl := urlInfo.Scheme + "://" + urlInfo.Host + "/" + strings.TrimPrefix(v, "/")
|
||||
return fullUrl, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("not found ico")
|
||||
}
|
||||
|
||||
// 获取远程文件的大小
|
||||
func GetRemoteFileSize(url string) (int64, error) {
|
||||
resp, err := http.Head(url)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 检查HTTP响应状态
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return 0, fmt.Errorf("HTTP request failed, status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// 获取Content-Length字段,即文件大小
|
||||
size := resp.ContentLength
|
||||
return size, nil
|
||||
}
|
||||
|
||||
// 下载图片
|
||||
func DownloadImage(url, savePath string, maxSize int64) (*os.File, error) {
|
||||
// 获取远程文件大小
|
||||
fileSize, err := GetRemoteFileSize(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 判断文件大小是否在阈值内
|
||||
if fileSize > maxSize {
|
||||
return nil, fmt.Errorf("文件太大,不下载。大小:%d字节", fileSize)
|
||||
}
|
||||
|
||||
// 发送HTTP GET请求获取图片数据
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
// 检查HTTP响应状态
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("HTTP request failed, status code: %d", response.StatusCode)
|
||||
}
|
||||
|
||||
urlFileName := path.Base(url)
|
||||
fileExt := path.Ext(url)
|
||||
fileName := cmn.Md5(fmt.Sprintf("%s%s", urlFileName, time.Now().String())) + fileExt
|
||||
|
||||
destination := savePath + "/" + fileName
|
||||
|
||||
// 创建本地文件用于保存图片
|
||||
file, err := os.Create(destination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 将图片数据写入本地文件
|
||||
_, err = io.Copy(file, response.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func GetOneFaviconURLAndUpload(urlStr string) (string, bool) {
|
||||
//www.iqiyipic.com/pcwimg/128-128-logo.png
|
||||
iconURLs, err := getFaviconURL(urlStr)
|
||||
if err != nil {
|
||||
return "", false
|
||||
|
@ -574,7 +574,11 @@ function handleAddItem(itemIconGroupId?: number) {
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-full h-full rounded-2xl overflow-hidden border dark:border-zinc-700">
|
||||
<NSkeleton v-if="windowIframeIsLoad" height="100%" width="100%" />
|
||||
<div v-if="windowIframeIsLoad" class="flex flex-col p-5">
|
||||
<NSkeleton height="50px" width="100%" class="rounded-lg" />
|
||||
<NSkeleton height="180px" width="100%" class="mt-[20px] rounded-lg" />
|
||||
<NSkeleton height="180px" width="100%" class="mt-[20px] rounded-lg" />
|
||||
</div>
|
||||
<iframe
|
||||
v-show="!windowIframeIsLoad" id="windowIframeId" ref="windowIframeRef" :src="windowSrc"
|
||||
class="w-full h-full" frameborder="0" @load="handWindowIframeIdLoad"
|
||||
|
Loading…
x
Reference in New Issue
Block a user