marge: 合并代码
This commit is contained in:
@@ -94,6 +94,7 @@ cors:
|
||||
- "X-Requested-With"
|
||||
- "Content-Type"
|
||||
- "Content-Language"
|
||||
- "Accept-Language"
|
||||
- "Accept"
|
||||
- "Range"
|
||||
- "Accesstoken"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# 应用服务配置
|
||||
server:
|
||||
port: 3040
|
||||
proxy: true
|
||||
|
||||
# 日志
|
||||
logger:
|
||||
|
||||
@@ -16,11 +16,11 @@ func ErrorCatch() gin.HandlerFunc {
|
||||
defer func() {
|
||||
// 在这里处理 Panic 异常,例如记录日志或返回错误信息给客户端
|
||||
if err := recover(); err != nil {
|
||||
logger.Errorf("Panic 异常: %s => %v", c.Request.URL, err)
|
||||
logger.Errorf("Panic Error: %s => %v", c.Request.URL, err)
|
||||
|
||||
// 返回错误响应给客户端
|
||||
if config.Env() == "prod" {
|
||||
c.JSON(500, result.ErrMsg("服务器内部错误"))
|
||||
c.JSON(500, result.ErrMsg("Internal Server Errors"))
|
||||
} else {
|
||||
// 通过实现 error 接口的 Error() 方法自定义错误类型进行捕获
|
||||
switch v := err.(type) {
|
||||
|
||||
73
src/framework/i18n/i18n.go
Normal file
73
src/framework/i18n/i18n.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
systemService "ems.agt/src/modules/system/service"
|
||||
)
|
||||
|
||||
// localeItem 国际化数据项
|
||||
type localeItem struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// localeMap 国际化数据组
|
||||
var localeMap = make(map[string][]localeItem)
|
||||
|
||||
// ClearLocaleData 清空国际化数据
|
||||
func ClearLocaleData() {
|
||||
localeMap = make(map[string][]localeItem)
|
||||
}
|
||||
|
||||
// LoadLocaleData 加载国际化数据
|
||||
func LoadLocaleData(language string) []localeItem {
|
||||
dictType := fmt.Sprintf("i18n_%s", language)
|
||||
dictTypeList := systemService.NewSysDictTypeImpl.DictDataCache(dictType)
|
||||
localeData := []localeItem{}
|
||||
for _, v := range dictTypeList {
|
||||
localeData = append(localeData, localeItem{
|
||||
Key: v.DictLabel,
|
||||
Value: v.DictValue,
|
||||
})
|
||||
}
|
||||
localeMap[language] = localeData
|
||||
return localeData
|
||||
}
|
||||
|
||||
// TKey 翻译键
|
||||
func TKey(language, key string) string {
|
||||
value := key
|
||||
if key == "" {
|
||||
return value
|
||||
}
|
||||
arr, ok := localeMap[language]
|
||||
if !ok || len(arr) == 0 {
|
||||
arr = LoadLocaleData(language)
|
||||
}
|
||||
|
||||
for _, v := range arr {
|
||||
if v.Key == key {
|
||||
value = v.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// TTemplate 翻译模板字符串
|
||||
func TTemplate(language, key string, params map[string]any) string {
|
||||
templateString := TKey(language, key)
|
||||
|
||||
re := regexp.MustCompile("{(.*?)}")
|
||||
result := re.ReplaceAllStringFunc(templateString, func(match string) string {
|
||||
key := match[1 : len(match)-1]
|
||||
if val, ok := params[key]; ok {
|
||||
return fmt.Sprint(val)
|
||||
}
|
||||
return match
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -90,7 +90,8 @@ func RateLimit(option LimitOption) gin.HandlerFunc {
|
||||
c.Header("X-RateLimit-Reset", fmt.Sprintf("%d", time.Now().Unix()+int64(rateTime))) // 重置时间戳
|
||||
|
||||
if rateCount >= option.Count {
|
||||
c.JSON(200, result.ErrMsg("访问过于频繁,请稍候再试"))
|
||||
// 访问过于频繁,请稍候再试
|
||||
c.JSON(200, result.ErrMsg("Visits are too frequent. Please try again later"))
|
||||
c.Abort() // 停止执行后续的处理函数
|
||||
return
|
||||
}
|
||||
|
||||
@@ -60,7 +60,8 @@ func RepeatSubmit(interval int64) gin.HandlerFunc {
|
||||
|
||||
// 小于间隔时间且参数内容一致
|
||||
if compareTime < interval && compareParams {
|
||||
c.JSON(200, result.ErrMsg("不允许重复提交,请稍候再试"))
|
||||
// 不允许重复提交,请稍候再试
|
||||
c.JSON(200, result.ErrMsg("Duplicate submissions are not allowed. Please try again later"))
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -42,14 +42,16 @@ func referer(c *gin.Context) {
|
||||
|
||||
referer := c.GetHeader("Referer")
|
||||
if referer == "" {
|
||||
c.AbortWithStatusJSON(200, result.ErrMsg("无效 Referer 未知"))
|
||||
// 无效 Referer 未知
|
||||
c.AbortWithStatusJSON(200, result.ErrMsg("Invalid referer unknown"))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取host
|
||||
u, err := url.Parse(referer)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(200, result.ErrMsg("无效 Referer 未知"))
|
||||
// 无效 Referer 未知
|
||||
c.AbortWithStatusJSON(200, result.ErrMsg("Invalid referer unknown"))
|
||||
return
|
||||
}
|
||||
host := u.Host
|
||||
@@ -70,7 +72,8 @@ func referer(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
c.AbortWithStatusJSON(200, result.ErrMsg("无效 Referer "+host))
|
||||
// 无效 Referer
|
||||
c.AbortWithStatusJSON(200, result.ErrMsg("Invalid referer "+host))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"ems.agt/src/framework/utils/ip2region"
|
||||
"ems.agt/src/framework/utils/ua"
|
||||
"ems.agt/src/framework/vo"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
@@ -81,13 +82,13 @@ func UaOsBrowser(c *gin.Context) (string, string) {
|
||||
userAgent := c.GetHeader("user-agent")
|
||||
uaInfo := ua.Info(userAgent)
|
||||
|
||||
browser := "未知 未知"
|
||||
browser := "Unknown Unknown"
|
||||
bName, bVersion := uaInfo.Browser()
|
||||
if bName != "" && bVersion != "" {
|
||||
browser = bName + " " + bVersion
|
||||
}
|
||||
|
||||
os := "未知 未知"
|
||||
os := "Unknown Unknown"
|
||||
bos := uaInfo.OS()
|
||||
if bos != "" {
|
||||
os = bos
|
||||
@@ -95,13 +96,27 @@ func UaOsBrowser(c *gin.Context) (string, string) {
|
||||
return os, browser
|
||||
}
|
||||
|
||||
// AcceptLanguage 解析客户端接收语言 zh:中文 en: 英文
|
||||
func AcceptLanguage(c *gin.Context) string {
|
||||
preferredLanguage := language.English
|
||||
acceptLanguage := c.GetHeader("Accept-Language")
|
||||
tags, _, _ := language.ParseAcceptLanguage(acceptLanguage)
|
||||
if len(tags) > 0 {
|
||||
preferredLanguage = tags[0]
|
||||
}
|
||||
// 只取前缀
|
||||
lang := preferredLanguage.String()
|
||||
arr := strings.Split(lang, "-")
|
||||
return arr[0]
|
||||
}
|
||||
|
||||
// LoginUser 登录用户信息
|
||||
func LoginUser(c *gin.Context) (vo.LoginUser, error) {
|
||||
value, exists := c.Get(common.CTX_LOGIN_USER)
|
||||
if exists {
|
||||
return value.(vo.LoginUser), nil
|
||||
}
|
||||
return vo.LoginUser{}, fmt.Errorf("无效登录用户信息")
|
||||
return vo.LoginUser{}, fmt.Errorf("invalid login user information")
|
||||
}
|
||||
|
||||
// LoginUserToUserID 登录用户信息-用户ID
|
||||
|
||||
@@ -22,7 +22,7 @@ func WriterCSVFile(data [][]string, filePath string) error {
|
||||
// 确保文件夹路径存在
|
||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
||||
if err != nil {
|
||||
logger.Errorf("创建文件夹失败 CreateFile %v", err)
|
||||
logger.Errorf("MkdirAll dir %v", err)
|
||||
}
|
||||
|
||||
// 创建或打开文件
|
||||
@@ -51,7 +51,7 @@ func ReadCSVFile(filePath string) []map[string]string {
|
||||
// 打开 CSV 文件
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
logger.Errorf("无法打开 CSV 文件:%v", err)
|
||||
logger.Errorf("Open CSV file: %v", err)
|
||||
return arr
|
||||
}
|
||||
defer file.Close()
|
||||
@@ -62,7 +62,7 @@ func ReadCSVFile(filePath string) []map[string]string {
|
||||
// 读取 CSV 头部行
|
||||
header, err := reader.Read()
|
||||
if err != nil {
|
||||
logger.Errorf("无法读取 CSV 头部行:%v", err)
|
||||
logger.Errorf("Read CSV header rows: %v", err)
|
||||
return arr
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ func ReadSheet(filePath, sheetName string) ([]map[string]string, error) {
|
||||
}
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
logger.Errorf("工作表文件关闭失败 : %v", err)
|
||||
logger.Errorf("ReadSheet to close worksheet file : %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -60,7 +60,7 @@ func ReadSheet(filePath, sheetName string) ([]map[string]string, error) {
|
||||
sheetName = "Sheet1"
|
||||
}
|
||||
if visible, _ := f.GetSheetVisible(sheetName); !visible {
|
||||
return data, fmt.Errorf("读取工作簿 %s 失败", sheetName)
|
||||
return data, fmt.Errorf("failed to read workbook %s", sheetName)
|
||||
}
|
||||
|
||||
// 获取工作簿记录
|
||||
@@ -99,7 +99,7 @@ func WriteSheet(headerCells map[string]string, dataCells []map[string]any, fileN
|
||||
f := excelize.NewFile()
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
logger.Errorf("工作表文件关闭失败 : %v", err)
|
||||
logger.Errorf("WriteSheet to close worksheet file: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -109,7 +109,7 @@ func WriteSheet(headerCells map[string]string, dataCells []map[string]any, fileN
|
||||
}
|
||||
index, err := f.NewSheet(sheetName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("创建工作表失败 %v", err)
|
||||
return "", fmt.Errorf("failed to create worksheet %v", err)
|
||||
}
|
||||
// 设置工作簿的默认工作表
|
||||
f.SetActiveSheet(index)
|
||||
@@ -143,12 +143,12 @@ func WriteSheet(headerCells map[string]string, dataCells []map[string]any, fileN
|
||||
|
||||
// 创建文件目录
|
||||
if err := os.MkdirAll(filepath.Dir(saveFilePath), 0750); err != nil {
|
||||
return "", fmt.Errorf("创建保存文件失败 %v", err)
|
||||
return "", fmt.Errorf("failed to create save file %v", err)
|
||||
}
|
||||
|
||||
// 根据指定路径保存文件
|
||||
if err := f.SaveAs(saveFilePath); err != nil {
|
||||
return "", fmt.Errorf("保存工作表失败 %v", err)
|
||||
return "", fmt.Errorf("failed to save worksheet %v", err)
|
||||
}
|
||||
return saveFilePath, nil
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"path"
|
||||
@@ -74,13 +73,13 @@ func generateFileName(fileName string) string {
|
||||
func isAllowWrite(fileName string, allowExts []string, fileSize int64) error {
|
||||
// 判断上传文件名称长度
|
||||
if len(fileName) > DEFAULT_FILE_NAME_LENGTH {
|
||||
return fmt.Errorf("上传文件名称长度限制最长为 %d", DEFAULT_FILE_NAME_LENGTH)
|
||||
return fmt.Errorf("the maximum length limit for uploading file names is %d", DEFAULT_FILE_NAME_LENGTH)
|
||||
}
|
||||
|
||||
// 最大上传文件大小
|
||||
maxFileSize := uploadFileSize()
|
||||
if fileSize > maxFileSize {
|
||||
return fmt.Errorf("最大上传文件大小 %s", parse.Bit(float64(maxFileSize)))
|
||||
return fmt.Errorf("maximum upload file size %s", parse.Bit(float64(maxFileSize)))
|
||||
}
|
||||
|
||||
// 判断文件拓展是否为允许的拓展类型
|
||||
@@ -96,7 +95,7 @@ func isAllowWrite(fileName string, allowExts []string, fileSize int64) error {
|
||||
}
|
||||
}
|
||||
if !hasExt {
|
||||
return fmt.Errorf("上传文件类型不支持,仅支持以下类型:%s", strings.Join(allowExts, "、"))
|
||||
return fmt.Errorf("the upload file type is not supported, only the following types are supported: %s", strings.Join(allowExts, ","))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -108,7 +107,7 @@ func isAllowWrite(fileName string, allowExts []string, fileSize int64) error {
|
||||
func isAllowRead(filePath string) error {
|
||||
// 禁止目录上跳级别
|
||||
if strings.Contains(filePath, "..") {
|
||||
return fmt.Errorf("禁止目录上跳级别")
|
||||
return fmt.Errorf("prohibit jumping levels on the directory")
|
||||
}
|
||||
|
||||
// 检查允许下载的文件规则
|
||||
@@ -121,7 +120,7 @@ func isAllowRead(filePath string) error {
|
||||
}
|
||||
}
|
||||
if !hasExt {
|
||||
return fmt.Errorf("非法下载的文件规则:%s", fileExt)
|
||||
return fmt.Errorf("rules for illegally downloaded files: %s", fileExt)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -203,7 +202,7 @@ func ReadUploadFileStream(filePath, headerRange string) (map[string]any, error)
|
||||
result["chunkSize"] = end - start + 1
|
||||
byteArr, err := getFileStream(fileAsbPath, start, end)
|
||||
if err != nil {
|
||||
return map[string]any{}, errors.New("读取文件失败")
|
||||
return map[string]any{}, fmt.Errorf("fail to read file")
|
||||
}
|
||||
result["data"] = byteArr
|
||||
return result, nil
|
||||
@@ -211,7 +210,7 @@ func ReadUploadFileStream(filePath, headerRange string) (map[string]any, error)
|
||||
|
||||
byteArr, err := getFileStream(fileAsbPath, 0, fileSize)
|
||||
if err != nil {
|
||||
return map[string]any{}, errors.New("读取文件失败")
|
||||
return map[string]any{}, fmt.Errorf("fail to read file")
|
||||
}
|
||||
result["data"] = byteArr
|
||||
return result, nil
|
||||
@@ -261,7 +260,7 @@ func ChunkCheckFile(identifier, originalFileName string) ([]string, error) {
|
||||
readPath := path.Join(dir, dirPath)
|
||||
fileList, err := getDirFileNameList(readPath)
|
||||
if err != nil {
|
||||
return []string{}, errors.New("读取文件失败")
|
||||
return []string{}, fmt.Errorf("fail to read file")
|
||||
}
|
||||
return fileList, nil
|
||||
}
|
||||
|
||||
@@ -51,10 +51,10 @@ func mergeToNewFile(dirPath string, writePath string, fileName string) error {
|
||||
// 读取目录下所有文件并排序,注意文件名称是否数值
|
||||
fileNameList, err := getDirFileNameList(dirPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("读取合并目标文件失败: %v", err)
|
||||
return fmt.Errorf("failed to read merge target file: %v", err)
|
||||
}
|
||||
if len(fileNameList) <= 0 {
|
||||
return fmt.Errorf("读取合并目标文件失败")
|
||||
return fmt.Errorf("failed to read merge target file")
|
||||
}
|
||||
|
||||
// 排序
|
||||
|
||||
@@ -42,7 +42,8 @@ func init() {
|
||||
func RegionSearchByIp(ip string) (string, int, int64) {
|
||||
ip = ClientIP(ip)
|
||||
if ip == LOCAT_HOST {
|
||||
return "0|0|0|内网IP|内网IP", 0, 0
|
||||
// "0|0|0|内网IP|内网IP"
|
||||
return "0|0|0|Intranet IP|Intranet IP", 0, 0
|
||||
}
|
||||
tStart := time.Now()
|
||||
region, err := searcher.SearchByStr(ip)
|
||||
@@ -59,17 +60,20 @@ func RegionSearchByIp(ip string) (string, int, int64) {
|
||||
func RealAddressByIp(ip string) string {
|
||||
ip = ClientIP(ip)
|
||||
if ip == LOCAT_HOST {
|
||||
return "内网IP"
|
||||
return "Intranet IP" // 内网IP
|
||||
}
|
||||
region, err := searcher.SearchByStr(ip)
|
||||
if err != nil {
|
||||
logger.Errorf("failed to SearchIP(%s): %s\n", ip, err)
|
||||
return "未知"
|
||||
return "unknown" // 未知
|
||||
}
|
||||
parts := strings.Split(region, "|")
|
||||
province := parts[2]
|
||||
city := parts[3]
|
||||
if province == "0" && city != "0" {
|
||||
if city == "内网IP" {
|
||||
return "Intranet IP" // 内网IP
|
||||
}
|
||||
return city
|
||||
}
|
||||
return province + " " + city
|
||||
|
||||
@@ -32,7 +32,7 @@ func FileSCPNeToLocal(neIp, nePath, localPath string) error {
|
||||
// 确保文件夹路径存在
|
||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
||||
if err != nil {
|
||||
log.Errorf("创建文件夹失败 CreateFile %v", err)
|
||||
log.Errorf("FileSCPNeToLocal MkdirAll err %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package token
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"ems.agt/src/framework/config"
|
||||
@@ -124,13 +124,14 @@ func Verify(tokenString string) (jwt.MapClaims, error) {
|
||||
})
|
||||
if err != nil {
|
||||
logger.Errorf("token String Verify : %v", err)
|
||||
return nil, errors.New("无效身份授权")
|
||||
// 无效身份授权
|
||||
return nil, fmt.Errorf("invalid identity authorization")
|
||||
}
|
||||
// 如果解析负荷成功并通过签名校验
|
||||
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
return nil, errors.New("token valid error")
|
||||
return nil, fmt.Errorf("token valid error")
|
||||
}
|
||||
|
||||
// LoginUser 缓存的登录用户信息
|
||||
|
||||
Reference in New Issue
Block a user