migu_music_server/app/admin/models/clue.go
2025-03-28 14:07:20 +08:00

471 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}