migu_music_server/app/admin/models/clue.go

471 lines
12 KiB
Go
Raw Normal View History

2025-03-28 06:07:20 +00:00
package models
import (
"errors"
"fmt"
"github.com/go-admin-team/go-admin-core/logger"
"github.com/xuri/excelize/v2"
"gorm.io/gorm"
"math/rand"
"strings"
"time"
)
const (
QueryTimeFormat = "2006-01-02T15:04:05+08:00"
TimeFormat = "2006-01-02 15-04-05"
ExportUrl = "https://admin.go2switch.cn/load/export/"
ExportExcelFlag = 1
ExportPath = "/www/server/images/export/"
)
var certMap = map[int]string{
1: "电工证",
2: "焊工证",
3: "叉车证",
4: "制冷与空调作业证",
5: "高空作业证",
6: "危化品作业证",
7: "安全员证",
8: "其他工种上岗证",
}
var WhiteList = map[string]int{
"15019230751": 1,
"18025373706": 2,
}
type SendDataReq struct {
Url string `json:"url"`
Uid string `json:"uid"`
}
type OppoSendDataReq struct {
PageId int64 `json:"pageId"`
OwnerId int64 `json:"ownerId"`
Ip string `json:"ip"`
Tid string `json:"tid"`
Lbid string `json:"lbid"`
Items []ClueDataItem `json:"items"`
TransformType int `json:"transformType"`
PageType int `json:"pageType,omitempty"`
PayId string `json:"payId,omitempty"`
PayAmount string `json:"payAmount,omitempty"`
RefundId string `json:"refundId,omitempty"`
Amount string `json:"amount,omitempty"`
CustomId string `json:"customId,omitempty"`
}
type ClueDataItem struct {
Column string `json:"column"`
Type string `json:"type"`
IfNeed bool `json:"ifNeed"`
Desc string `json:"desc"`
Value string `json:"value"`
Options []string `json:"options,omitempty"`
}
type OppoSendDataResp struct {
Code int `json:"code"`
Msg string `json:"msg"`
}
type NewSendDataReq struct {
Url string `json:"url" binding:"required"` // 页面url路径
Name string `json:"name" binding:"required"` // 姓名
Tel string `json:"tel" binding:"required"` // 电话
Type int `json:"type" binding:"required"` // 广告页类型 1-八大员2-旅游
CertList []int `json:"cert_list"` // 证书列表1-电工证2-焊工证3-叉车证4-制冷与空调作业证5-高空作业证6-危化品作业证7-安全员证8-其他工种上岗证
Data interface{} `json:"data"` // 其他选择内容
}
// TravelData 旅游广告页其他参数
type TravelData struct {
TravelCount int `json:"travel_count"` // 出行人数
}
type ClueUser struct {
Model
Name string `json:"name"` // 姓名
Tel string `json:"tel" gorm:"index"` // 电话
Cert string `json:"cert" gorm:"index"` // 证书列表
}
type ClueUserTravel struct {
Model
Name string `json:"name"` // 姓名
Tel string `json:"tel" gorm:"index"` // 电话
}
type GetUserDataReq struct {
Name string `json:"name"` // 姓名
Tel string `json:"tel"` // 电话
StartTime string `json:"start_time"` // 开始时间
EndTime string `json:"end_time"` // 结束时间
Type int `json:"type"` // 广告页类型 1-八大员2-旅游
IsExport uint32 `json:"is_export"` // 1-导出
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
}
type GetUserDataResp struct {
Total int64 `json:"total"` // 总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
ExportUrl string `json:"export_url"` // 导出excel地址
List []ClueUser `json:"list"`
}
type ClueCode struct {
Model
Phone string `json:"phone" gorm:"index"` // 电话
Code int `json:"code"` // 验证码
Expiry time.Time `json:"expiry"` // 过期时间
}
type GetCodeReq struct {
Tel string `json:"tel" binding:"required"` // 电话
Type int `json:"type" binding:"required"` // 广告页类型 1-八大员2-旅游
}
type GetCodeResp struct {
Code int `json:"code"` // 验证码
}
type VerifyCodeReq struct {
Tel string `json:"tel" binding:"required"` // 电话
Code int `json:"code" binding:"required"` // 验证码
}
type GetPhoneWithTokenReq struct {
SpToken string `json:"SpToken" binding:"required"` // JSSDK 获取的号码认证 Token
}
type RecordLog struct {
Data interface{} `json:"data"`
}
func GetUserDataList(req *GetUserDataReq, Db *gorm.DB) (*GetUserDataResp, error) {
page := req.PageIndex - 1
if page < 0 {
page = 0
}
if req.PageSize == 0 {
req.PageSize = 10
}
resp := &GetUserDataResp{
PageIndex: req.PageIndex,
PageSize: req.PageSize,
}
var qs *gorm.DB
if req.Type == 2 { // 旅游
qs = Db.Table("clue_user_travel")
} else {
qs = Db.Table("clue_user")
}
if req.Name != "" {
qs = qs.Where("name=?", req.Name)
}
if req.Tel != "" {
qs = qs.Where("tel=?", req.Tel)
}
if req.StartTime != "" {
startTime := req.StartTime
loc, _ := time.LoadLocation("Asia/Shanghai") // 以东八区为例
start, err := time.ParseInLocation(QueryTimeFormat, startTime, loc)
if err != nil {
logger.Errorf("Error parsing start time: %v", err)
return resp, err
}
qs = qs.Where("created_at >= ?", start)
}
if req.EndTime != "" {
endTime := req.EndTime
loc, _ := time.LoadLocation("Asia/Shanghai") // 以东八区为例
end, err := time.ParseInLocation(QueryTimeFormat, endTime, loc)
if err != nil {
logger.Errorf("Error parsing end time: %v", err)
return resp, err
}
qs = qs.Where("created_at <= ?", end)
}
fmt.Printf("Start Time: %v, End Time: %v", req.StartTime, req.EndTime)
var count int64
err := qs.Count(&count).Error
if err != nil {
logger.Error("count err:", err)
return resp, err
}
var orders []ClueUser
if req.IsExport == ExportExcelFlag { // 导出excel
err := qs.Order("id DESC").Find(&orders).Error
if err != nil && err != RecordNotFound {
logger.Error("erp commodity list err:", err)
return resp, err
}
var filePath string
if req.Type == 2 { // 旅游
filePath, err = travelUserDataExport(orders)
} else {
filePath, err = userDataExport(orders)
}
if err != nil {
return nil, nil
}
resp.ExportUrl = filePath
} else {
err := qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&orders).Error
if err != nil && err != RecordNotFound {
logger.Error("erp commodity list err:", err)
return resp, err
}
resp.List = orders
resp.Total = count
}
return resp, nil
}
// userDataExport 导出用户数据-八大员
func userDataExport(req []ClueUser) (string, error) {
file := excelize.NewFile()
streamWriter, err := file.NewStreamWriter("Sheet1")
if err != nil {
fmt.Println(err)
}
url := ExportUrl
//url := "/Users/max/Documents/"
fileName := time.Now().Format(TimeFormat) + "-八大员操作证-用户数据" + ".xlsx"
fmt.Println("url fileName:", url+fileName)
title := []interface{}{"姓名", "电话", "工种操作证", "提交时间"}
cell, _ := excelize.CoordinatesToCellName(1, 1)
if err = streamWriter.SetRow(cell, title); err != nil {
fmt.Println(err)
}
var row []interface{}
nExcelStartRow := 0
for rowId := 0; rowId < len(req); rowId++ {
row = []interface{}{
req[rowId].Name,
req[rowId].Tel,
req[rowId].Cert,
req[rowId].CreatedAt,
}
cell, _ = excelize.CoordinatesToCellName(1, nExcelStartRow+2)
if err = streamWriter.SetRow(cell, row); err != nil {
fmt.Println(err)
}
nExcelStartRow++
}
if err := streamWriter.Flush(); err != nil {
fmt.Println(err)
}
fmt.Println("save fileName:", url+fileName)
if err := file.SaveAs(ExportPath + fileName); err != nil {
fmt.Println(err)
}
return url + fileName, nil
}
// userDataExport 导出用户数据-旅游
func travelUserDataExport(req []ClueUser) (string, error) {
file := excelize.NewFile()
streamWriter, err := file.NewStreamWriter("Sheet1")
if err != nil {
fmt.Println(err)
}
url := ExportUrl
//url := "/Users/max/Documents/"
fileName := time.Now().Format(TimeFormat) + "-重庆旅游-用户数据" + ".xlsx"
fmt.Println("url fileName:", url+fileName)
title := []interface{}{"姓名", "电话", "提交时间"}
cell, _ := excelize.CoordinatesToCellName(1, 1)
if err = streamWriter.SetRow(cell, title); err != nil {
fmt.Println(err)
}
var row []interface{}
nExcelStartRow := 0
for rowId := 0; rowId < len(req); rowId++ {
row = []interface{}{
req[rowId].Name,
req[rowId].Tel,
req[rowId].CreatedAt,
}
cell, _ = excelize.CoordinatesToCellName(1, nExcelStartRow+2)
if err = streamWriter.SetRow(cell, row); err != nil {
fmt.Println(err)
}
nExcelStartRow++
}
if err := streamWriter.Flush(); err != nil {
fmt.Println(err)
}
fmt.Println("save fileName:", url+fileName)
if err := file.SaveAs(ExportPath + fileName); err != nil {
fmt.Println(err)
}
return url + fileName, nil
}
// ConvertCertListToString 转换证书列表数据
func ConvertCertListToString(certList []int) string {
var result []string
for _, cert := range certList {
if certName, ok := certMap[cert]; ok {
result = append(result, certName)
}
}
return strings.Join(result, ",")
}
func GetSMSCode(req *GetCodeReq, db *gorm.DB, nType int) (*GetCodeResp, error) {
// Generate random 6-digit OTP
rand.Seed(time.Now().UnixNano())
otp := rand.Intn(900000) + 100000
expiry := time.Now().Add(5 * time.Minute)
// 发送短信
var err error
var message string
if nType == 2 { // 重庆旅游
message = fmt.Sprintf("【边城旅行】短信验证码:%d有效期5分钟您正在领取优惠名额。如非本人操作请忽略本短信。", otp)
} else { // 八大员操作证
message = fmt.Sprintf("【捷速教育】短信验证码:%d有效期5分钟您正在领取免费报考福利。如非本人操作请忽略本短信。", otp)
}
fmt.Println(message)
var phoneList []string
phoneList = append(phoneList, req.Tel)
err = GtSendMessage(phoneList, message)
if err != nil {
return nil, err
}
// 成功后记录数据
codeData := &ClueCode{}
codeData.Phone = req.Tel
codeData.Code = otp
codeData.Expiry = expiry
err = db.Create(codeData).Error
if err != nil {
return nil, err
}
return &GetCodeResp{
Code: otp,
}, nil
}
func VerifySMSCode(req *VerifyCodeReq, db *gorm.DB) error {
var codeDataList []ClueCode
err := db.Model(&ClueCode{}).Where("phone = ?", req.Tel).Find(&codeDataList).Error
if err != nil {
return err
}
if len(codeDataList) == 0 {
return errors.New("未查询到验证码,请重新获取")
}
// 校验当前验证码
flag := false
for _, v := range codeDataList {
if req.Code != v.Code {
continue
} else {
if time.Now().After(v.Expiry) {
return errors.New("验证码已过期,请重新获取")
} else {
flag = true
}
}
}
if !flag {
return errors.New("校验失败,请重新获取")
}
return nil
}
// CheckPhone 检查手机号是否存在
func CheckPhone(nType int, tel string, db *gorm.DB) (bool, error) {
var exist bool
var whiteExist bool
var err error
if nType == 1 {
exist, err = QueryRecordExist(fmt.Sprintf("SELECT * FROM clue_user WHERE tel='%s'", tel), db)
if err != nil {
logger.Errorf("CheckPhone err:", err)
return false, err
}
} else if nType == 2 {
exist, err = QueryRecordExist(fmt.Sprintf("SELECT * FROM clue_user_travel WHERE tel='%s'", tel), db)
if err != nil {
logger.Errorf("CheckPhone err:", err)
return false, err
}
} else {
return false, errors.New("参数type类型有误")
}
whiteExist, err = QueryRecordExist(fmt.Sprintf("SELECT * FROM white_list WHERE phone='%s'", tel), db)
if err != nil {
logger.Errorf("CheckPhone err:", err)
return false, err
}
if exist && !whiteExist {
return true, nil
}
return false, nil
}
// RecordUserData 回传成功后记录到数据库
func RecordUserData(req *NewSendDataReq, db *gorm.DB) error {
if req.Type == 1 {
h5Data := &ClueUser{}
h5Data.Name = req.Name
h5Data.Tel = req.Tel
if len(req.CertList) != 0 {
h5Data.Cert = ConvertCertListToString(req.CertList)
}
err := db.Create(h5Data).Error
if err != nil {
logger.Info("Create ClueUser err:", err)
return err
}
} else if req.Type == 2 {
h5Data := &ClueUserTravel{}
h5Data.Name = req.Name
h5Data.Tel = req.Tel
err := db.Create(h5Data).Error
if err != nil {
logger.Info("Create ClueUser err:", err)
return err
}
}
return nil
}