初始化项目文件

This commit is contained in:
2025-07-11 16:54:11 +08:00
parent 6bffd582a0
commit 39fedaac16
213 changed files with 16944 additions and 0 deletions

70
api_iris/utils/aes.go Normal file
View File

@ -0,0 +1,70 @@
package utils
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"errors"
)
func pkcs7Padding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padText...)
}
func pkcs7UnPadding(data []byte) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, errors.New("加密字符串为空!")
}
unPadding := int(data[length-1])
return data[:(length - unPadding)], nil
}
func aesEncrypt(data []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
encryptBytes := pkcs7Padding(data, blockSize)
encrypted := make([]byte, len(encryptBytes))
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
blockMode.CryptBlocks(encrypted, encryptBytes)
return encrypted, nil
}
func aesDecrypt(data []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
decrypted := make([]byte, len(data))
blockMode.CryptBlocks(decrypted, data)
//fmt.Println(data, decrypted)
decrypted, err = pkcs7UnPadding(decrypted)
if err != nil {
return nil, err
}
return decrypted, err
}
func EncryptByAes(data []byte, key []byte) (string, error) {
res, err := aesEncrypt(data, key)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(res), nil
}
func DecryptByAes(data string, key []byte) ([]byte, error) {
dataByte, err := base64.StdEncoding.DecodeString(data)
if err != nil {
return nil, err
}
return aesDecrypt(dataByte, key)
}

View File

@ -0,0 +1,55 @@
package utils
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
)
var holidays []ResHolidays
func CheckHoliday(date string) (bool, string) {
year, err := strconv.Atoi(date[:4])
if len(holidays) == 0 {
err = getHolidays(year)
if err != nil {
return false, ""
}
}
for _, holiday := range holidays {
if date == holiday.Date {
return true, holiday.HolidayNameCn
}
}
return false, ""
}
func getHolidays(year int) error {
var res map[string]resHolidaysApi
//var holidays []ResHolidays
data, err := http.Get(fmt.Sprintf("https://api.jiejiariapi.com/v1/holidays/%s", strconv.Itoa(year)))
if err != nil {
return err
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
return
}
}(data.Body)
body, _ := io.ReadAll(data.Body)
//解析json结构
err = json.Unmarshal(body, &res)
if err != nil {
return err
}
for _, j := range res {
holidays = append(holidays, ResHolidays{
Date: j.Date,
HolidayNameCn: j.Name,
})
}
return nil
}

43
api_iris/utils/menus.go Normal file
View File

