算了,后端我自己写吧

This commit is contained in:
2026-04-01 12:09:02 +08:00
parent 4138340f53
commit 1a0a01a56d
69 changed files with 1949 additions and 102 deletions
+57
View File
@@ -0,0 +1,57 @@
package models
import "github.com/mitchellh/mapstructure"
var Configs map[string]interface{}
type ConfigsWeb_ struct {
Host string `mapstructure:"host"`
Port string `mapstructure:"port"`
Tls bool `mapstructure:"tls"`
CertPrivatePath string `mapstructure:"certPrivatePath"`
CertPublicPath string `mapstructure:"certPublicPath"`
}
type ConfigsUser_ struct {
CookieTimeout int `mapstructure:"cookieTimeout"`
PassHashType string `mapstructure:"passHashType"`
}
type ConfigsFile_ struct {
MaxSize uint64 `mapstructure:"maxSize"`
Pahts map[string]string `mapstructure:"pahts"`
AllowImageMime map[string]string `mapstructure:"allowImageMime"`
AllowVideoMime map[string]string `mapstructure:"allowVideoMime"`
AllowMusicMime map[string]string `mapstructure:"allowMusicMime"`
AllowPdfMime map[string]string `mapstructure:"allowPdfMime"`
}
var ConfigsWed ConfigsWeb_
var ConfigsUser ConfigsUser_
var ConfigsFile ConfigsFile_
func ConfigAllInit() error {
//初始化数据库
DatabaseInit()
//读取web配置
err := mapstructure.Decode(Configs["web"].(map[string]interface{}), &ConfigsWed)
if err != nil {
panic(err)
}
//初始化user config
err = mapstructure.Decode(Configs["user"].(map[string]interface{}), &ConfigsUser)
if err != nil {
panic(err)
}
//初始化file config
err = mapstructure.Decode(Configs["file"].(map[string]interface{}), &ConfigsFile)
if err != nil {
panic(err)
}
return nil
}
+108
View File
@@ -0,0 +1,108 @@
package models
import (
"crypto/md5"
"crypto/rand"
"encoding/hex"
"regexp"
"strings"
"time"
)
// 获取当前时间字符串
// 参数格式可选,默认"2006-01-02 15:04:05"
func GetCurrentTimeString(format ...string) string {
// 默认格式
layout := "2006_01_02-15_04_05.999999999"
// 如果传入了格式参数则使用自定义格式
if len(format) > 0 {
layout = format[0]
}
return time.Now().Format(layout)
}
func StringToTimePtr(str string) (*time.Time, error) {
layout := "2006-01-02 15:04"
t, err := time.Parse(layout, str)
if err != nil {
return nil, err
}
return &t, nil
}
func RandStr32() string {
// 生成 32 字节 (256 位) 随机数据
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil {
panic(err)
}
// 转换为 16 进制字符串 (长度 64)
cookie := hex.EncodeToString(b)
return cookie
}
func Md5Str(str string) string {
hashBytes2 := md5.Sum([]byte(str))
hashString2 := hex.EncodeToString(hashBytes2[:]) // 注意数组转切片的[:]
return hashString2
}
func HashUserPass(user *TabUser_) {
switch ConfigsUser.PassHashType {
case "text":
break
case "md5":
user.Pass = Md5Str(user.Pass)
case "md5salt":
if user.Salt == "" {
user.Salt = RandStr32()
}
user.Pass = Md5Str(Md5Str(user.Pass) + user.Salt)
}
}
func IsExpired(expireTime time.Time) bool {
return expireTime.Before(time.Now())
}
func CheckCookiesAndUpdate(cookie *TabCookie_) bool {
if !IsExpired(cookie.ExpiresAt) {
if cookie.Remember {
cookiewhere := TabCookie_{
ID: cookie.ID,
}
cookieupdata := TabCookie_{
UpdatedAt: time.Now(),
ExpiresAt: time.Now().Add(time.Duration(ConfigsUser.CookieTimeout) * time.Second),
}
DB.Where(&cookiewhere).Updates(&cookieupdata)
}
return true
} else {
//以过期
return false
}
//return false
}
// 判断邮箱是否合法
func IsEmailValid(email string) bool {
// 正则表达式(覆盖 99% 常见邮箱格式)
pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
regex := regexp.MustCompile(pattern)
return regex.MatchString(email)
}
// 判断字符串是否包含标点符号
func IsContainsSpecialChar(str string) bool {
specialChars := "!@#$%^&*()-+={}[]|\\:;\"'<>,.?/"
return strings.ContainsAny(str, specialChars)
}
+58
View File
@@ -0,0 +1,58 @@
package models
import (
"crypto"
"encoding/hex"
"io"
"mime/multipart"
"net/http"
"os"
)
// 判断文件是否存在
func FileExists(path string) bool {
_, err := os.Stat(path)
if err != nil {
return !os.IsNotExist(err)
}
return true
}
// 计算文件的哈希
func SHA256HashFile(file_head *multipart.FileHeader) (string, error) {
// 打开文件
file, err := file_head.Open()
if err != nil {
return "foen error", err
}
defer file.Close()
hasher := crypto.SHA256.New()
// 从文件流中读取并计算哈希
_, err = io.Copy(hasher, file)
if err != nil {
return "", err
}
hashBytes := hasher.Sum(nil)
return hex.EncodeToString(hashBytes), nil
}
// 获取文件mime
func GetFileMime(file_head *multipart.FileHeader) (string, error) {
file, err := file_head.Open()
if err != nil {
return "foen error", err
}
defer file.Close()
// 读取前512字节用于MIME检测
buffer := make([]byte, 512)
io.ReadFull(file, buffer)
mimeType := http.DetectContentType(buffer)
return mimeType, nil
}
+50
View File
@@ -0,0 +1,50 @@
package models
import (
"net"
"strings"
"github.com/gin-gonic/gin"
)
// GetRealIP 获取真实IP(处理代理)
func GetRealIP(c *gin.Context) string {
// 优先级顺序
headers := []string{
"CF-Connecting-IP", // Cloudflare
"True-Client-IP",
"X-Forwarded-For",
"X-Real-IP",
}
for _, header := range headers {
if ip := c.GetHeader(header); ip != "" {
// 处理多个IP的情况(如 X-Forwarded-For: client, proxy1, proxy2
if strings.Contains(ip, ",") {
ips := strings.Split(ip, ",")
ip = strings.TrimSpace(ips[0])
}
if net.ParseIP(ip) != nil {
return ip
}
}
}
// 最后使用Gin的ClientIP方法
return c.ClientIP()
}
func LogAdd(c *gin.Context, msg string) {
var logtemp APIRequestLog_
logtemp.IPAddress = GetRealIP(c)
logtemp.Path = c.Request.URL.Path
logtemp.Method = c.Request.Method
logtemp.Message = msg
//fmt.Println(logtemp)
DB.Create(&logtemp)
}
+167
View File
@@ -0,0 +1,167 @@
package models
import (
"fmt"
"time"
"github.com/glebarez/sqlite"
"gorm.io/datatypes"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
var DB *gorm.DB
type TabFileInfo_ struct {
ID uint `gorm:"primaryKey;autoIncrement"`
Name string `gorm:"not null;size:256;index"` // 前端报告的文件名
Path string `gorm:"not null;size:300"` //
Sha256 string `gorm:"not null;size:64;index"` //
Mime string `gorm:"size:64;index"`
Type string `gorm:"size:64;index"`
Const uint `gorm:"default:1;index"`
Per uint `gorm:"default:1"`
UserID uint `gorm:"not null;index"`
Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间
}
type TabUser_ struct {
ID uint `gorm:"primaryKey;autoIncrement"` // 自增主键
Name string `gorm:"size:100;uniqueIndex"` // 唯一约束索引
Email string `gorm:"size:255;index"` // 字符串长度限制100 索引
Pass string `gorm:"size:128"` // 建议存储哈希后的密码
Type string `gorm:"size:64;default:user"` //
Salt string `gorm:"size:64;"`
Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间
}
type TabUserGroups_ struct {
ID uint `gorm:"primaryKey;autoIncrement"` // 自增主键
Name string `gorm:"size:100;uniqueIndex"` // 唯一约束索引
Email string `gorm:"size:255;index"` // 字符串长度限制100 索引
Type string `gorm:"size:64;default:usergroup"` //
Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间
}
type TabUserGroupBinds_ struct {
ID uint `gorm:"primaryKey;autoIncrement"` // 自增主键
UserID uint `gorm:"index"`
GroupID uint `gorm:"index"`
Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间
}
type TabUserInfo_ struct {
ID uint `gorm:"primaryKey;autoIncrement"`
UserID uint `gorm:"not null;uniqueIndex"`
FirstName string `gorm:"size:50;null"`
Username string `gorm:"size:30;null"`
Birthdate time.Time `gorm:"type:datetime;null"`
Gender string `gorm:"type:char(1);check:gender IN ('M', 'F', 'U');default:'U'"`
AvatarPath string `gorm:"size:255"`
Region string `gorm:"size:50"`
Language string `gorm:"size:10;default:'zh-CN'"`
CreatedAt time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP;column:created_at"`
}
// var def_user_info = User_info{
// ID:0,
// UserID:0,
// }
type TabCookie_ struct {
ID uint `gorm:"primaryKey;autoIncrement"`
UserID uint `gorm:"not null"`
Name string `gorm:"size:255;not null;index"`
Value string `gorm:"size:255;not null;index"`
ExpiresAt time.Time `gorm:"type:datetime;index"`
CreatedAt time.Time `gorm:"type:datetime;not null;default:CURRENT_TIMESTAMP"`
UpdatedAt time.Time `gorm:"type:datetime;index;not null;default:CURRENT_TIMESTAMP"`
Remember bool `gorm:"default:false"`
}
type APIRequestLog_ struct {
ID int64 `gorm:"primaryKey;column:id" json:"id"`
IPAddress string `gorm:"column:ip_address;size:45;not null" json:"ip_address"`
Path string `gorm:"column:path;size:500;not null" json:"path"`
Method string `gorm:"column:method;size:10;not null" json:"method"`
StatusCode int `gorm:"column:status_code;index" json:"status_code"`
Message string `gorm:"column:error_message;type:text" json:"error_message"`
CreatedAt time.Time `gorm:"column:created_at;type:datetime;default:CURRENT_TIMESTAMP" json:"created_at"`
}
type TabPurchaseOrder struct {
ID uint `gorm:"primarykey"`
UserID uint `gorm:"not null"`
Title string `gorm:"size:200;comment:标题"`
Remark string `gorm:"type:text;comment:备注"`
Photos datatypes.JSON `gorm:"type:json;comment:照片哈希数组"`
Link string `gorm:"size:1000;comment:链接"`
PartName string `gorm:"size:200;not null;comment:物品名称"`
Styles string `gorm:"type:text;comment:样式数组"`
//Costs datatypes.JSON `gorm:"type:json;comment:费用明细数组"`
UpdateTime *time.Time `gorm:"type:datetime;autoUpdateTime;comment:更新时间"`
TrackingNumber string `gorm:"size:100;Index;comment:快递单号"`
OrderStatus string `gorm:"default:1;comment:订单状态"`
CreatedAt *time.Time `gorm:"type:datetime;autoCreateTime"`
UpdatedAt *time.Time `gorm:"type:datetime;autoUpdateTime"`
DeletedAt gorm.DeletedAt `gorm:"index"`
}
type TabPurchaseCosts struct {
ID uint `gorm:"primarykey"`
OrderID uint `gorm:"not null"`
UserID uint `gorm:"not null"`
Price int `gorm:"not null"`
Quantity int `gorm:"not null"`
CreatedAt *time.Time `gorm:"type:datetime;autoCreateTime"`
}
func DatabaseInit() error {
var err error
fmt.Println("database_init")
DatabaseConfigs := Configs["database"].(map[string]interface{})
if DatabaseConfigs["type"].(string) == "sqlite" {
//sqlite init
fmt.Println("sqlite")
DB, err = gorm.Open(sqlite.Open(DatabaseConfigs["path"].(string)), &gorm.Config{})
} else if DatabaseConfigs["type"].(string) == "mysql" {
//mysql init
fmt.Println("mysql")
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", DatabaseConfigs["user"].(string), DatabaseConfigs["pass"].(string), DatabaseConfigs["host"].(string), DatabaseConfigs["port"].(string), DatabaseConfigs["name"].(string))
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
} else if DatabaseConfigs["type"].(string) == "pg" {
//postgresql init
fmt.Println("postgresql")
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai", DatabaseConfigs["host"].(string), DatabaseConfigs["user"].(string), DatabaseConfigs["pass"].(string), DatabaseConfigs["name"].(string), DatabaseConfigs["port"].(string))
DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
}
if err != nil {
fmt.Println(err)
panic("数据库连接失败")
}
// 自动创建表结构
DB.AutoMigrate(&TabUser_{})
DB.AutoMigrate(&TabUserGroups_{})
DB.AutoMigrate(&TabUserGroupBinds_{})
DB.AutoMigrate(&TabUserInfo_{})
DB.AutoMigrate(&TabCookie_{})
DB.AutoMigrate(&TabFileInfo_{})
DB.AutoMigrate(&APIRequestLog_{})
DB.AutoMigrate(&TabPurchaseOrder{})
DB.AutoMigrate(&TabPurchaseCosts{})
return nil
}