@ -0,0 +1,43 @@
package utils
import (
"github.com/sirupsen/logrus"
"main/database"
"main/model"
)
var MenuList []model.Menus
func UpdateMenuList() {
db := database.GetInstance().GetMysqlDb()
if err := db.Order("menu_id").Find(&MenuList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
logrus.Infoln("更新暂存MenuList列表")
if len(MenuList) == 0 {
logrus.Warningln("数据库MenuList为空添加初始数据")
if err := db.Create(&model.Menus{
MenuId: "999",
Name: "系统管理",
Icon: "bi-gear",
Path: "",
UserType: "admin",
WhiteList: "",
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if err := db.Create(&model.Menus{
MenuId: "99901",
Name: "菜单管理",
Icon: "bi-list",
Path: "/admin/menus",
UserType: "admin",
WhiteList: "",
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if err := db.Order("menu_id").Find(&MenuList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
}
}

127
api_iris/utils/rsa.go Normal file
View File

@ -0,0 +1,127 @@
package utils
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
"reflect"
"time"
)
func GetPrivateKeys(user string, date string) (model.DayKeys, error) {
var resKey model.DayKeys
//today := time.Now().Format("2006-01-02")
db := database.GetInstance().GetMysqlDb()
if err := db.Where("date = ? and user = ?", date, user).Order("id").First(&resKey).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if reflect.DeepEqual(resKey, model.DayKeys{}) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return model.DayKeys{}, err
}
x509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)
base64PrivateKey := base64.StdEncoding.EncodeToString(x509PrivateKey)
resKey = model.DayKeys{
Date: date,
Key: base64PrivateKey,
AesKey: NewKey(32),
User: user,
}
if err1 := db.Create(&resKey).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1)
}
logrus.Warnln(date + "resKey为空创建resKey")
return resKey, nil
} else {
if err := db.Where("date = ? and user = ? and id <> ?", date, user, resKey.ID).Delete(&model.DayKeys{}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
}
logrus.Infoln("resKey存在返回私钥")
return resKey, nil
}
func GetPublicKey(user string) (string, error) {
var userLogin model.User
db := database.GetInstance().GetMysqlDb()
if err := db.Where("username = ?", user).First(&userLogin).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if userLogin.Date == "" {
logrus.Infoln(user + ":用户之前未登录系统")
userLogin.Date = time.Now().Format("2006-01-02")
}
sPrivateKey, err := GetPrivateKeys(user, userLogin.Date)
if err != nil {
return "", err
}
deBase64privateKey, err := base64.StdEncoding.DecodeString(sPrivateKey.Key)
if err != nil {
return "", err
}
privateKey, err := x509.ParsePKCS1PrivateKey(deBase64privateKey)
if err != nil {
return "", err
}
publicKey := privateKey.PublicKey
x509PublicKey, err := x509.MarshalPKIXPublicKey(&publicKey)
if err != nil {
return "", err
}
base64PublicKey := base64.StdEncoding.EncodeToString(x509PublicKey)
logrus.Infoln(user + ":获取公钥成功")
return base64PublicKey, nil
}
func RsaEncrypt(s string, user string) (string, error) {
sPublicKey, err := GetPublicKey(user)
if err != nil {
return "", err
}
deBase64Public, err := base64.StdEncoding.DecodeString(sPublicKey)
if err != nil {
return "", err
}
publicKey, err := x509.ParsePKIXPublicKey(deBase64Public)
if err != nil {
return "", err
}
res, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey.(*rsa.PublicKey), []byte(s))
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(res), nil
}
func RsaDecrypt(s string, sPrivateKey string) (string, error) {
//sPrivateKey, err := GetPrivateKeys(user)
//if err != nil {
// return "", err
//}
deBase64Private, err := base64.StdEncoding.DecodeString(sPrivateKey)
if err != nil {
logrus.Errorln("rsa私钥: base64 decode err:", err)
return "", err
}
privateKey, err := x509.ParsePKCS1PrivateKey(deBase64Private)
if err != nil {
logrus.Errorln("rsa私钥: x509 decode err:", err)
return "", err
}
des, err := base64.StdEncoding.DecodeString(s)
if err != nil {
logrus.Errorln("rsa: base64 decode err:", err)
return "", err
}
res, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, des)
if err != nil {
logrus.Errorln("rsa: 解密失败:", err)
return "", err
}
return string(res), nil
}

34
api_iris/utils/sudoku.go Normal file
View File

@ -0,0 +1,34 @@
package utils
import (
"encoding/json"
"fmt"
"github.com/sirupsen/logrus"
"io"
"net/http"
"net/url"
)
func CheckSudoku(sudoku string) (error, ResSudoku) {
resp, err := http.Get(fmt.Sprintf("https://git-ylsa0.cn/api_ylsa/get_sudoku_check/?sudoku=%s", url.QueryEscape(sudoku)))
if err != nil {
logrus.Errorln("请求get_sudoku_check接口失败", err)
return err, ResSudoku{}
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
logrus.Errorln(err.Error())
}
}(resp.Body)
body, _ := io.ReadAll(resp.Body)
var r ResSudoku
//解析json结构
err = json.Unmarshal(body, &r)
if err != nil {
logrus.Errorln("请求结果json解析失败", err)
return err, ResSudoku{}
}
logrus.Infoln("数独检查完成")
return nil, r
}

View File

@ -0,0 +1,38 @@
package utils
import (
"github.com/sirupsen/logrus"
"main/database"
"main/model"
)
var SysSettings []model.SysSettings
func UpdateSysSettings() {
db := database.GetInstance().GetMysqlDb()
if err := db.Order("name").Find(&SysSettings).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if len(SysSettings) == 0 {
if err := db.Create(&model.SysSettings{
Name: "user_type",
CnName: "系统管理员",
Value: "admin",
DType: "",
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if err := db.Create(&model.SysSettings{
Name: "user_type",
CnName: "系统用户",
Value: "user",
DType: "",
}).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if err := db.Order("name").Find(&SysSettings).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
}
logrus.Infoln("更新系统配置列表")
}

45
api_iris/utils/type.d.go Normal file
View File

@ -0,0 +1,45 @@
package utils
// ResponseBean result结构
type ResponseBean struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
type ResApiUtils struct {
Flag bool `json:"flag"`
Data interface{} `json:"data"`
Msg string `json:"msg"`
}
// ResSudoku sudoku --------------------------------------------------------------------
type ResSudoku struct {
Flag bool `json:"flag"`
Data resSudokuData
}
type resSudokuData struct {
Check bool `json:"check"`
Result string `json:"result"`
}
// ResHolidays holidays -------------------------------------------------------------------
type ResHolidays struct {
Date string `json:"date"`
HolidayNameCn string `json:"holiday_name_cn"`
}
type resHolidaysApi struct {
Date string `json:"date"`
Name string `json:"name"`
IsOffDay bool `json:"isOffDay"`
}
// ipLocation
type resIpLocation struct {
Status string `json:"status"`
Data []resIpLocationData `json:"data"`
}
type resIpLocationData struct {
OriginQuery string `json:"origin_query"`
Location string `json:"location"`
}

68
api_iris/utils/user.go Normal file
View File

@ -0,0 +1,68 @@
package utils
import (
"errors"
"github.com/golang-jwt/jwt/v4"
"github.com/kataras/iris/v12"
"github.com/sirupsen/logrus"
"main/database"
"main/model"
)
var UserList []model.Userinfo
// GetLoginUser 根据token获取用户,返回用户信息
func GetLoginUser(ctx iris.Context) model.Userinfo {
if ctx.Values().Get("jwt") == nil {
ctx.StatusCode(iris.StatusUnauthorized)
ctx.SetErr(errors.New("未登录"))
logrus.Warningln("请求未携带token信息")
return model.Userinfo{}
}
var tokens []model.JwtKeys
db := database.GetInstance().GetMysqlDb()
auth := ctx.Values().Get("jwt").(*jwt.Token)
if err := db.Where("token = ?", auth.Raw).Find(&tokens).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
if len(tokens) == 0 {
ctx.StatusCode(iris.StatusUnauthorized)
ctx.SetErr(errors.New("未登录"))
logrus.Warningln("token信息无效")
return model.Userinfo{}
}
foobar := auth.Claims.(jwt.MapClaims)
for key, value := range foobar {
if key == "username" {
return GetUserInfo(value.(string))
}
}
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(errors.New("系统错误,请联系管理员"))
logrus.Errorln("token存在但获取用户信息失败")
return model.Userinfo{}
}
// GetUserInfo 根据用户名获取用户信息,先更新本地数据
func GetUserInfo(username string) model.Userinfo {
if len(UserList) == 0 {
logrus.Warnln("暂存用户列表为空,刷新数据")
UpdateUserInfo()
}
for _, u := range UserList {
if u.Username == username {
return u
}
}
logrus.Warnln("未找到对应的用户信息")
return model.Userinfo{}
}
// UpdateUserInfo 更新当前用户信息
func UpdateUserInfo() {
db := database.GetInstance().GetMysqlDb()
if err := db.Find(&UserList).Error; err != nil {
logrus.Errorln("sql执行失败", err)
}
logrus.Infoln("刷新暂存用户列表")
}

255
api_iris/utils/utils.go Normal file
View File

@ -0,0 +1,255 @@
package utils
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"github.com/jordan-wright/email"
"github.com/kataras/iris/v12"
"github.com/shopspring/decimal"
"github.com/sirupsen/logrus"
"io"
"main/config"
"main/database"
"main/model"
"math/rand"
"net/http"
"net/smtp"
"os"
"path"
"reflect"
"regexp"
"runtime"
"strings"
"time"
"unsafe"
)
// FormatRes 格式化result
func FormatRes(code int, msg string, data interface{}) ResponseBean {
return ResponseBean{
Code: code,
Msg: msg,
Data: data,
}
}
// GetEnvDefault 获取带默认值环境变量
func GetEnvDefault(name string, defaultVal string) string {
val, ok := os.LookupEnv(name)
if ok {
return val
} else {
return defaultVal
}
}
// FileRead 读取文件,返回行列表
func FileRead(file string, condition bool) ([]string, error) {
f, err := os.Open(file)
var res []string
if err != nil {
return []string{}, err
}
defer func(f *os.File) {
err = f.Close()
if err != nil {
return
}
}(f)
reader := bufio.NewReader(f)
for {
line, _, err := reader.ReadLine()
if err != nil {
break
}
if condition && len(line) > 1 {
res = append(res, string(line))
}
}
return res, nil
}
func SendEmail(receiver []string, subject string, content string) error {
emailConfig := config.Config.Email
sender := fmt.Sprintf("ylsa <%s>", emailConfig.Username)
message := email.NewEmail()
message.From = sender
message.To = receiver
message.Subject = subject
message.Text = []byte(content)
logrus.Infoln("发送邮件:", sender, receiver)
err := message.Send("smtp.163.com:25", smtp.PlainAuth("", emailConfig.Username, emailConfig.Password, "smtp.163.com"))
if err != nil {
return err
}
return nil
}
// DataIsNil 判断数据是否为空
func DataIsNil(arg interface{}) bool {
if reflect.ValueOf(arg).Kind().String() == "ptr" || reflect.ValueOf(arg).Kind().String() == "slice" {
if reflect.ValueOf(arg).IsValid() {
return true
}
} else {
if reflect.ValueOf(arg).IsZero() {
return true
}
}
return false
}
// ErrHandle 错误处理
func ErrHandle(ctx iris.Context, err error) bool {
if err != nil {
pc, _, _, _ := runtime.Caller(1)
f := runtime.FuncForPC(pc).Name()
db := database.GetInstance().GetMysqlDb()
if err1 := db.Create(&model.SysError{
Username: GetLoginUser(ctx).Username,
Time: time.Now(),
Function: f,
ErrorInfo: err.Error(),
}).Error; err1 != nil {
logrus.Errorln("sql执行失败", err1.Error())
}
ctx.StatusCode(iris.StatusInternalServerError)
ctx.SetErr(err)
return true
}
return false
}
// NewKey 取n位随机数
func NewKey(n int) string {
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890()-+*/~"
var src = rand.NewSource(time.Now().UnixNano())
const (
// 6 bits to represent a letter index
letterIdBits = 6
// All 1-bits as many as letterIdBits
letterIdMask = 1<<letterIdBits - 1
letterIdMax = 63 / letterIdBits
)
b := make([]byte, n)
// A rand.Int63() generates 63 random bits, enough for letterIdMax letters!
for i, cache, remain := n-1, src.Int63(), letterIdMax; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), letterIdMax
}
if idx := int(cache & letterIdMask); idx < len(letters) {
b[i] = letters[idx]
i--
}
cache >>= letterIdBits
remain--
}
return *(*string)(unsafe.Pointer(&b))
}
// CheckListItem 判断item是否在list内
func CheckListItem[T comparable](data []T, item T) bool {
for _, value := range data {
if value == item {
return true
}
}
return false
}
// FileIsExist 判断路径是否存在
func FileIsExist(path string) bool {
if _, err := os.Stat(path); os.IsNotExist(err) {
return false
}
return true
}
// Round float取小数
func Round(num float64, n int32) float64 {
res, _ := decimal.NewFromFloat(num).Round(n).Float64()
return res
}
// GetFileType 获取文件类型
func GetFileType(f string) string {
fileSuffix := path.Ext(f)
fileSuffix = strings.ToLower(fileSuffix)
patternFileSuffix := fmt.Sprintf("^%s,|,%s,|,%s$|%s", fileSuffix, fileSuffix, fileSuffix, fileSuffix)
regFileSuffix := regexp.MustCompile(patternFileSuffix)
for _, v := range SysSettings {
if strings.HasPrefix(v.Name, "fileType:") && regFileSuffix.MatchString(v.Value) {
return strings.Split(v.Name, "fileType:")[1]
}
}
//switch fileSuffix {
//case ".png", ".jpg", ".jpeg", ".bmp", ".gif":
// return "image"
//case ".mp4", ".m2v", ".mkv", ".rmvb", ".avi", ".flv", ".mov", ".m4v", ".wmv", ".f4v":
// return "video"
//case ".mp3", ".wav", ".flac":
// return "audio"
//case ".zip", ".rar", ".7z":
// return "zip"
//}
return "doc"
}
// IntAbs 数字取绝对值
func IntAbs(i int) int {
if i < 0 {
return -i
} else {
return i
}
}
// Reverse 字符串反转
func Reverse(s string) string {
a := []rune(s)
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
}
return string(a)
}
func GetRequestIp(ctx iris.Context) string {
realIp := ctx.Request().Header.Get("X-Real-IP")
if realIp != "" {
return realIp
}
ip := ctx.RemoteAddr()
return ip
}
func GetIpLocation(ip string) (string, error) {
var ipLocation resIpLocation
data, err := http.Get(fmt.Sprintf("https://opendata.baidu.com/api.php?query=%s&co=&resource_id=6006&oe=utf8", ip))
if err != nil {
logrus.Errorln(ip, "ip地址请求失败", err)
return "", err
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
return
}
}(data.Body)
body, err := io.ReadAll(data.Body)
if err != nil {
logrus.Errorln(ip, "获取IP地址请求读取失败", err)
return "", err
}
err = json.Unmarshal(body, &ipLocation)
if err != nil {
logrus.Errorln(ip, "IP地址请求结果解析失败", err)
return "", err
}
if len(ipLocation.Data) == 0 {
logrus.Errorln(ip, "ip地址无效")
return "", errors.New("ip地址无效")
}
return ipLocation.Data[0].Location, nil
}