diff --git a/app/agent/hdl/hdl_file_img_callback.go b/app/agent/hdl/hdl_file_img_callback.go new file mode 100644 index 0000000..57562b6 --- /dev/null +++ b/app/agent/hdl/hdl_file_img_callback.go @@ -0,0 +1,57 @@ +package hdl + +import ( + "applet/app/utils" + "fmt" + "github.com/gin-gonic/gin" + + "applet/app/e" + "applet/app/md" + "applet/app/svc" +) + +// 文件七牛云回调确认 +func FileImgCallback(c *gin.Context) { + masterID := c.Query("master_id") + c.Set("mid", masterID) + var args md.FileCallback + err := c.ShouldBindJSON(&args) + utils.FilePutContents("qiniuyun", masterID) + + if err != nil { + utils.FilePutContents("qiniuyun", utils.SerializeStr(err)) + fmt.Println("七牛云上传回调参数错误:>>>>>>>>>>", err) + e.OutErr(c, 200, e.ERR_INVALID_ARGS) + return + } + fmt.Println("七牛云上传回调参数:>>>>>>>>>>", utils.SerializeStr(args)) + if err = svc.FileSave(c, &args); err != nil { + utils.FilePutContents("qiniuyun", utils.SerializeStr(err)) + + fmt.Println("七牛云上传回调保存文件错误:>>>>>>>>>>", err) + e.OutErr(c, 200, err) + return + } + + res := map[string]interface{}{ + "name": args.FileName, + "fname": getFileNameURL(c, args.FileName), + "fsize": args.FileSize, + "provider": args.Provider, + "uid": args.Uid, + "dir_id": args.DirId, + "w": args.Width, + "h": args.Height, + } + e.OutSuc(c, &res, nil) +} + +func getFileNameURL(c *gin.Context, filename string) string { + protocol := svc.SysCfgGet(c, "file_bucket_scheme") + domain := svc.SysCfgGet(c, "file_bucket_host") + imgformat := svc.SysCfgGet(c, "file_avatar_thumbnail") + if protocol != "" && domain != "" && imgformat != "" { + return protocol + "://" + domain + "/" + filename + } + return filename +} diff --git a/app/agent/hdl/hdl_file_img_req_upload.go b/app/agent/hdl/hdl_file_img_req_upload.go new file mode 100644 index 0000000..6f3b8bf --- /dev/null +++ b/app/agent/hdl/hdl_file_img_req_upload.go @@ -0,0 +1,95 @@ +package hdl + +import ( + "applet/app/e" + "applet/app/md" + "applet/app/svc" + "applet/app/utils" + "applet/app/utils/logx" + "github.com/gin-gonic/gin" +) + +// 请求上传图片 +func ImgReqUpload(c *gin.Context) { + user := svc.GetUser(c) + uid := utils.IntToStr(user.Info.Uid) + // 文件名名称 + var args struct { + Dir string `json:"dir"` + FileName string `json:"file_name"` + FileSize int64 `json:"file_size"` // 文件大小, 单位byte + } + if err := c.ShouldBindJSON(&args); err != nil || args.FileSize < 1 || args.FileName == "" { + logx.Warn(err) + e.OutErr(c, e.ERR_INVALID_ARGS) + return + } + // 限制用户上传目录 + if _, ok := md.FileUserDir[args.Dir]; !ok { + e.OutErr(c, e.ERR_FORBIDEN) + return + } + scheme := "http" + if c.Request.TLS != nil { + scheme = "https" + } + // 拼装回调地址 + callbackUrl := scheme + "://" + c.Request.Host + "/api/v1/communityTeam/agent/file/img/callback?master_id=" + c.GetString("mid") + utils.FilePutContents("qiniuyun", callbackUrl) + //fmt.Println(callbackUrl) + // callbackUrl = "http://120.55.83.222/raw.php" + res, err := svc.ImgReqUpload(c, uid, args.Dir, args.FileName, callbackUrl, args.FileSize) + if err != nil { + e.OutErr(c, 400, err) + return + } + my := utils.SerializeStr(res) + var my1 map[string]interface{} + utils.Unserialize([]byte(my), &my1) + if c.GetHeader("Platform") == md.PLATFORM_WX_APPLET || c.GetHeader("Platform") == md.PLATFORM_TIKTOK_APPLET || c.GetHeader("Platform") == md.PLATFORM_TOUTIAO_APPLET || c.GetHeader("Platform") == md.PLATFORM_BAIDU_APPLET || c.GetHeader("Platform") == md.PLATFORM_ALIPAY_APPLET { + my1["host"] = "https://api.zhiyingos.com/api/v1/proxy/upload" //官方页面才有白名单 + } + e.OutSuc(c, my1, nil) +} + +// 请求上传图片 +func ImgReqUploadNoUser(c *gin.Context) { + // 文件名名称 + var args struct { + Dir string `json:"dir"` + FileName string `json:"file_name"` + FileSize int64 `json:"file_size"` // 文件大小, 单位byte + } + if err := c.ShouldBindJSON(&args); err != nil || args.FileSize < 1 || args.FileName == "" { + logx.Warn(err) + e.OutErr(c, e.ERR_INVALID_ARGS) + return + } + // 限制用户上传目录 + if _, ok := md.FileUserDir[args.Dir]; !ok { + e.OutErr(c, e.ERR_FORBIDEN) + return + } + scheme := "http" + if c.Request.TLS != nil { + scheme = "https" + } + // 拼装回调地址 + callbackUrl := scheme + "://" + c.Request.Host + "/api/v1/file/img/callback?master_id=" + c.GetString("mid") + utils.FilePutContents("qny", callbackUrl) + //fmt.Println(callbackUrl) + // callbackUrl = "http://120.55.83.222/raw.php" + res, err := svc.ImgReqUpload(c, "", args.Dir, args.FileName, callbackUrl, args.FileSize) + if err != nil { + e.OutErr(c, 400, err) + return + } + my := utils.SerializeStr(res) + var my1 map[string]interface{} + utils.Unserialize([]byte(my), &my1) + domainApiBase := svc.GetWebSiteDomainInfoOfficial(c, "api") + if c.GetHeader("Platform") == md.PLATFORM_WX_APPLET || c.GetHeader("Platform") == md.PLATFORM_TIKTOK_APPLET || c.GetHeader("Platform") == md.PLATFORM_TOUTIAO_APPLET || c.GetHeader("Platform") == md.PLATFORM_BAIDU_APPLET || c.GetHeader("Platform") == md.PLATFORM_ALIPAY_APPLET { + my1["host"] = domainApiBase + "/api/v1/proxy/upload" + } + e.OutSuc(c, my1, nil) +} diff --git a/app/db/db_file.go b/app/db/db_file.go new file mode 100644 index 0000000..b9ae8e8 --- /dev/null +++ b/app/db/db_file.go @@ -0,0 +1,33 @@ +package db + +import ( + "applet/app/db/model" + "applet/app/utils/logx" + + "xorm.io/xorm" +) + +// 通过文件名目录与文件名查找文件 +func FileGetByPFidAndName(Db *xorm.Engine, dirId, fname string) (*model.SysFile, error) { + var f model.SysFile + if has, err := Db.Where("parent_fid = ? AND show_name = ?", dirId, fname).Get(&f); !has || err != nil { + return nil, logx.Warn(err) + } + return &f, nil +} + +// 插入文件信息 +func FileInsert(Db *xorm.Engine, f *model.SysFile) error { + if _, err := Db.InsertOne(f); err != nil { + return logx.Warn(err) + } + return nil +} + +// 文件信息更新 +func FileUpdate(Db *xorm.Engine, f *model.SysFile) error { + if _, err := Db.Where("`fid` = ?", f.Fid).Update(f); err != nil { + return logx.Warn(err) + } + return nil +} diff --git a/app/db/db_good.go b/app/db/db_good.go index f862099..fad6e75 100644 --- a/app/db/db_good.go +++ b/app/db/db_good.go @@ -20,6 +20,9 @@ func GetStoreGoods(eg *xorm.Engine, req map[string]string) (*[]model.CommunityTe if req["store_type"] != "" { sess.And("store_type=?", req["store_type"]) } + if req["is_up"] != "" { + sess.And("state=?", 0) + } if req["start_time"] != "" { sess.And("create_at>=?", req["start_time"]) } diff --git a/app/db/db_good_cate.go b/app/db/db_good_cate.go index c334b3a..f96b2d0 100644 --- a/app/db/db_good_cate.go +++ b/app/db/db_good_cate.go @@ -6,6 +6,14 @@ import ( "xorm.io/xorm" ) +func GetGoodsCateAllArg(eg *xorm.Engine, arg map[string]string) *[]model.CommunityTeamCate { + var data []model.CommunityTeamCate + err := eg.Where("uid=? and store_type=?", arg["uid"], arg["store_type"]).OrderBy("sort desc,id desc").Find(&data) + if err != nil { + return nil + } + return &data +} func GetGoodsCateAll(eg *xorm.Engine) *[]model.CommunityTeamCate { var data []model.CommunityTeamCate err := eg.Where("uid=0").OrderBy("sort desc,id desc").Find(&data) diff --git a/app/db/db_order.go b/app/db/db_order.go index 927e916..bb0e4f1 100644 --- a/app/db/db_order.go +++ b/app/db/db_order.go @@ -85,7 +85,6 @@ func GetStoreOrderList(eg *xorm.Engine, req md.StoreOrder, parent_uid int) (*[]m if req.Oid != "" { sess.And("oid like ?", "%"+req.Oid+"%") } - if req.StoreName != "" { var store []model.CommunityTeamStore eg.Where("name like ?", "%"+req.StoreName+"%").Find(&store) diff --git a/app/db/db_store_audit.go b/app/db/db_store_audit.go new file mode 100644 index 0000000..578de65 --- /dev/null +++ b/app/db/db_store_audit.go @@ -0,0 +1,15 @@ +package db + +import ( + "applet/app/db/model" + "xorm.io/xorm" +) + +func StoreAuditByUid(eg *xorm.Engine, uid int) *model.CommunityTeamStoreAudit { + var data model.CommunityTeamStoreAudit + get, err := eg.Where("uid=?", uid).Get(&data) + if get == false || err != nil { + return nil + } + return &data +} diff --git a/app/db/db_user.go b/app/db/db_user.go index 82310a8..eeb66b1 100644 --- a/app/db/db_user.go +++ b/app/db/db_user.go @@ -386,7 +386,14 @@ func UpdateUserFinValid() { func UserDelete(Db *xorm.Engine, uid interface{}) (int64, error) { return Db.Where("uid = ?", uid).Delete(model.User{}) } - +func UserFindByPhoneOrNickname(Db *xorm.Engine, mobile string) (*model.User, error) { + var m model.User + if has, err := Db.Where("(phone = ? or nickname=?) AND delete_at = 0", mobile, mobile). + Get(&m); err != nil || has == false { + return nil, err + } + return &m, nil +} func UserDeleteWithSess(sess *xorm.Session, uid interface{}) (int64, error) { return sess.Where("uid = ?", uid).Delete(model.User{}) } diff --git a/app/db/db_user_store_activity.go b/app/db/db_user_store_activity.go new file mode 100644 index 0000000..750074b --- /dev/null +++ b/app/db/db_user_store_activity.go @@ -0,0 +1,35 @@ +package db + +import ( + "applet/app/db/model" + "xorm.io/xorm" +) + +func GetUserStoreActivity(eg *xorm.Engine, types string, uid int) *[]model.UserStoreActivity { + var data []model.UserStoreActivity + sess := eg.Where("type=?", types) + if uid > 0 { + sess.And("uid=?", uid) + } + err := sess.OrderBy("sort desc,id asc").Find(&data) + if err != nil { + return nil + } + return &data +} +func GetUserStoreActivityByType(eg *xorm.Engine, types string) *[]model.UserStoreActivity { + var data []model.UserStoreActivity + err := eg.Where("type=?", types).OrderBy("sort desc,id asc").Find(&data) + if err != nil { + return nil + } + return &data +} +func GetUserStoreActivityById(eg *xorm.Engine, id string) *model.UserStoreActivity { + var data model.UserStoreActivity + get, err := eg.Where("id=?", id).Get(&data) + if get == false || err != nil { + return nil + } + return &data +} diff --git a/app/db/model/community_team_store_audit.go b/app/db/model/community_team_store_audit.go new file mode 100644 index 0000000..c3861fa --- /dev/null +++ b/app/db/model/community_team_store_audit.go @@ -0,0 +1,30 @@ +package model + +import ( + "time" +) + +type CommunityTeamStoreAudit struct { + Id int `json:"id" xorm:"not null pk autoincr INT(11)"` + Uid int `json:"uid" xorm:"default 0 INT(11)"` + Lat string `json:"lat" xorm:"default 0.000000 comment('纬度') DECIMAL(30,6)"` + Lng string `json:"lng" xorm:"default 0.000000 comment('经度') DECIMAL(30,6)"` + Address string `json:"address" xorm:"default '' comment('详细地址') VARCHAR(255)"` + CreateAt time.Time `json:"create_at" xorm:"DATETIME"` + UpdateAt time.Time `json:"update_at" xorm:"DATETIME"` + State int `json:"state" xorm:"default 0 INT(1)"` + Name string `json:"name" xorm:"default '' VARCHAR(255)"` + Province string `json:"province" xorm:"comment('省级的名称') VARCHAR(255)"` + City string `json:"city" xorm:"comment('市级的名称') VARCHAR(255)"` + District string `json:"district" xorm:"comment('县,区名称') VARCHAR(255)"` + Phone string `json:"phone" xorm:"default '' VARCHAR(255)"` + ProvinceId int `json:"province_id" xorm:"default 0 comment('省级的名称') INT(11)"` + CityId int `json:"city_id" xorm:"default 0 comment('市级的名称') INT(11)"` + DistrictId int `json:"district_id" xorm:"default 0 comment('县,区名称') INT(11)"` + BusinessLicenseImg string `json:"business_license_img" xorm:"VARCHAR(255)"` + UserName string `json:"user_name" xorm:"VARCHAR(255)"` + IdcardHeadImg string `json:"idcard_head_img" xorm:"VARCHAR(255)"` + IdcardBadgeImg string `json:"idcard_badge_img" xorm:"VARCHAR(255)"` + AccountImg string `json:"account_img" xorm:"VARCHAR(255)"` + Info string `json:"info" xorm:"VARCHAR(255)"` +} diff --git a/app/db/model/sys_file.go b/app/db/model/sys_file.go new file mode 100644 index 0000000..1324692 --- /dev/null +++ b/app/db/model/sys_file.go @@ -0,0 +1,21 @@ +package model + +type SysFile struct { + Fid int64 `json:"fid" xorm:"not null pk autoincr BIGINT(20)"` + ParentFid int64 `json:"parent_fid" xorm:"not null default 0 comment('父目录id') index BIGINT(20)"` + FileType int `json:"file_type" xorm:"not null default 1 comment('0目录,1文件') TINYINT(1)"` + Uid int `json:"uid" xorm:"not null default 0 comment('上传用户ID,0为管理员') INT(10)"` + ShowName string `json:"show_name" xorm:"not null default '' comment('显示名字') index VARCHAR(128)"` + SaveName string `json:"save_name" xorm:"not null default '' comment('服务器保存名字') VARCHAR(128)"` + Ext string `json:"ext" xorm:"not null default '' comment('文件后缀') VARCHAR(8)"` + Hash string `json:"hash" xorm:"not null default '' comment('哈希值') VARCHAR(32)"` + Mime string `json:"mime" xorm:"not null default '' comment('Mime类型') VARCHAR(64)"` + Provider string `json:"provider" xorm:"not null default '' comment('供应商,qiniu,aliyun,local') VARCHAR(16)"` + Width int `json:"width" xorm:"not null default 0 comment('宽,px') INT(10)"` + Height int `json:"height" xorm:"not null default 0 comment('高,px') INT(10)"` + Bucket string `json:"bucket" xorm:"not null default '' comment('上传空间') VARCHAR(32)"` + FileSize int64 `json:"file_size" xorm:"not null default 0 comment('文件大小,byte') BIGINT(20)"` + CreateAt int `json:"create_at" xorm:"not null default 0 comment('上传时间') INT(10)"` + Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(100)"` + State int `json:"state" xorm:"not null default 0 comment('状态0未锁定,1锁定,锁定状态不能进行删除') TINYINT(1)"` +} diff --git a/app/db/model/user_store_activity.go b/app/db/model/user_store_activity.go new file mode 100644 index 0000000..a79e5a2 --- /dev/null +++ b/app/db/model/user_store_activity.go @@ -0,0 +1,19 @@ +package model + +import ( + "time" +) + +type UserStoreActivity struct { + Id int `json:"id" xorm:"not null pk autoincr INT(11)"` + Title string `json:"title" xorm:"VARCHAR(255)"` + Sort int `json:"sort" xorm:"default 0 INT(11)"` + Img string `json:"img" xorm:"VARCHAR(255)"` + Time time.Time `json:"time" xorm:"DATETIME"` + Label string `json:"label" xorm:"VARCHAR(255)"` + LinkType int `json:"link_type" xorm:"default 0 INT(1)"` + Content string `json:"content" xorm:"TEXT"` + Url string `json:"url" xorm:"VARCHAR(255)"` + Type string `json:"type" xorm:"VARCHAR(255)"` + Uid int `json:"uid" xorm:"default 0 INT(11)"` +} diff --git a/app/hdl/hdl_file_img_callback.go b/app/hdl/hdl_file_img_callback.go new file mode 100644 index 0000000..57562b6 --- /dev/null +++ b/app/hdl/hdl_file_img_callback.go @@ -0,0 +1,57 @@ +package hdl + +import ( + "applet/app/utils" + "fmt" + "github.com/gin-gonic/gin" + + "applet/app/e" + "applet/app/md" + "applet/app/svc" +) + +// 文件七牛云回调确认 +func FileImgCallback(c *gin.Context) { + masterID := c.Query("master_id") + c.Set("mid", masterID) + var args md.FileCallback + err := c.ShouldBindJSON(&args) + utils.FilePutContents("qiniuyun", masterID) + + if err != nil { + utils.FilePutContents("qiniuyun", utils.SerializeStr(err)) + fmt.Println("七牛云上传回调参数错误:>>>>>>>>>>", err) + e.OutErr(c, 200, e.ERR_INVALID_ARGS) + return + } + fmt.Println("七牛云上传回调参数:>>>>>>>>>>", utils.SerializeStr(args)) + if err = svc.FileSave(c, &args); err != nil { + utils.FilePutContents("qiniuyun", utils.SerializeStr(err)) + + fmt.Println("七牛云上传回调保存文件错误:>>>>>>>>>>", err) + e.OutErr(c, 200, err) + return + } + + res := map[string]interface{}{ + "name": args.FileName, + "fname": getFileNameURL(c, args.FileName), + "fsize": args.FileSize, + "provider": args.Provider, + "uid": args.Uid, + "dir_id": args.DirId, + "w": args.Width, + "h": args.Height, + } + e.OutSuc(c, &res, nil) +} + +func getFileNameURL(c *gin.Context, filename string) string { + protocol := svc.SysCfgGet(c, "file_bucket_scheme") + domain := svc.SysCfgGet(c, "file_bucket_host") + imgformat := svc.SysCfgGet(c, "file_avatar_thumbnail") + if protocol != "" && domain != "" && imgformat != "" { + return protocol + "://" + domain + "/" + filename + } + return filename +} diff --git a/app/hdl/hdl_file_img_req_upload.go b/app/hdl/hdl_file_img_req_upload.go new file mode 100644 index 0000000..c7dd759 --- /dev/null +++ b/app/hdl/hdl_file_img_req_upload.go @@ -0,0 +1,95 @@ +package hdl + +import ( + "applet/app/e" + "applet/app/md" + "applet/app/svc" + "applet/app/utils" + "applet/app/utils/logx" + "github.com/gin-gonic/gin" +) + +// 请求上传图片 +func ImgReqUpload(c *gin.Context) { + user := svc.GetUser(c) + uid := utils.IntToStr(user.Info.Uid) + // 文件名名称 + var args struct { + Dir string `json:"dir"` + FileName string `json:"file_name"` + FileSize int64 `json:"file_size"` // 文件大小, 单位byte + } + if err := c.ShouldBindJSON(&args); err != nil || args.FileSize < 1 || args.FileName == "" { + logx.Warn(err) + e.OutErr(c, e.ERR_INVALID_ARGS) + return + } + // 限制用户上传目录 + if _, ok := md.FileUserDir[args.Dir]; !ok { + e.OutErr(c, e.ERR_FORBIDEN) + return + } + scheme := "http" + if c.Request.TLS != nil { + scheme = "https" + } + // 拼装回调地址 + callbackUrl := scheme + "://" + c.Request.Host + "/api/v1/file/img/callback?master_id=" + c.GetString("mid") + utils.FilePutContents("qiniuyun", callbackUrl) + //fmt.Println(callbackUrl) + // callbackUrl = "http://120.55.83.222/raw.php" + res, err := svc.ImgReqUpload(c, uid, args.Dir, args.FileName, callbackUrl, args.FileSize) + if err != nil { + e.OutErr(c, 400, err) + return + } + my := utils.SerializeStr(res) + var my1 map[string]interface{} + utils.Unserialize([]byte(my), &my1) + if c.GetHeader("Platform") == md.PLATFORM_WX_APPLET || c.GetHeader("Platform") == md.PLATFORM_TIKTOK_APPLET || c.GetHeader("Platform") == md.PLATFORM_TOUTIAO_APPLET || c.GetHeader("Platform") == md.PLATFORM_BAIDU_APPLET || c.GetHeader("Platform") == md.PLATFORM_ALIPAY_APPLET { + my1["host"] = "https://api.zhiyingos.com/api/v1/proxy/upload" //官方页面才有白名单 + } + e.OutSuc(c, my1, nil) +} + +// 请求上传图片 +func ImgReqUploadNoUser(c *gin.Context) { + // 文件名名称 + var args struct { + Dir string `json:"dir"` + FileName string `json:"file_name"` + FileSize int64 `json:"file_size"` // 文件大小, 单位byte + } + if err := c.ShouldBindJSON(&args); err != nil || args.FileSize < 1 || args.FileName == "" { + logx.Warn(err) + e.OutErr(c, e.ERR_INVALID_ARGS) + return + } + // 限制用户上传目录 + if _, ok := md.FileUserDir[args.Dir]; !ok { + e.OutErr(c, e.ERR_FORBIDEN) + return + } + scheme := "http" + if c.Request.TLS != nil { + scheme = "https" + } + // 拼装回调地址 + callbackUrl := scheme + "://" + c.Request.Host + "/api/v1/file/img/callback?master_id=" + c.GetString("mid") + utils.FilePutContents("qny", callbackUrl) + //fmt.Println(callbackUrl) + // callbackUrl = "http://120.55.83.222/raw.php" + res, err := svc.ImgReqUpload(c, "", args.Dir, args.FileName, callbackUrl, args.FileSize) + if err != nil { + e.OutErr(c, 400, err) + return + } + my := utils.SerializeStr(res) + var my1 map[string]interface{} + utils.Unserialize([]byte(my), &my1) + domainApiBase := svc.GetWebSiteDomainInfoOfficial(c, "api") + if c.GetHeader("Platform") == md.PLATFORM_WX_APPLET || c.GetHeader("Platform") == md.PLATFORM_TIKTOK_APPLET || c.GetHeader("Platform") == md.PLATFORM_TOUTIAO_APPLET || c.GetHeader("Platform") == md.PLATFORM_BAIDU_APPLET || c.GetHeader("Platform") == md.PLATFORM_ALIPAY_APPLET { + my1["host"] = domainApiBase + "/api/v1/proxy/upload" + } + e.OutSuc(c, my1, nil) +} diff --git a/app/lib/zhimeng/api.go b/app/lib/zhimeng/api.go new file mode 100644 index 0000000..c1aef2d --- /dev/null +++ b/app/lib/zhimeng/api.go @@ -0,0 +1,66 @@ +package zhimeng + +import ( + "fmt" + "sort" + "strconv" + "time" + + "applet/app/utils" +) + +var StatusSuc int = 1 + +type ZM struct { + AK string + SK string + SMS_AK string + SMS_SK string +} + +// 智盟接口, 可以调取京东, 拼多多等 +const ZM_HOST = "http://www.izhim.com/" + +var ( + ZM_BASE_URL = ZM_HOST + "?mod=api&act=%s&ctrl=%s" + APP_KEY = "300000001" + SECRET_KEY = "95c347002b2750dbd4b6a03bd4196c18" + SMS_APP_KEY = "300000175" + SMS_SECRET_KEY = "6cf1dcd1820a576ff2cbecbe00d31df2" +) + +func Send(act, op string, args map[string]interface{}) ([]byte, error) { + router := fmt.Sprintf(ZM_BASE_URL, act, op) + // args["appkey"] = APP_KEY + args["time"] = strconv.Itoa(int(time.Now().Unix())) + args["sign"] = sign(args, args["secret_key"].(string)) + // b, _ := json.Marshal(args) + // fmt.Println(string(b)) + return utils.CurlPost(router, args, nil) +} + +// SMSend is 发送短信用的key 和签名 +func SMSend(act, op, key, secret string, args map[string]interface{}) ([]byte, error) { + router := fmt.Sprintf(ZM_BASE_URL, act, op) + args["appkey"] = key + args["time"] = strconv.Itoa(int(time.Now().Unix())) + args["sign"] = sign(args, secret) + fmt.Println("====短信==", router, args) + return utils.CurlPost(router, args, nil) +} + +func sign(m map[string]interface{}, SK string) string { + // key sort + keys := make([]string, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + sort.Strings(keys) + str := "" + for _, k := range keys { + str += k + utils.AnyToString(m[k]) + } + // merge string + str = SK + str + SK + "方诺科技" + return utils.Md5(str) +} diff --git a/app/lib/zhimeng/sdk.go b/app/lib/zhimeng/sdk.go new file mode 100644 index 0000000..ade00d8 --- /dev/null +++ b/app/lib/zhimeng/sdk.go @@ -0,0 +1,151 @@ +package zhimeng + +import ( + "applet/app/utils/logx" + "encoding/json" + "errors" + "fmt" + "strings" + + "github.com/shopspring/decimal" + "github.com/tidwall/gjson" +) + +// SDK is zm sdk +type SDK struct { + Action string + operation string + response []byte + SmsKey string + SmsSecret string + data interface{} + err error +} + +// Init is init action +// In some condition, such as send Sms, need pass sms key and secret after 'action' +func (sdk *SDK) Init(action string, keys ...string) { + sdk.Action = action + //if keys[0] == "" || keys[1] == "" { + // sdk.err = errors.New("智盟短信未配置") + //} + if len(keys) > 1 { + sdk.SmsKey = keys[0] + sdk.SmsSecret = keys[1] + } + +} + +// SelectFunction is select api with operation +func (sdk *SDK) SelectFunction(operation string) *SDK { + sdk.operation = operation + return sdk +} + +// WithSMSArgs is SMS +func (sdk *SDK) WithSMSArgs(args map[string]interface{}) *SDK { + res, err := SMSend(sdk.Action, sdk.operation, sdk.SmsKey, sdk.SmsSecret, args) + if err != nil { + logx.Error(err) + } + sdk.response = res + return sdk +} + +// WithArgs is post data to api +func (sdk *SDK) WithArgs(args map[string]interface{}) *SDK { + // args["appkey"] = svc.SysCfgGet(c, md.KEY_CFG_ZM_AK) + // args["secret_key"] = svc.SysCfgGet(c, md.KEY_CFG_ZM_SK) + + res, err := Send(sdk.Action, sdk.operation, args) + if err != nil { + logx.Error(err) + } + // for k, v := range args { + // fmt.Printf("%s:%v \n", k, v) + // } + fmt.Println("唯品会请求", args, string(res)) + sdk.response = res + return sdk +} + +// Result is response data from api , return interface{} +func (sdk *SDK) Result() (*SDK, error) { + if sdk.err != nil { + return nil, sdk.err + } + tmp := struct { + Msg string `json:"msg"` + Success int `json:"success"` + Data interface{} `json:"data"` + }{} + if err := json.Unmarshal(sdk.response, &tmp); err != nil { + return nil, logx.Error("【Resp】" + string(sdk.response) + ", 【Error】" + err.Error()) + } + if tmp.Success != StatusSuc { + return nil, logx.Error(string(sdk.response)) + } + + if gjson.GetBytes(sdk.response, "data").String() == "[]" { + return nil, errors.New("no result") + } + + sdk.data = tmp.Data + return sdk, nil +} + +// ToInterface is data to Interface +func (sdk *SDK) ToInterface() interface{} { + return sdk.data +} + +// ToMapStringInterface is data to map[string]string +func (sdk *SDK) ToMapStringInterface(item interface{}) map[string]interface{} { + data, err := json.Marshal(item) + if err != nil { + logx.Error("ToMapStringString marshal error : " + err.Error()) + + } + m := make(map[string]interface{}) + if err = json.Unmarshal(data, &m); err != nil { + logx.Error("ToMapStringString unmarshal error : " + err.Error()) + + } + for key, v := range m { + switch v.(type) { + case int: + t, ok := v.(string) + if !ok { + logx.Warn("int convert error") + } + m[key] = t + case int32: + t, ok := v.(string) + if !ok { + logx.Warn("int32 convert error") + } + m[key] = t + case int64: + t, ok := v.(string) + if !ok { + logx.Warn("int64 convert error") + } + m[key] = t + case float64: + vstr := fmt.Sprintf("%v", v) + if strings.Contains(vstr, "e+") { + decimalNum, err := decimal.NewFromString(vstr) + if err != nil { + panic(logx.Errorf("decimal.NewFromString error, vstr:%s, err:%v", vstr, err)) + } + vstr = decimalNum.String() + } + m[key] = vstr + case nil: + m[key] = v + default: + m[key] = v + } + } + return m +} diff --git a/app/lib/zhimeng/sms_send.go b/app/lib/zhimeng/sms_send.go new file mode 100644 index 0000000..21030a4 --- /dev/null +++ b/app/lib/zhimeng/sms_send.go @@ -0,0 +1,70 @@ +package zhimeng + +import ( + "applet/app/utils" + "applet/app/utils/logx" + "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/sms" + "encoding/json" + "xorm.io/xorm" +) + +// 查询数量 +func SmsNum(engine *xorm.Engine, dbName, smsType, appKey, appSecret string) (int, error) { + if smsType == "1" { //新的 + num := sms.SmsNumGetSmsNum(engine, "putong", dbName) + return num, nil + } + params := map[string]interface{}{ + "appkey": appKey, + "secret_key": appSecret, + } + resp, err := Send("send_msg", "msg_num", params) + if err != nil { + return 0, logx.Warn(err) + } + var tmp struct { + Msg string `json:"msg"` + Success int `json:"success"` + Data struct { + Count string `json:"count"` + } `json:"data"` + } + if err = json.Unmarshal(resp, &tmp); err != nil { + return 0, logx.Warn("[resp]: " + string(resp) + ", [err]:" + err.Error()) + } + return utils.StrToInt(tmp.Data.Count), nil +} + +func SmsToSend(engine *xorm.Engine, dbName, smsType, appKey, appSecret, content, phone string) (int, error) { + if smsType == "1" { //新的 + args := map[string]interface{}{ + "mobile": phone, + "content": content, + "sms_type": "putong", + "uid": dbName, + } + err := sms.SmsSend(engine, args) + if err != nil { + return 0, err + } + return 1, nil + } + params := map[string]interface{}{ + "appkey": appKey, + "secret_key": appSecret, + "mobile": phone, + "content": content, + } + resp, err := Send("send_msg", "msg_doing", params) + if err != nil { + return 0, logx.Warn(err) + } + var tmp struct { + Msg string `json:"msg"` + Success int `json:"success"` + } + if err = json.Unmarshal(resp, &tmp); err != nil { + return 0, logx.Warn("[resp]: " + string(resp) + ", [err]:" + err.Error()) + } + return tmp.Success, nil +} diff --git a/app/md/cfg_key.go b/app/md/cfg_key.go index 5637f6f..0e847cc 100644 --- a/app/md/cfg_key.go +++ b/app/md/cfg_key.go @@ -8,4 +8,16 @@ const ( KEY_CFG_CRON_COMMUNITY_TEAM_ORDER_STORE_SETTLE = "community_team_cron_order_store_settle" KEY_CFG_CRON_COMMUNITY_TEAM_ORDER_SETTLE = "community_team_cron_order_settle" KEY_CFG_CRON_COMMUNITY_TEAM_ORDER_COMMISSION = "community_team_cron_order_commission" + + // 文件缓存的key + KEY_CFG_FILE_PVD = "file_provider" // 文件供应商 + KEY_CFG_FILE_BUCKET = "file_bucket" + KEY_CFG_FILE_REGION = "file_bucket_region" + KEY_CFG_FILE_HOST = "file_bucket_host" + KEY_CFG_FILE_SCHEME = "file_bucket_scheme" + KEY_CFG_FILE_AK = "file_access_key" + KEY_CFG_FILE_SK = "file_secret_key" + KEY_CFG_FILE_MAX_SIZE = "file_user_upload_max_size" + KEY_CFG_FILE_EXT = "file_ext" + KEY_CFG_FILE_AVATAR_THUMBNAIL = "file_avatar_thumbnail" // 默认头像缩略图参数,宽高120px,格式webp. ) diff --git a/app/md/file.go b/app/md/file.go new file mode 100644 index 0000000..0418fa5 --- /dev/null +++ b/app/md/file.go @@ -0,0 +1,62 @@ +package md + +// 用户拥有上传权限的目录, 目录ID + +const ( + FILE_DIR_FEEDBACK = "feedback" + FILE_DIR_AVATAR = "avatar" + FILE_DIR_QRCODE = "qrcode" + FILE_DIR_STYLE = "style" + FILE_DIR_O2O = "O2OStore" + FILE_DIR_MALL_AFTER_SALE = "Proprietary_After_Service" + FILE_DIR_IMGREWARD = "img_reward" + FILE_DOCTOR = "doctor" +) + +var ( + FileUserDir = map[string]string{ + FILE_DIR_FEEDBACK: "4", // 用户反馈 + FILE_DIR_AVATAR: "5", // 用户头像 + FILE_DIR_QRCODE: "6", // 用户微信二维码 + FILE_DIR_STYLE: "7", // 用户样式 + FILE_DIR_O2O: "8", //O2O商家上传 + FILE_DIR_MALL_AFTER_SALE: "9", // 售后图片上传 + FILE_DIR_IMGREWARD: "10", //拍立返 + FILE_DOCTOR: "11", //数字医生 + } +) + +// 文件回调信息 +type FileCallback struct { + Uid string `json:"uid"` + DirId string `json:"dir_id"` + Provider string `json:"provider"` // 供应商 + FileName string `json:"fname"` // 原文件名 + FileSize string `json:"fsize"` + Hash string `json:"hash"` + Bucket string `json:"bucket"` + Mime string `json:"mime"` + Width string `json:"w,omitempty"` + Height string `json:"h,omitempty"` + Time string `json:"time"` // 默认一个小时内要上传完毕,否则超时 + Sign string `json:"sign"` // 签名 +} + +type FileList struct { + Path string `json:"path"` + DirId int `json:"dir_id"` + FileName string `json:"f_name"` // 显示名称 + StgName string `json:"stg_name"` // 存储名字 + Ext string `json:"ext"` // 后缀名, png,jpg等 + FileSize string `json:"f_size"` + Provider string `json:"provider"` // 存储供应商 + Hash string `json:"hash"` + Bucket string `json:"bucket"` + Width int `json:"w"` + Height int `json:"h"` + Mime string `json:"mime"` + IsAdm bool `json:"is_adm"` //是否管理后台上传 + IsDir bool `json:"is_dir"` //是否文件夹 + CreateAt int `json:"create_at"` + Url string `json:"url"` +} diff --git a/app/md/md_store.go b/app/md/md_store.go index 0b253e6..09ed6d7 100644 --- a/app/md/md_store.go +++ b/app/md/md_store.go @@ -1,6 +1,8 @@ package md -import "applet/app/db/model" +import ( + "applet/app/db/model" +) type Store struct { P string `json:"p"` @@ -35,3 +37,29 @@ type StoreOrderTotal struct { type StoreOrderDetail struct { Oid string `json:"oid"` } + +// Register is 注册 postbody +type Register struct { + Mobile string `json:"mobile"` + Captcha string `json:"captcha"` + Type string `json:"type"` + Zone string `json:"zone"` + PicCode string `json:"pic_code"` + PicCodeId string `json:"pic_code_id"` +} +type CommunityTeamStore struct { + Lat string `json:"lat" xorm:"default 0.000000 comment('纬度') DECIMAL(30,6)"` + Lng string `json:"lng" xorm:"default 0.000000 comment('经度') DECIMAL(30,6)"` + Address string `json:"address" xorm:"comment('详细地址') VARCHAR(255)"` + WorkState string `json:"work_state" xorm:"default 0 comment('0营业中 1休息中') INT(1)"` + Name string `json:"name" xorm:"VARCHAR(255)"` + Province string `json:"province" xorm:"comment('省级的名称') VARCHAR(255)"` + City string `json:"city" xorm:"comment('市级的名称') VARCHAR(255)"` + District string `json:"district" xorm:"comment('县,区名称') VARCHAR(255)"` + Timer string `json:"timer" xorm:"comment('') VARCHAR(255)"` + Phone string `json:"phone" xorm:"comment('') VARCHAR(255)"` + Logo string `json:"logo" xorm:"comment('') VARCHAR(255)"` + ProvinceId string `json:"province_id" xorm:"comment('省级的名称') INT(11)"` + CityId string `json:"city_id" xorm:"comment('市级的名称') INT(11)"` + DistrictId string `json:"district_id" xorm:"comment('县,区名称') INT(11)"` +} diff --git a/app/md/store_audit.go b/app/md/store_audit.go new file mode 100644 index 0000000..fc1020b --- /dev/null +++ b/app/md/store_audit.go @@ -0,0 +1,22 @@ +package md + +type CommunityTeamStoreAudit struct { + Lat string `json:"lat" xorm:"default 0.000000 comment('纬度') DECIMAL(30,6)"` + Lng string `json:"lng" xorm:"default 0.000000 comment('经度') DECIMAL(30,6)"` + Address string `json:"address" xorm:"default '' comment('详细地址') VARCHAR(255)"` + State string `json:"state" xorm:"default 0 INT(1)"` + Name string `json:"name" xorm:"default '' VARCHAR(255)"` + Province string `json:"province" xorm:"comment('省级的名称') VARCHAR(255)"` + City string `json:"city" xorm:"comment('市级的名称') VARCHAR(255)"` + District string `json:"district" xorm:"comment('县,区名称') VARCHAR(255)"` + Phone string `json:"phone" xorm:"default '' VARCHAR(255)"` + ProvinceId string `json:"province_id" xorm:"default 0 comment('省级的名称') INT(11)"` + CityId string `json:"city_id" xorm:"default 0 comment('市级的名称') INT(11)"` + DistrictId string `json:"district_id" xorm:"default 0 comment('县,区名称') INT(11)"` + BusinessLicenseImg string `json:"business_license_img" xorm:"VARCHAR(255)"` + UserName string `json:"user_name" xorm:"VARCHAR(255)"` + IdcardHeadImg string `json:"idcard_head_img" xorm:"VARCHAR(255)"` + IdcardBadgeImg string `json:"idcard_badge_img" xorm:"VARCHAR(255)"` + AccountImg string `json:"account_img" xorm:"VARCHAR(255)"` + Info string `json:"info" xorm:"VARCHAR(255)"` +} diff --git a/app/router/router.go b/app/router/router.go index 3e5a953..b82bfdb 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -5,6 +5,7 @@ import ( "applet/app/cfg" "applet/app/hdl" "applet/app/mw" + storeHdl "applet/app/store/hdl" _ "applet/docs" "github.com/gin-gonic/gin" swaggerFiles "github.com/swaggo/files" @@ -50,9 +51,13 @@ func Init() *gin.Engine { return r } func routeCommunityTeamAgent(r *gin.RouterGroup) { + // 文件上传确认回调, 不校验设备等头部信息 + r.POST("/file/img/callback", agentHdl.FileImgCallback) r.Use(mw.DB) // 下面接口再根据mid 获取数据库名 r.POST("/login", agentHdl.Login) r.Use(mw.AuthJWT) + // 文件上传 + r.POST("/img/upload", agentHdl.ImgReqUpload) r.GET("/user", agentHdl.User) r.POST("/service/file/upload", agentHdl.ServiceFileUpload) r.GET("/wechat/base", agentHdl.WechatBase) @@ -76,7 +81,38 @@ func routeCommunityTeamAgent(r *gin.RouterGroup) { } func routeCommunityTeamOwnStore(r *gin.RouterGroup) { + r.POST("/file/img/callback", storeHdl.FileImgCallback) + r.Use(mw.DB) // 下面接口再根据mid 获取数据库名 + r.POST("/login", storeHdl.Login) + r.POST("/login/send_sms", storeHdl.LoginSendSms) + r.POST("/login/fast_in", storeHdl.LoginFastIn) + r.Use(mw.AuthJWT) + r.POST("/img/upload", storeHdl.ImgReqUpload) + r.GET("/user", storeHdl.User) + r.GET("/base", storeHdl.Base) + r.GET("/base/set", storeHdl.BaseSet) + r.GET("/info", storeHdl.UserStoreInfo) + r.POST("/info/set", storeHdl.UserStoreInfoSet) + r.POST("/banner/save", storeHdl.UserStoreBannerSave) + r.POST("/banner/del", storeHdl.UserStoreBannerDel) + r.POST("/banner/detail", storeHdl.UserStoreBannerDetail) + r.POST("/banner", storeHdl.UserStoreBanner) + r.GET("/audit/info", storeHdl.AuditInfo) + r.POST("/audit/doing", storeHdl.AuditDoing) + r.POST("/store/order", storeHdl.UserStoreOrder) + r.POST("/store/order/detail", storeHdl.UserStoreOrderDetail) + r.POST("/goods/list", storeHdl.Goods) + r.POST("/goods/save", storeHdl.GoodsSave) + r.POST("/goods/detail", storeHdl.GoodsDetail) + r.POST("/goods/del", storeHdl.GoodsDel) + r.POST("/goods/cate/list", storeHdl.GoodsCate) + r.POST("/goods/cate/save", storeHdl.GoodsCateSave) + r.POST("/goods/cate/show", storeHdl.GoodsCateShow) + r.POST("/goods/cate/del", storeHdl.GoodsCateDel) + r.POST("/agent/goods/list", storeHdl.AgentGoods) + r.POST("/agent/goods/detail", storeHdl.AgentGoodsDetail) + r.POST("/agent/goods/copy", storeHdl.AgentGoodsCopy) } func routeCommunityTeam(r *gin.RouterGroup) { r.Use(mw.DB) // 下面接口再根据mid 获取数据库名 diff --git a/app/store/hdl/hdl_agent_goods.go b/app/store/hdl/hdl_agent_goods.go new file mode 100644 index 0000000..82cabe2 --- /dev/null +++ b/app/store/hdl/hdl_agent_goods.go @@ -0,0 +1,17 @@ +package hdl + +import ( + "applet/app/store/svc" + "github.com/gin-gonic/gin" +) + +func AgentGoods(c *gin.Context) { + svc.AgentGoods(c) +} + +func AgentGoodsCopy(c *gin.Context) { + svc.AgentGoodsCopy(c) +} +func AgentGoodsDetail(c *gin.Context) { + svc.AgentGoodsDetail(c) +} diff --git a/app/store/hdl/hdl_audit.go b/app/store/hdl/hdl_audit.go new file mode 100644 index 0000000..1ef2d66 --- /dev/null +++ b/app/store/hdl/hdl_audit.go @@ -0,0 +1,13 @@ +package hdl + +import ( + "applet/app/store/svc" + "github.com/gin-gonic/gin" +) + +func AuditInfo(c *gin.Context) { + svc.AuditInfo(c) +} +func AuditDoing(c *gin.Context) { + svc.AuditDoing(c) +} diff --git a/app/store/hdl/hdl_file_img_callback.go b/app/store/hdl/hdl_file_img_callback.go new file mode 100644 index 0000000..57562b6 --- /dev/null +++ b/app/store/hdl/hdl_file_img_callback.go @@ -0,0 +1,57 @@ +package hdl + +import ( + "applet/app/utils" + "fmt" + "github.com/gin-gonic/gin" + + "applet/app/e" + "applet/app/md" + "applet/app/svc" +) + +// 文件七牛云回调确认 +func FileImgCallback(c *gin.Context) { + masterID := c.Query("master_id") + c.Set("mid", masterID) + var args md.FileCallback + err := c.ShouldBindJSON(&args) + utils.FilePutContents("qiniuyun", masterID) + + if err != nil { + utils.FilePutContents("qiniuyun", utils.SerializeStr(err)) + fmt.Println("七牛云上传回调参数错误:>>>>>>>>>>", err) + e.OutErr(c, 200, e.ERR_INVALID_ARGS) + return + } + fmt.Println("七牛云上传回调参数:>>>>>>>>>>", utils.SerializeStr(args)) + if err = svc.FileSave(c, &args); err != nil { + utils.FilePutContents("qiniuyun", utils.SerializeStr(err)) + + fmt.Println("七牛云上传回调保存文件错误:>>>>>>>>>>", err) + e.OutErr(c, 200, err) + return + } + + res := map[string]interface{}{ + "name": args.FileName, + "fname": getFileNameURL(c, args.FileName), + "fsize": args.FileSize, + "provider": args.Provider, + "uid": args.Uid, + "dir_id": args.DirId, + "w": args.Width, + "h": args.Height, + } + e.OutSuc(c, &res, nil) +} + +func getFileNameURL(c *gin.Context, filename string) string { + protocol := svc.SysCfgGet(c, "file_bucket_scheme") + domain := svc.SysCfgGet(c, "file_bucket_host") + imgformat := svc.SysCfgGet(c, "file_avatar_thumbnail") + if protocol != "" && domain != "" && imgformat != "" { + return protocol + "://" + domain + "/" + filename + } + return filename +} diff --git a/app/store/hdl/hdl_file_img_req_upload.go b/app/store/hdl/hdl_file_img_req_upload.go new file mode 100644 index 0000000..711733c --- /dev/null +++ b/app/store/hdl/hdl_file_img_req_upload.go @@ -0,0 +1,95 @@ +package hdl + +import ( + "applet/app/e" + "applet/app/md" + "applet/app/svc" + "applet/app/utils" + "applet/app/utils/logx" + "github.com/gin-gonic/gin" +) + +// 请求上传图片 +func ImgReqUpload(c *gin.Context) { + user := svc.GetUser(c) + uid := utils.IntToStr(user.Info.Uid) + // 文件名名称 + var args struct { + Dir string `json:"dir"` + FileName string `json:"file_name"` + FileSize int64 `json:"file_size"` // 文件大小, 单位byte + } + if err := c.ShouldBindJSON(&args); err != nil || args.FileSize < 1 || args.FileName == "" { + logx.Warn(err) + e.OutErr(c, e.ERR_INVALID_ARGS) + return + } + // 限制用户上传目录 + if _, ok := md.FileUserDir[args.Dir]; !ok { + e.OutErr(c, e.ERR_FORBIDEN) + return + } + scheme := "http" + if c.Request.TLS != nil { + scheme = "https" + } + // 拼装回调地址 + callbackUrl := scheme + "://" + c.Request.Host + "/api/v1/communityTeam/ownStore/file/img/callback?master_id=" + c.GetString("mid") + utils.FilePutContents("qiniuyun", callbackUrl) + //fmt.Println(callbackUrl) + // callbackUrl = "http://120.55.83.222/raw.php" + res, err := svc.ImgReqUpload(c, uid, args.Dir, args.FileName, callbackUrl, args.FileSize) + if err != nil { + e.OutErr(c, 400, err) + return + } + my := utils.SerializeStr(res) + var my1 map[string]interface{} + utils.Unserialize([]byte(my), &my1) + if c.GetHeader("Platform") == md.PLATFORM_WX_APPLET || c.GetHeader("Platform") == md.PLATFORM_TIKTOK_APPLET || c.GetHeader("Platform") == md.PLATFORM_TOUTIAO_APPLET || c.GetHeader("Platform") == md.PLATFORM_BAIDU_APPLET || c.GetHeader("Platform") == md.PLATFORM_ALIPAY_APPLET { + my1["host"] = "https://api.zhiyingos.com/api/v1/proxy/upload" //官方页面才有白名单 + } + e.OutSuc(c, my1, nil) +} + +// 请求上传图片 +func ImgReqUploadNoUser(c *gin.Context) { + // 文件名名称 + var args struct { + Dir string `json:"dir"` + FileName string `json:"file_name"` + FileSize int64 `json:"file_size"` // 文件大小, 单位byte + } + if err := c.ShouldBindJSON(&args); err != nil || args.FileSize < 1 || args.FileName == "" { + logx.Warn(err) + e.OutErr(c, e.ERR_INVALID_ARGS) + return + } + // 限制用户上传目录 + if _, ok := md.FileUserDir[args.Dir]; !ok { + e.OutErr(c, e.ERR_FORBIDEN) + return + } + scheme := "http" + if c.Request.TLS != nil { + scheme = "https" + } + // 拼装回调地址 + callbackUrl := scheme + "://" + c.Request.Host + "/api/v1/file/img/callback?master_id=" + c.GetString("mid") + utils.FilePutContents("qny", callbackUrl) + //fmt.Println(callbackUrl) + // callbackUrl = "http://120.55.83.222/raw.php" + res, err := svc.ImgReqUpload(c, "", args.Dir, args.FileName, callbackUrl, args.FileSize) + if err != nil { + e.OutErr(c, 400, err) + return + } + my := utils.SerializeStr(res) + var my1 map[string]interface{} + utils.Unserialize([]byte(my), &my1) + domainApiBase := svc.GetWebSiteDomainInfoOfficial(c, "api") + if c.GetHeader("Platform") == md.PLATFORM_WX_APPLET || c.GetHeader("Platform") == md.PLATFORM_TIKTOK_APPLET || c.GetHeader("Platform") == md.PLATFORM_TOUTIAO_APPLET || c.GetHeader("Platform") == md.PLATFORM_BAIDU_APPLET || c.GetHeader("Platform") == md.PLATFORM_ALIPAY_APPLET { + my1["host"] = domainApiBase + "/api/v1/proxy/upload" + } + e.OutSuc(c, my1, nil) +} diff --git a/app/store/hdl/hdl_goods.go b/app/store/hdl/hdl_goods.go new file mode 100644 index 0000000..1658539 --- /dev/null +++ b/app/store/hdl/hdl_goods.go @@ -0,0 +1,32 @@ +package hdl + +import ( + "applet/app/store/svc" + "github.com/gin-gonic/gin" +) + +func GoodsCate(c *gin.Context) { + svc.GoodsCate(c) +} +func GoodsCateSave(c *gin.Context) { + svc.GoodsCateSave(c) +} +func GoodsCateShow(c *gin.Context) { + svc.GoodsCateShow(c) +} +func GoodsCateDel(c *gin.Context) { + svc.GoodsCateDel(c) +} + +func Goods(c *gin.Context) { + svc.Goods(c) +} +func GoodsSave(c *gin.Context) { + svc.GoodsSave(c) +} +func GoodsDel(c *gin.Context) { + svc.GoodsDel(c) +} +func GoodsDetail(c *gin.Context) { + svc.GoodsDetail(c) +} diff --git a/app/store/hdl/hdl_login.go b/app/store/hdl/hdl_login.go new file mode 100644 index 0000000..0bce125 --- /dev/null +++ b/app/store/hdl/hdl_login.go @@ -0,0 +1,26 @@ +package hdl + +import ( + "applet/app/store/svc" + "github.com/gin-gonic/gin" +) + +// Login 登陆 +// @Summary 登陆 +// @Tags 登陆 +// @Description 登入 +// @Accept json +// @Produce json +// @Param req body md.FastLoginRequestBody true "请求参数" +// @Success 200 {object} md.LoginResponse "" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/v1/communityTeam/store/login [post] +func Login(c *gin.Context) { + svc.Login(c) +} +func LoginSendSms(c *gin.Context) { + svc.LoginSendSms(c) +} +func LoginFastIn(c *gin.Context) { + svc.LoginFastIn(c) +} diff --git a/app/store/hdl/hdl_store.go b/app/store/hdl/hdl_store.go new file mode 100644 index 0000000..9c081ff --- /dev/null +++ b/app/store/hdl/hdl_store.go @@ -0,0 +1,465 @@ +package hdl + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/e" + "applet/app/md" + "applet/app/svc" + "applet/app/utils" + "encoding/json" + "github.com/gin-gonic/gin" + "github.com/tidwall/gjson" + "time" +) + +// UserStoreList 门店列表 +// @Summary 门店-列表 +// @Tags 门店 +// @Description 门店-列表 +// @Accept json +// @Produce json +// @Param req body md.Store true "请求参数" +// @Success 200 {string} "" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/v1/communityTeam/ownStore/store/list [POST] +func UserStoreList(c *gin.Context) { + var arg md.Store + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + list, count := db.GetUserList(svc.MasterDb(c), arg, user.Info.Uid) + data := make([]map[string]interface{}, 0) + if list != nil { + currentMonth := utils.GetTimeRange("current_month") + for _, v := range *list { + store := v.CommunityTeamStore + tmp := map[string]interface{}{ + "uid": utils.IntToStr(v.User.Uid), + "create_at": store.CreateAt.Format("2006-01-02 15:04:05"), + "name": "", + "address": "", + "logo": "", + "order_count": "0", + "order_amount": "0", + "agent_commission": "0", + "platform_commission": "0", + "base_commission": "0", + "work_state": "", + } + count1, _ := svc.MasterDb(c).Where("store_uid=? and parent_uid=?", v.User.Uid, user.Info.Uid).In("state", []string{"1", "2"}).Count(&model.CommunityTeamOrder{}) + sum, _ := svc.MasterDb(c).Where("store_uid=? and parent_uid=? and create_at>=?", v.User.Uid, user.Info.Uid, time.Unix(currentMonth["start"], 0).Format("2006-01-02 15:04:05")).In("state", []string{"1", "2"}).Sum(&model.CommunityTeamOrder{}, "amount") + tmp["order_count"] = utils.Int64ToStr(count1) + tmp["order_amount"] = svc.GetCommissionPrec(c, utils.Float64ToStr(sum), "2", "") + tmp["name"] = store.Name + tmp["address"] = store.Address + tmp["logo"] = store.Logo + tmp["work_state"] = "营业中" + if store.WorkState == 1 { + tmp["work_state"] = "休息中" + } + tmp["agent_commission"] = store.AgentCommission + data = append(data, tmp) + } + } + res := map[string]interface{}{ + "total": count, + "list": data, + } + e.OutSuc(c, res, nil) +} + +// UserStoreSave 门店编辑 +// @Summary 门店-门店编辑 +// @Tags 门店 +// @Description 门店-门店编辑 +// @Accept json +// @Produce json +// @Param req body md.StoreSave true "请求参数" +// @Success 200 {string} "" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/v1/communityTeam/ownStore/store/save [POST] +func UserStoreSave(c *gin.Context) { + var arg md.StoreSave + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + store := db.GetUserStore(svc.MasterDb(c), utils.StrToInt(arg.Uid)) + if store == nil { + e.OutErr(c, 400, e.NewErr(400, "门店不存在")) + return + } + store.AgentCommission = arg.AgentCommission + svc.MasterDb(c).Where("id=?", store.Id).Cols("agent_commission").Update(store) + e.OutSuc(c, "success", nil) + return +} + +// UserStoreOrder 门店订单-订单管理共用一个 +// @Summary 门店-门店订单 +// @Tags 门店 +// @Description 门店-门店订单 +// @Accept json +// @Produce json +// @Param req body md.StoreOrder true "请求参数" +// @Success 200 {string} "" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/v1/communityTeam/ownStore/store/order [POST] +func UserStoreOrder(c *gin.Context) { + var arg md.StoreOrder + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + arg.StoreUid = utils.IntToStr(user.Info.Uid) + data, total, _ := db.GetStoreOrderList(svc.MasterDb(c), arg, 0) + list := make([]map[string]string, 0) + if data != nil { + stateList := []string{"待付款", "已支付", "已提货", "已取消"} + for _, v := range *data { + tmp := map[string]string{ + "oid": utils.Int64ToStr(v.Oid), + "uid": utils.IntToStr(v.Uid), + "phone": "", + "nickname": "", + "store_name": "", + "state_str": stateList[v.State], + "amount": v.Amount, + "agent_commission": v.AgentCommission, + "state": utils.IntToStr(v.State), + "create_at": v.CreateAt.Format("2006-01-02 15:04:05"), + "confirm_at": utils.Int64ToStr(v.Oid), + } + if v.ConfirmAt.IsZero() == false { + tmp["confirm_at"] = v.ConfirmAt.Format("2006-01-02 15:04:05") + } + user1, _ := db.UserFindByID(svc.MasterDb(c), v.Uid) + if user1 != nil { + tmp["phone"] = user1.Phone + tmp["nickname"] = user1.Nickname + } + store := db.GetUserStore(svc.MasterDb(c), v.StoreUid) + if store != nil { + tmp["store_name"] = store.Name + } + list = append(list, tmp) + } + } + res := map[string]interface{}{ + "total": total, + "state": []map[string]string{ + {"name": "待付款", "value": "0"}, + {"name": "已支付", "value": "1"}, + {"name": "已提货", "value": "2"}, + {"name": "已取消", "value": "3"}, + }, + "list": list, + } + e.OutSuc(c, res, nil) +} + +// UserStoreOrderDetail 门店订单详情-订单管理共用一个 +// @Summary 门店-门店订单详情 +// @Tags 门店 +// @Description 门店-门店订单详情 +// @Accept json +// @Produce json +// @Param req body md.StoreOrderDetail true "请求参数" +// @Success 200 {string} "" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/v1/communityTeam/ownStore/store/order/detail [POST] +func UserStoreOrderDetail(c *gin.Context) { + var arg md.StoreOrderDetail + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + order := db.GetOrderByOid(svc.MasterDb(c), arg.Oid) + if order == nil { + e.OutErr(c, 400, e.NewErr(400, "订单不存在")) + return + } + stateList := []string{"待付款", "已支付", "已提货", "已取消"} + payMethodStr := []string{"余额支付", "支付宝支付", "微信支付"} + orderInfoMap := make([]map[string]string, 0) + res := map[string]interface{}{ + "oid": utils.Int64ToStr(order.Oid), + "uid": utils.IntToStr(order.Uid), + "phone": order.Phone, + "nickname": "", + "store_name": "", + "memo": order.Memo, + "coupon": order.Coupon, + "code": order.Code, + "amount": order.Amount, + "all_amount": utils.Float64ToStr(utils.StrToFloat64(order.Amount) + utils.StrToFloat64(order.Coupon)), + "pay_method_str": payMethodStr[order.PayMethod], + "state_str": stateList[order.State], + "state": utils.IntToStr(order.State), + "create_at": order.CreateAt.Format("2006-01-02 15:04:05"), + "confirm_at": "", + "pay_at": "", + "order_info": orderInfoMap, + } + if order.ConfirmAt.IsZero() == false { + res["confirm_at"] = order.ConfirmAt.Format("2006-01-02 15:04:05") + } else { + res["confirm_at"] = order.Timer + if order.IsNow == 1 { + res["confirm_at"] = "立即提货" + } + } + if order.PayAt.IsZero() == false { + res["pay_at"] = order.PayAt.Format("2006-01-02 15:04:05") + } + + user, _ := db.UserFindByID(svc.MasterDb(c), order.Uid) + if user != nil { + res["nickname"] = user.Nickname + if order.Phone == "" { + res["phone"] = user.Phone + } + } + store := db.GetUserStore(svc.MasterDb(c), order.StoreUid) + if store != nil { + res["store_name"] = store.Name + } + orderInfo := db.GetOrderInfoAllEg(svc.MasterDb(c), arg.Oid) + if orderInfo != nil { + for _, v := range *orderInfo { + skuData := make([]md.Sku, 0) + json.Unmarshal([]byte(v.SkuInfo), &skuData) + skuStr := "" + for _, v1 := range skuData { + if skuStr != "" { + skuStr += ";" + } + skuStr += v1.Value + } + tmp := map[string]string{ + "sku_str": skuStr, + "goods_title": v.Title, + "goods_img": v.Img, + "num": utils.IntToStr(v.Num), + "amount": utils.Float64ToStr(float64(v.Num) * utils.StrToFloat64(v.Price)), + } + orderInfoMap = append(orderInfoMap, tmp) + } + res["order_info"] = orderInfoMap + } + + e.OutSuc(c, res, nil) + return +} + +func UserStoreInfo(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + data, _ := db.SysModFindBySkipIdentifierWithUid(c, svc.MasterDb(c), "pub.flutter.user_store", user.Info.Uid) + if data == nil { + data = &model.SysModule{ + ModName: "user_store", + Position: "user_store", + SkipIdentifier: "pub.flutter.user_store", + Title: "店铺模板", + Uid: utils.StrToInt(arg["uid"]), + State: 1, + Data: "{\"icon\":\"\",\"icon_url\":\"\",\"name\":\"\",\"store_detail_url\":\"\",\"address\":\"\",\"phone\":\"\",\"time_str\":\"\",\"notice_str\":\"\",\"banner_title\":\"\",\"activity_title\":\"\"}", + Platform: 1, + CreateAt: time.Now(), + UpdateAt: time.Now(), + } + svc.MasterDb(c).Insert(data) + } + var tmp = make(map[string]interface{}) + json.Unmarshal([]byte(data.Data), &tmp) + h5Domain := svc.GetWebSiteDomainInfo(c, "wap") + store := db.GetStoreIdEg(svc.MasterDb(c), utils.IntToStr(user.Info.Uid)) + if store != nil { + tmp["lat"] = store.Lat + tmp["lng"] = store.Lng + tmp["province"] = store.Province + tmp["city"] = store.City + tmp["district"] = store.District + tmp["province_id"] = store.ProvinceId + tmp["city_id"] = store.CityId + tmp["district_id"] = store.DistrictId + tmp["work_state"] = utils.IntToStr(store.WorkState) + } + tmp["share_url"] = h5Domain + "/#/zy-user-store/pages/store-page/index?uid=" + arg["uid"] + e.OutSuc(c, tmp, nil) + return +} +func UserStoreInfoSet(c *gin.Context) { + var arg map[string]interface{} + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + data, _ := db.SysModFindBySkipIdentifierWithUid(c, svc.MasterDb(c), "pub.flutter.user_store", user.Info.Uid) + data.Data = utils.SerializeStr(arg) + svc.MasterDb(c).Where("mod_id=?", data.ModId).Cols("data").Update(data) + store := db.GetStoreIdEg(svc.MasterDb(c), utils.IntToStr(user.Info.Uid)) + if store == nil { + store = &model.CommunityTeamStore{ + Uid: int(utils.AnyToInt64(arg["uid"])), + CreateAt: time.Now(), + UpdateAt: time.Now(), + State: 1, + } + svc.MasterDb(c).Insert(store) + } + if gjson.Get(data.Data, "address").String() != "" { + store.Address = gjson.Get(data.Data, "address").String() + } + if gjson.Get(data.Data, "lat").String() != "" { + store.Lat = gjson.Get(data.Data, "lat").String() + } + if gjson.Get(data.Data, "lng").String() != "" { + store.Lng = gjson.Get(data.Data, "lng").String() + } + if gjson.Get(data.Data, "province").String() != "" { + store.Province = gjson.Get(data.Data, "province").String() + } + if gjson.Get(data.Data, "city").String() != "" { + store.City = gjson.Get(data.Data, "city").String() + } + if gjson.Get(data.Data, "district").String() != "" { + store.District = gjson.Get(data.Data, "district").String() + } + if gjson.Get(data.Data, "province_id").String() != "" { + store.ProvinceId = utils.StrToInt(gjson.Get(data.Data, "province_id").String()) + } + if gjson.Get(data.Data, "city_id").String() != "" { + store.CityId = utils.StrToInt(gjson.Get(data.Data, "city_id").String()) + } + if gjson.Get(data.Data, "district_id").String() != "" { + store.DistrictId = utils.StrToInt(gjson.Get(data.Data, "district_id").String()) + } + if gjson.Get(data.Data, "name").String() != "" { + store.Name = gjson.Get(data.Data, "name").String() + } + if gjson.Get(data.Data, "work_state").String() != "" { + store.WorkState = utils.StrToInt(gjson.Get(data.Data, "work_state").String()) + } + if gjson.Get(data.Data, "time_str").String() != "" { + store.Timer = gjson.Get(data.Data, "time_str").String() + } + if gjson.Get(data.Data, "phone").String() != "" { + store.Phone = gjson.Get(data.Data, "phone").String() + } + if gjson.Get(data.Data, "icon_url").String() != "" { + store.Logo = gjson.Get(data.Data, "icon_url").String() + } + svc.MasterDb(c).Where("id=?", store.Id).Cols("province_id,city_id,district_id,timer,phone,logo,work_state,name,province,city,district,address,lat,lng").Update(store) + e.OutSuc(c, "success", nil) + return +} +func UserStoreBanner(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + + uid := utils.StrToInt(arg["uid"]) + activity := db.GetUserStoreActivity(svc.MasterDb(c), arg["type"], uid) + data := make([]map[string]string, 0) + if activity != nil { + scheme := svc.SysCfgGet(c, "file_bucket_scheme") + domain := svc.SysCfgGet(c, "file_bucket_host") + linkTypeStr := []string{"内链分享", "外链分享"} + for _, v := range *activity { + tmp := map[string]string{ + "id": utils.IntToStr(v.Id), + "title": v.Title, + "link_type_str": linkTypeStr[v.LinkType], + "img": v.Img, + "img_url": svc.ImageFormatWithBucket(scheme, domain, v.Img), + "label": v.Label, + "uid": utils.IntToStr(v.Uid), + } + data = append(data, tmp) + } + } + e.OutSuc(c, data, nil) + return +} + +func UserStoreBannerDetail(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + data := db.GetUserStoreActivityById(svc.MasterDb(c), arg["id"]) + if data == nil { + e.OutErr(c, 400, e.NewErr(400, "记录不存在")) + return + } + scheme := svc.SysCfgGet(c, "file_bucket_scheme") + domain := svc.SysCfgGet(c, "file_bucket_host") + res := map[string]string{ + "id": utils.IntToStr(data.Id), + "uid": utils.IntToStr(data.Uid), + "title": data.Title, + "img": data.Img, + "img_url": svc.ImageFormatWithBucket(scheme, domain, data.Img), + "label": data.Label, + "content": data.Content, + "type": data.Type, + "url": data.Url, + "link_type": utils.IntToStr(data.LinkType), + "sort": utils.IntToStr(data.Sort), + } + e.OutSuc(c, res, nil) + return +} +func UserStoreBannerSave(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + + data := model.UserStoreActivity{} + if arg["id"] == "" { + data = model.UserStoreActivity{ + Uid: utils.StrToInt(arg["uid"]), + Type: arg["type"], + Time: time.Now(), + } + svc.MasterDb(c).Insert(&data) + } else { + svc.MasterDb(c).Where("id=?", arg["id"]).Get(&data) + } + data.Label = arg["label"] + data.Img = arg["img"] + data.Title = arg["title"] + data.Content = arg["content"] + data.LinkType = utils.StrToInt(arg["link_type"]) + data.Url = arg["url"] + data.Sort = utils.StrToInt(arg["sort"]) + svc.MasterDb(c).Where("id=?", data.Id).Update(&data) + e.OutSuc(c, "success", nil) + return +} +func UserStoreBannerDel(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + svc.MasterDb(c).Where("id=?", arg["id"]).Delete(&model.UserStoreActivity{}) + e.OutSuc(c, "success", nil) + return +} diff --git a/app/store/hdl/hdl_user.go b/app/store/hdl/hdl_user.go new file mode 100644 index 0000000..d50c29f --- /dev/null +++ b/app/store/hdl/hdl_user.go @@ -0,0 +1,87 @@ +package hdl + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/e" + "applet/app/md" + "applet/app/svc" + "applet/app/utils" + "github.com/gin-gonic/gin" + "github.com/jinzhu/copier" +) + +// User 用户信息 +// @Summary 用户信息 +// @Tags 用户信息 +// @Description 用户信息 +// @Accept json +// @Produce json +// @Success 200 {string} "" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/v1/communityTeam/ownStore/user [GET] +func User(c *gin.Context) { + user := svc.GetUser(c) + res := map[string]string{ + "head_img": user.Profile.AvatarUrl, + "nickname": user.Info.Nickname, + "phone": user.Info.Phone, + "state": "0", + "info": "", + } + storeCheck := db.StoreAuditByUid(svc.MasterDb(c), user.Info.Uid) + if storeCheck != nil { + if storeCheck.State == 1 { + res["state"] = "1" + } + if storeCheck.State == 3 { + res["state"] = "3" + res["info"] = storeCheck.Info + } + } + + userParty := db.GetStoreIdEg(svc.MasterDb(c), utils.IntToStr(user.Info.Uid)) + if userParty != nil { + if userParty.State == 1 { + res["state"] = "2" + } else if storeCheck != nil && storeCheck.State == 2 { + res["state"] = "3" + } + } + e.OutSuc(c, res, nil) + return +} + +func Base(c *gin.Context) { + user := svc.GetUser(c) + store := db.GetStoreIdEg(svc.MasterDb(c), utils.IntToStr(user.Info.Uid)) + + var res = md.CommunityTeamStore{} + if store != nil { + copier.Copy(&res, &store) + res.DistrictId = utils.IntToStr(store.DistrictId) + res.CityId = utils.IntToStr(store.CityId) + res.WorkState = utils.IntToStr(store.WorkState) + res.ProvinceId = utils.IntToStr(store.ProvinceId) + } + e.OutSuc(c, res, nil) + return +} +func BaseSet(c *gin.Context) { + var arg md.CommunityTeamStore + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + store := db.GetStoreIdEg(svc.MasterDb(c), utils.IntToStr(user.Info.Uid)) + var storeData model.CommunityTeamStore + copier.Copy(&storeData, &arg) + storeData.DistrictId = utils.StrToInt(arg.DistrictId) + storeData.CityId = utils.StrToInt(arg.CityId) + storeData.WorkState = utils.StrToInt(arg.WorkState) + storeData.ProvinceId = utils.StrToInt(arg.ProvinceId) + svc.MasterDb(c).Where("id=?", store.Id).Cols("lat,lng,address,work_state,name,province,city,district,timer,phone,logo,province_id,city_id,district_id").Update(&storeData) + e.OutSuc(c, "success", nil) + return +} diff --git a/app/store/svc/svc_agent_goods.go b/app/store/svc/svc_agent_goods.go new file mode 100644 index 0000000..4bffd12 --- /dev/null +++ b/app/store/svc/svc_agent_goods.go @@ -0,0 +1,179 @@ +package svc + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/e" + "applet/app/md" + "applet/app/svc" + "applet/app/utils" + "encoding/json" + "github.com/gin-gonic/gin" + "strings" +) + +func AgentGoods(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + store := db.GetStoreIdEg(svc.MasterDb(c), utils.IntToStr(user.Info.Uid)) + arg["uid"] = utils.IntToStr(store.ParentUid) + arg["store_type"] = "2" + arg["is_up"] = "1" + cate, total := db.GetStoreGoods(svc.MasterDb(c), arg) + list := make([]map[string]string, 0) + cateData := db.GetGoodsCateAllArg(svc.MasterDb(c), arg) + cateList := make([]map[string]string, 0) + cateMap := make(map[int]string) + if cateData != nil { + for _, v := range *cateData { + tmp := map[string]string{ + "name": v.Title, "value": utils.IntToStr(v.Id), + } + cateList = append(cateList, tmp) + cateMap[v.Id] = v.Title + } + } + if cate != nil { + stateMap := []string{"上架", "下架"} + scheme, host := svc.ImageBucket(c) + for _, v := range *cate { + tmp := map[string]string{ + "id": utils.IntToStr(v.Id), + "title": v.Title, + "price": v.Price, + "info": v.Info, + "img_url": svc.ImageFormatWithBucket(scheme, host, v.Img), + "create_at": v.CreateAt.Format("2006-01-02 15:04:05"), + "cate": cateMap[v.Cid], + "state": stateMap[v.State], + } + list = append(list, tmp) + } + } + res := map[string]interface{}{ + "list": list, "total": total, "cate_list": cateList, + } + e.OutSuc(c, res, nil) + return +} +func AgentGoodsCopy(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + sess := svc.MasterDb(c).NewSession() + defer sess.Close() + sess.Begin() + var goods = make([]model.CommunityTeamGoods, 0) + sess.In("id", strings.Split(arg["ids"], ",")).Get(&goods) + for _, v := range goods { + id := v.Id + v.Id = 0 + v.Stock = 0 + v.Uid = user.Info.Uid + v.StoreType = 1 + _, err := sess.Insert(&v) + if err != nil { + sess.Rollback() + e.OutErr(c, 400, e.NewErr(400, "添加失败")) + return + } + var goodsSku = make([]model.CommunityTeamSku, 0) + sess.Where("goods_id=?", id).Get(&goodsSku) + for k1 := range goodsSku { + goodsSku[k1].SkuId = 0 + goodsSku[k1].Stock = 0 + } + _, err = sess.Insert(&goodsSku) + if err != nil { + sess.Rollback() + e.OutErr(c, 400, e.NewErr(400, "添加失败")) + return + } + } + sess.Commit() + e.OutSuc(c, "success", nil) + return +} +func AgentGoodsDetail(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + goods := db.GetGoodsById(svc.MasterDb(c), arg["id"]) + if goods == nil { + e.OutErr(c, 400, e.NewErr(400, "商品不存在")) + return + } + cateData := db.GetGoodsCateAll(svc.MasterDb(c)) + cateList := make([]map[string]string, 0) + cateMap := make(map[int]string) + if cateData != nil { + for _, v := range *cateData { + tmp := map[string]string{ + "name": v.Title, "value": utils.IntToStr(v.Id), + } + cateList = append(cateList, tmp) + cateMap[v.Id] = v.Title + } + } + stateMap := []string{"上架", "下架"} + scheme, host := svc.ImageBucket(c) + res := md.BaseGoods{ + Id: utils.IntToStr(goods.Id), + Title: goods.Title, + Cid: utils.IntToStr(goods.Cid), + CategoryName: cateMap[goods.Cid], + IsSingleSku: utils.IntToStr(goods.IsSingleSku), + Price: goods.Price, + Stock: utils.IntToStr(goods.Stock), + Img: goods.Img, + ImgUrl: svc.ImageFormatWithBucket(scheme, host, goods.Img), + Spe: nil, + Sort: utils.IntToStr(goods.Sort), + Info: goods.Info, + State: utils.IntToStr(goods.State), + StateStr: stateMap[goods.State], + } + GoodsSpe := make([]md.GoodsSpe, 0) + json.Unmarshal([]byte(goods.Spe), &GoodsSpe) + for k, v := range GoodsSpe { + if len(v.Values) == 0 { + GoodsSpe[k].Values = make([]string, 0) + } + } + res.Spe = GoodsSpe + sku := db.GetGoodsSkuById(svc.MasterDb(c), goods.Id) + skuList := make([]md.MallGoodsSku, 0) + if sku != nil { + for _, v := range *sku { + skuMap := make([]map[string]string, 0) + json.Unmarshal([]byte(v.Sku), &skuMap) + tmp := md.MallGoodsSku{ + SkuID: utils.Int64ToStr(v.SkuId), + GoodsID: utils.IntToStr(v.GoodsId), + Price: v.Price, + Stock: utils.IntToStr(v.Stock), + Indexes: v.Indexes, + Sku: skuMap, + } + skuList = append(skuList, tmp) + } + } + if goods.IsSingleSku == 1 { + skuList = nil + } + re := map[string]interface{}{ + "base": res, + "sku_list": skuList, + } + e.OutSuc(c, re, nil) + return +} diff --git a/app/store/svc/svc_audit.go b/app/store/svc/svc_audit.go new file mode 100644 index 0000000..3be2b34 --- /dev/null +++ b/app/store/svc/svc_audit.go @@ -0,0 +1,75 @@ +package svc + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/e" + "applet/app/md" + "applet/app/svc" + "applet/app/utils" + "github.com/gin-gonic/gin" + "github.com/jinzhu/copier" + "time" +) + +func AuditInfo(c *gin.Context) { + var res md.CommunityTeamStoreAudit + user := svc.GetUser(c) + storeCheck := db.StoreAuditByUid(svc.MasterDb(c), user.Info.Uid) + res.State = "0" + if storeCheck != nil { + copier.Copy(&res, &storeCheck) + res.State = utils.IntToStr(storeCheck.State) + res.ProvinceId = utils.IntToStr(storeCheck.ProvinceId) + res.CityId = utils.IntToStr(storeCheck.CityId) + res.DistrictId = utils.IntToStr(storeCheck.DistrictId) + } + userParty := db.GetStoreIdEg(svc.MasterDb(c), utils.IntToStr(user.Info.Uid)) + if userParty != nil { + if userParty.State == 1 { + res.State = "2" + } else if storeCheck != nil && storeCheck.State == 2 { + res.State = "3" + } + } + e.OutSuc(c, res, nil) + return +} +func AuditDoing(c *gin.Context) { + var arg md.CommunityTeamStoreAudit + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + userParty := db.GetStoreIdEg(svc.MasterDb(c), utils.IntToStr(user.Info.Uid)) + if userParty != nil { + if userParty.State == 1 { + e.OutErr(c, 400, e.NewErr(400, "已审核通过")) + return + } + } + var tmp model.CommunityTeamStoreAudit + copier.Copy(&tmp, &arg) + tmp.State = 1 + tmp.ProvinceId = utils.StrToInt(arg.ProvinceId) + tmp.CityId = utils.StrToInt(arg.CityId) + tmp.DistrictId = utils.StrToInt(arg.DistrictId) + tmp.Uid = user.Info.Uid + tmp.CreateAt = time.Now() + tmp.UpdateAt = time.Now() + storeCheck := db.StoreAuditByUid(svc.MasterDb(c), user.Info.Uid) + if storeCheck != nil { + if storeCheck.State == 2 { + e.OutErr(c, 400, e.NewErr(400, "已审核通过")) + return + } + tmp.CreateAt = storeCheck.CreateAt + svc.MasterDb(c).Where("id=?", storeCheck.Id).Update(&tmp) + } else { + svc.MasterDb(c).Insert(&tmp) + } + + e.OutSuc(c, "success", nil) + return +} diff --git a/app/store/svc/svc_base.go b/app/store/svc/svc_base.go new file mode 100644 index 0000000..b3463c0 --- /dev/null +++ b/app/store/svc/svc_base.go @@ -0,0 +1 @@ +package svc diff --git a/app/store/svc/svc_goods.go b/app/store/svc/svc_goods.go new file mode 100644 index 0000000..1ca8eec --- /dev/null +++ b/app/store/svc/svc_goods.go @@ -0,0 +1,386 @@ +package svc + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/e" + "applet/app/md" + "applet/app/svc" + "applet/app/utils" + "applet/app/utils/logx" + "encoding/json" + "github.com/gin-gonic/gin" + "github.com/jinzhu/copier" + "github.com/shopspring/decimal" + "strings" + "time" +) + +func GoodsCate(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + arg["uid"] = utils.IntToStr(user.Info.Uid) + arg["store_type"] = "1" + cate, total := db.GetGoodsCate(svc.MasterDb(c), arg) + list := make([]map[string]string, 0) + if cate != nil { + for _, v := range *cate { + tmp := map[string]string{ + "id": utils.IntToStr(v.Id), + "sort": utils.IntToStr(v.Sort), + "is_show": utils.IntToStr(v.IsShow), + "title": v.Title, + } + list = append(list, tmp) + } + } + res := map[string]interface{}{ + "list": list, "total": total, + } + e.OutSuc(c, res, nil) + return +} +func GoodsCateSave(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + var data = &model.CommunityTeamCate{} + + if utils.StrToInt(arg["id"]) > 0 { + cate := db.GetGoodsCateById(svc.MasterDb(c), arg["id"]) + if cate == nil { + e.OutErr(c, 400, e.NewErr(400, "分类不存在")) + return + } + data = cate + } else { + data = &model.CommunityTeamCate{ + IsShow: utils.StrToInt(arg["is_show"]), + } + svc.MasterDb(c).Insert(data) + } + data.StoreType = 1 + data.Uid = user.Info.Uid + data.Sort = utils.StrToInt(arg["sort"]) + data.IsShow = utils.StrToInt(arg["is_show"]) + data.Title = arg["title"] + svc.MasterDb(c).Where("id=?", data.Id).Update(data) + e.OutSuc(c, "success", nil) + return + +} +func GoodsCateShow(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + cate := db.GetGoodsCateById(svc.MasterDb(c), arg["id"]) + if cate == nil { + e.OutErr(c, 400, e.NewErr(400, "分类不存在")) + return + } + cate.IsShow = utils.StrToInt(arg["is_show"]) + svc.MasterDb(c).Where("id=?", cate.Id).Cols("is_show").Update(cate) + e.OutSuc(c, "success", nil) + return + +} +func GoodsCateDel(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + svc.MasterDb(c).In("id", strings.Split(arg["ids"], ",")).Delete(&model.CommunityTeamCate{}) + e.OutSuc(c, "success", nil) + return +} + +func Goods(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := svc.GetUser(c) + arg["uid"] = utils.IntToStr(user.Info.Uid) + arg["store_type"] = "1" + cate, total := db.GetStoreGoods(svc.MasterDb(c), arg) + list := make([]map[string]string, 0) + cateData := db.GetGoodsCateAllArg(svc.MasterDb(c), arg) + cateList := make([]map[string]string, 0) + cateMap := make(map[int]string) + if cateData != nil { + for _, v := range *cateData { + tmp := map[string]string{ + "name": v.Title, "value": utils.IntToStr(v.Id), + } + cateList = append(cateList, tmp) + cateMap[v.Id] = v.Title + } + } + if cate != nil { + stateMap := []string{"上架", "下架"} + scheme, host := svc.ImageBucket(c) + for _, v := range *cate { + tmp := map[string]string{ + "id": utils.IntToStr(v.Id), + "title": v.Title, + "price": v.Price, + "info": v.Info, + "img_url": svc.ImageFormatWithBucket(scheme, host, v.Img), + "create_at": v.CreateAt.Format("2006-01-02 15:04:05"), + "cate": cateMap[v.Cid], + "state": stateMap[v.State], + } + list = append(list, tmp) + } + } + res := map[string]interface{}{ + "list": list, "total": total, "cate_list": cateList, + } + e.OutSuc(c, res, nil) + return +} +func GoodsSave(c *gin.Context) { + var args md.AddGoodsReq + if err := c.ShouldBindJSON(&args); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + saleCount := 0 + eg := svc.MasterDb(c) + user := svc.GetUser(c) + if utils.StrToInt(args.Base.Id) != 0 { + oldGoods := db.GetGoodsById(eg, args.Base.Id) + if oldGoods == nil { + e.OutErr(c, 400, e.NewErr(400, "商品不存在")) + return + } + saleCount = oldGoods.SaleCount + } + sess := eg.NewSession() + defer func() { + _ = sess.Close() + }() + err := sess.Begin() + if err != nil { + e.OutErr(c, 400, e.NewErr(400, err.Error())) + return + } + // 商品基本信息保存 + var goods model.CommunityTeamGoods + err = copier.Copy(&goods, args.Base) + goods.StoreType = 1 + goods.Uid = user.Info.Uid + goods.Id = utils.StrToInt(args.Base.Id) + goods.Stock = utils.StrToInt(args.Base.Stock) + goods.State = utils.StrToInt(args.Base.State) + goods.Cid = utils.StrToInt(args.Base.Cid) + goods.IsSingleSku = utils.StrToInt(args.Base.IsSingleSku) + goods.Sort = utils.StrToInt(args.Base.Sort) + if err != nil { + _ = sess.Rollback() + e.OutErr(c, 400, e.NewErr(400, err.Error())) + return + } + goods.SaleCount = saleCount + goods.Img = args.Base.Img + goods.ImageList = utils.SerializeStr([]string{args.Base.Img}) + goods.Spe = utils.SerializeStr(args.Base.Spe) + // 商品价格处理 + if goods.IsSingleSku == 1 { // 单规格 计算折扣价 + args.SkuList = []md.MallGoodsSku{ + { + Price: args.Base.Price, + Stock: args.Base.Stock, + Indexes: "", + Sku: []map[string]string{}, + }, + } + } else { // 多规格 + var totalStock = 0 + minPriceD, err := decimal.NewFromString(args.SkuList[0].Price) + if err != nil { + _ = sess.Rollback() + e.OutErr(c, 400, e.NewErr(400, "规格价格格式有误")) + return + } + for _, item := range args.SkuList { + tempPrice, err := decimal.NewFromString(item.Price) + totalStock += utils.StrToInt(item.Stock) + if err != nil { + _ = sess.Rollback() + logx.Warn("", err) + e.OutErr(c, 400, e.NewErr(400, "规格价格格式有误")) + return + } + if tempPrice.LessThan(minPriceD) { + minPriceD = tempPrice + } + } + goods.Price = minPriceD.String() + goods.Stock = totalStock + } + goods.UpdateAt = time.Now() + if utils.StrToInt(args.Base.Id) == 0 { // 新增goods + goods.CreateAt = time.Now() + _, err = sess.Insert(&goods) + if err != nil { + logx.Warn(err) + _ = sess.Rollback() + e.OutErr(c, 400, e.NewErr(400, "插入商品数据失败")) + return + } + } else { // 更新数据 + oldGoods := db.GetGoodsByIdSess(sess, args.Base.Id) + goods.CreateAt = oldGoods.CreateAt + _, err = sess.Where(" id = ?", args.Base.Id). + AllCols().Update(&goods) + if err != nil { + _ = sess.Rollback() + logx.Warn(err) + e.OutErr(c, 400, e.NewErr(400, "更新商品失败")) + return + } + } + skuModelList := make([]*model.CommunityTeamSku, 0, len(args.SkuList)) + for _, item := range args.SkuList { + skuModelList = append(skuModelList, &model.CommunityTeamSku{ + GoodsId: goods.Id, + Price: item.Price, + Stock: utils.StrToInt(item.Stock), + Indexes: GetIndexesStr(&args.Base, item), + Sku: utils.SerializeStr(&item.Sku), + Discount: "10", + }) + } + // 插入sku信息 + if len(skuModelList) != 0 { + insert, err := sess.Insert(skuModelList) + if err != nil || insert < 1 { + _ = sess.Rollback() + e.OutErr(c, 400, e.NewErr(400, "商品规格插入失败")) + return + } + } + + sess.Commit() + e.OutSuc(c, "success", nil) + return + +} +func GetIndexesStr(baseGoods *md.BaseGoods, goodsSku md.MallGoodsSku) string { + spe := baseGoods.Spe + sku := goodsSku.Sku + result := "" + + for index, item := range sku { + for _, itm := range spe { + if item["name"] == itm.Name { + for i, v := range spe[index].Values { + if v == item["value"] { + result = result + utils.IntToStr(i) + "-" + } + } + } + } + } + return strings.Trim(result, "-") +} + +func GoodsDel(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + svc.MasterDb(c).In("id", strings.Split(arg["ids"], ",")).Delete(&model.CommunityTeamGoods{}) + svc.MasterDb(c).In("goods_id", strings.Split(arg["ids"], ",")).Delete(&model.CommunityTeamSku{}) + e.OutSuc(c, "success", nil) + return +} +func GoodsDetail(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + goods := db.GetGoodsById(svc.MasterDb(c), arg["id"]) + if goods == nil { + e.OutErr(c, 400, e.NewErr(400, "商品不存在")) + return + } + cateData := db.GetGoodsCateAll(svc.MasterDb(c)) + cateList := make([]map[string]string, 0) + cateMap := make(map[int]string) + if cateData != nil { + for _, v := range *cateData { + tmp := map[string]string{ + "name": v.Title, "value": utils.IntToStr(v.Id), + } + cateList = append(cateList, tmp) + cateMap[v.Id] = v.Title + } + } + stateMap := []string{"上架", "下架"} + scheme, host := svc.ImageBucket(c) + res := md.BaseGoods{ + Id: utils.IntToStr(goods.Id), + Title: goods.Title, + Cid: utils.IntToStr(goods.Cid), + CategoryName: cateMap[goods.Cid], + IsSingleSku: utils.IntToStr(goods.IsSingleSku), + Price: goods.Price, + Stock: utils.IntToStr(goods.Stock), + Img: goods.Img, + ImgUrl: svc.ImageFormatWithBucket(scheme, host, goods.Img), + Spe: nil, + Sort: utils.IntToStr(goods.Sort), + Info: goods.Info, + State: utils.IntToStr(goods.State), + StateStr: stateMap[goods.State], + } + GoodsSpe := make([]md.GoodsSpe, 0) + json.Unmarshal([]byte(goods.Spe), &GoodsSpe) + for k, v := range GoodsSpe { + if len(v.Values) == 0 { + GoodsSpe[k].Values = make([]string, 0) + } + } + res.Spe = GoodsSpe + sku := db.GetGoodsSkuById(svc.MasterDb(c), goods.Id) + skuList := make([]md.MallGoodsSku, 0) + if sku != nil { + for _, v := range *sku { + skuMap := make([]map[string]string, 0) + json.Unmarshal([]byte(v.Sku), &skuMap) + tmp := md.MallGoodsSku{ + SkuID: utils.Int64ToStr(v.SkuId), + GoodsID: utils.IntToStr(v.GoodsId), + Price: v.Price, + Stock: utils.IntToStr(v.Stock), + Indexes: v.Indexes, + Sku: skuMap, + } + skuList = append(skuList, tmp) + } + } + if goods.IsSingleSku == 1 { + skuList = nil + } + re := map[string]interface{}{ + "base": res, + "sku_list": skuList, + } + e.OutSuc(c, re, nil) + return +} diff --git a/app/store/svc/svc_login.go b/app/store/svc/svc_login.go new file mode 100644 index 0000000..21e4046 --- /dev/null +++ b/app/store/svc/svc_login.go @@ -0,0 +1,388 @@ +package svc + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/e" + "applet/app/lib/mob" + "applet/app/lib/sms" + "applet/app/lib/zhimeng" + "applet/app/md" + "applet/app/svc" + "applet/app/utils" + "applet/app/utils/cache" + "applet/app/utils/logx" + sms2 "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/sms" + "encoding/json" + "errors" + "fmt" + "github.com/gin-gonic/gin" + "github.com/syyongx/php2go" + "github.com/tidwall/gjson" + "math/rand" + "time" + "xorm.io/xorm" +) + +func Login(c *gin.Context) { + r := new(md.LoginResponse) + requestBody := new(md.FastLoginRequestBody) + if err := c.ShouldBindJSON(&requestBody); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user, _ := db.UserFindByMobileAll(svc.MasterDb(c), requestBody.Mobile) + if user == nil { + e.OutErr(c, 400, e.NewErr(400, "账号不存在")) + return + } + if user.Password != utils.Md5(requestBody.Password) { + e.OutErr(c, 400, e.NewErr(400, "密码不正确")) + return + } + if err := svc.FastLoginUserExist(c, r, requestBody); err != nil { + if e.ErrorIsAccountBan(err) { + e.OutErr(c, e.ERR_USER_IS_BAN, err) + return + } + e.OutErr(c, 400, err) + return + } + e.OutSuc(c, r, nil) + return +} +func LoginFastIn(c *gin.Context) { + var req map[string]string + if err := c.ShouldBindJSON(&req); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + if req["phone"] == "" { + e.OutErr(c, 400, e.NewErr(400, "手机号不能为空")) + return + } + if req["captcha"] == "" { + e.OutErr(c, 400, e.NewErr(400, "验证码不能为空")) + return + } + mob1, errr := mob.GetMobSDK(c.GetString("mid")) + if errr != nil { + e.OutErr(c, e.ERR_MOB_CONFIG, errr) + return + } + if req["zone"] == "" { + req["zone"] = "86" + } + send := map[string]interface{}{ + "phone": req["phone"], + "zone": req["zone"], + "code": req["captcha"], + } + + var ok bool + var err error + // h5(wap) 登录 + smsPlatform := sms.GetSmsPlatform(c) + key := fmt.Sprintf("%s_SMS_FastLogin_%s", db.SysCfgGet(c, "app_name"), req["phone"]) + if smsPlatform == "ljioe" { + b, err := cache.GetBytes(key) + if err != nil { + e.OutErr(c, e.ERR_MOB_SMS_NO_EXISTS, err) + return + } + if req["captcha"] != gjson.GetBytes(b, "data.captcha").String() { + e.OutErr(c, e.ERR_MOB_SMS_NO_SAME, err) + return + } + ok = true + } else { + c.Set("not_deduction_doing", "1") + ok, err = mob1.MobSMS(c, send) + if err != nil { + e.OutErr(c, 400, err.Error()) + return + } + } + + r := new(md.LoginResponse) + requestBody := &md.FastLoginRequestBody{ + Mobile: req["phone"], + } + if ok { + // 短信验证通过 + user, isExist, err := db.UserGetByMobileIgnoreDelete(db.DBs[c.GetString("mid")], req["phone"], req["zone"]) + if err != nil { + e.OutErr(c, e.ERR, err) + return + } + //用户已注册过,获取用户信息并返回 + if isExist { + if user.DeleteAt != 0 { + e.OutErr(c, e.ERR_USER_IS_BAN) + return + } + if err := svc.FastLoginUserExist(c, r, requestBody); err != nil { + if e.ErrorIsAccountBan(err) { + e.OutErr(c, e.ERR_USER_IS_BAN, err) + return + } + e.OutErr(c, 400, err) + return + } + e.OutSuc(c, r, nil) + return + } + + if err := FastLoginUserNoExist(c, r, requestBody); err != nil { + // 创建失败时清空用户 + if r.UserID != "" { + UserDeleteOne(c, r.UserID) + } + e.OutErr(c, e.ERR, err) + return + } + cache.Del(key) + // 返回登陆响应 + e.OutSuc(c, r, nil) + return + } + // 验证码无效或者过期,验证码错误 + e.OutErr(c, e.ERR_SMS_AUTH, err) + return +} +func FastLoginUserNoExist(c *gin.Context, r *md.LoginResponse, requestBody *md.FastLoginRequestBody) error { + user := new(model.User) + user.Username = requestBody.Mobile + user.Password = utils.Md5(requestBody.Mobile) + if requestBody.Password != "" { + user.Password = utils.Md5(requestBody.Password) + } + user.Platform = c.GetHeader("platform") + user.Phone = requestBody.Mobile + appNameCn := db.SysCfgGet(c, "app_name_cn") + user.Nickname = appNameCn + requestBody.Mobile[len(requestBody.Mobile)-4:len(requestBody.Mobile)] + user.Zone = "86" + lvs, err := db.UserLevlAll(c, db.DBs[c.GetString("mid")]) + if err != nil || len(lvs) == 0 { + return errors.New("会员等级不存在") + } + + user.Level = lvs[0].Id + user.State = 1 + user.CreateAt = time.Now() + user.UpdateAt = time.Now() + // ---- 插入用户-----! + exist, err := userCheck(c, user, db.UserInsert) + if err != nil { + return err + } + if exist { + return errors.New("Register user is exist") + } + r.UserID = utils.IntToStr(user.Uid) + // 生成jwt + appName := db.SysCfgGet(c, "app_name") + token, err := utils.GenToken(user.Uid, user.Username, user.Phone, appName, "", "") + if err != nil { + return logx.Warn(err) + } + // Insert user profile + userProfile := new(model.UserProfile) + userProfile.ArkidToken = token + userProfile.Uid = user.Uid + if userProfile.AvatarUrl == "" { + userProfile.AvatarUrl = db.SysCfgGet(c, "app_user_default_avatar") + } + userProfile.IsNew = 1 + exist, err = userProfileCheck(c, userProfile, db.UserProfileInsert) + if err != nil { + return err + } + if exist { + return errors.New("user Profile is exist") + } + //debug + //生成邀请码 防止卡死 + GetInviteCode(c, user, userProfile) + // 异步处理 有效会员和新会员 + // 写入缓存 + key := fmt.Sprintf("%s:token:%s", c.GetString("mid"), user.Username) + _, err = cache.SetEx(key, token, 39528000) // 半年 + if err != nil { + return logx.Warn(err) + } + r.Token = token + r.UserID = utils.IntToStr(user.Uid) + return nil +} +func GetInviteCode(c *gin.Context, user *model.User, userProfile *model.UserProfile) { + if userProfile.InviteCode != "" { + return + } + cc := c.Copy() // 传递上下文给 goroutine 的话 一定要使用副本,这样才能保证上下文的输出安全 + //生成邀请码的线程 直接访问怕慢 + go UserInviteCode(cc, &md.User{ + Info: user, + Profile: userProfile, + }) + + return +} + +func userCheck(c *gin.Context, user *model.User, f func(*xorm.Engine, *model.User) (int64, error)) (bool, error) { + fmt.Println("user in userCheck is ", utils.SerializeStr(user)) + isExist, err := db.UserIsExistByMobile(db.DBs[c.GetString("mid")], user.Username) + if isExist { + return isExist, nil + } + _, err = f(db.DBs[c.GetString("mid")], user) + + return false, err +} + +func userProfileCheck(c *gin.Context, userProfile *model.UserProfile, f func(*xorm.Engine, *model.UserProfile) (int64, error)) (bool, error) { + isExist, err := db.UserProfileIsExistByUserID(db.DBs[c.GetString("mid")], userProfile.Uid) + if isExist { + return isExist, nil + } + _, err = f(db.DBs[c.GetString("mid")], userProfile) + + return false, err +} +func UserDeleteOne(c *gin.Context, id interface{}) (int64, error) { + + _, err := db.UserDelete(db.DBs[c.GetString("mid")], id) + if err != nil { + return 0, err + } + // 删除用户 + _, err = db.UserProfileDelete(db.DBs[c.GetString("mid")], id) + if err != nil { + return 0, err + } + // 删除用户关系 + _, err = db.UserRelateDelete(db.DBs[c.GetString("mid")], id) + if err != nil { + return 0, err + } + // 将他的下级pid清零 + us, err := db.UserProfileByPuid(db.DBs[c.GetString("mid")], id) + if err != nil { + return 0, err + } + for _, item := range *us { + item.ParentUid = 0 + _, err = db.UserProfileUpdate(db.DBs[c.GetString("mid")], item.Uid, &item, "parent_uid") + if err != nil { + continue + } + } + + return 1, nil +} + +func LoginSendSms(c *gin.Context) { + var req map[string]string + if err := c.ShouldBindJSON(&req); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + if req["phone"] == "" { + e.OutErr(c, 400, e.NewErr(400, "手机号不能为空")) + return + } + isExist, err := db.UserisExistByMobile(db.DBs[c.GetString("mid")], req["phone"]) + if err != nil { + e.OutErr(c, e.ERR, err) + return + } + userdata, _ := db.UserFindByPhoneOrNickname(db.DBs[c.GetString("mid")], req["phone"]) + if userdata != nil && userdata.State == 2 { + e.OutErr(c, 400, e.NewErr(400, "账号已冻结")) + return + } + types := "" + if !isExist { + types = "register" + } else if isExist { + types = "login" + } + smsType := svc.SysCfgGet(c, "sms_type") + c.Set("sms_type", smsType) + if c.GetString("sms_type") == "1" { + count := sms2.SmsNumGetSmsNum(db.Db, "putong", c.GetString("mid")) + if count-1 < 0 { + e.OutErr(c, e.ERR_MOB_SMS_NO_AVA, err) + return + } + } else { + count, _ := zhimeng.SmsNum(db.Db, c.GetString("mid"), c.GetString("sms_type"), db.SysCfgGet(c, "third_zm_sms_key"), db.SysCfgGet(c, "third_zm_sms_secret")) + if count-1 < 0 { + e.OutErr(c, e.ERR_MOB_SMS_NO_AVA, err) + return + } + } + appName := db.SysCfgGet(c, "sms_push_sign") + captcha := createCaptcha() + content := fmt.Sprintf("【%s】验证码:%s", appName, captcha) + key := fmt.Sprintf("%s_SMS_%s", db.SysCfgGet(c, "app_name"), req["phone"]) + templateCode := "" + switch types { + case "login": + content = fmt.Sprintf("【%s】快捷登录验证码:%s", appName, captcha) + key = fmt.Sprintf("%s_SMS_FastLogin_%s", db.SysCfgGet(c, "app_name"), req["phone"]) + templateCode = "login" + case "register": + content = fmt.Sprintf("【%s】注册验证码:%s", appName, captcha) + key = fmt.Sprintf("%s_SMS_FastLogin_%s", db.SysCfgGet(c, "app_name"), req["phone"]) + templateCode = "register" + } + marshal, _ := json.Marshal(c.Request.Header) + waykeys := "app_" + c.ClientIP() + "_" + utils.IntToStr(utils.GetApiVersion(c)) + "_" + c.Request.RequestURI + "_" + string(marshal) + postData := map[string]interface{}{ + "content": content, + "mobile": req["phone"], + "templateCode": templateCode, + "way": php2go.Base64Encode(waykeys), + } + requestBody := new(md.Register) + requestBody.Mobile = req["phone"] + requestBody.Captcha = captcha + if requestBody.Zone == "" { + requestBody.Zone = "86" + } + err = sms.GetSmsConfig(c, requestBody.Zone, postData) + if err != nil { + e.OutErr(c, 400, err) + return + } + tmp := struct { + Data md.Register `json:"data"` + CacheTime int64 `json:"cache_time"` + }{ + Data: *requestBody, + CacheTime: time.Now().Unix(), + } + if _, err := cache.SetEx(key, utils.Serialize(tmp), 180); err != nil { + e.OutErr(c, e.ERR, err) + return + } + //存入一个缓存 用于邀请码注册时候判断 + keys := fmt.Sprintf("%s_SMSCHECK_%s", c.GetString("mid"), requestBody.Mobile) + tmps := struct { + Check int `json:"check"` + CacheTime int64 `json:"cache_time"` + }{ + Check: 1, + CacheTime: time.Now().Unix(), + } + if _, err := cache.SetEx(keys, utils.Serialize(tmps), 3600); err != nil { + e.OutErr(c, e.ERR, err) + return + } + e.OutSuc(c, "验证码已发送,3分钟内有效", nil) + return +} +func createCaptcha() string { + return fmt.Sprintf("%05v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000)) +} diff --git a/app/store/svc/svc_order.go b/app/store/svc/svc_order.go new file mode 100644 index 0000000..b3463c0 --- /dev/null +++ b/app/store/svc/svc_order.go @@ -0,0 +1 @@ +package svc diff --git a/app/store/svc/svc_store.go b/app/store/svc/svc_store.go new file mode 100644 index 0000000..b3463c0 --- /dev/null +++ b/app/store/svc/svc_store.go @@ -0,0 +1 @@ +package svc diff --git a/app/store/svc/svc_user_invitecode.go b/app/store/svc/svc_user_invitecode.go new file mode 100644 index 0000000..8d91eda --- /dev/null +++ b/app/store/svc/svc_user_invitecode.go @@ -0,0 +1,112 @@ +package svc + +import ( + "applet/app/db" + "applet/app/e" + "applet/app/md" + "applet/app/utils" + "fmt" + "github.com/gin-gonic/gin" + "math/rand" + "unicode" +) + +// 检测获取邀请码 +func UserInviteCode(c *gin.Context, user *md.User) string { + //已经有邀请码了就中断 + if user.Profile.InviteCode != "" { + return user.Profile.InviteCode + } + var code string + //读取后台配置判断是数字还是 数字+字母 + inviteData := db.SysCfgFind(c, "app_invite_length", "app_invite_type") + l := utils.StrToInt(inviteData["app_invite_length"]) + types := utils.StrToInt(inviteData["app_invite_type"]) + ////匹配最新的用户的邀请码长度 + //newUser, _ := db.UserProfileOrderByNew(db.DBs[c.GetString("mid")]) + //if newUser.InviteCode != "" { + // l = len(newUser.InviteCode) + //} + //读取code + code = returnCode(c, l, types, 0) + //查询用户信息 + userProfile, err := db.UserProfileFindByID(db.DBs[c.GetString("mid")], user.Info.Uid) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err) + return "" + } + //写入code + userProfile.InviteCode = code + fmt.Println(userProfile) + db.UserProfileUpdate(db.DBs[c.GetString("mid")], user.Info.Uid, userProfile) + return code +} +func returnCode(c *gin.Context, l, types, num int) string { + if num > 5 { + return "" + } + //循环3次判断是否存在该邀请码 + var code string + var ( + codes []string + ) + for i := 0; i < 3; i++ { + oneCode := GetRandomString(l, types) + codes = append(codes, oneCode) + } + + //判断是不是存在邀请码了 + tmp, _ := db.UserProfileFindByInviteCodes(db.DBs[c.GetString("mid")], codes...) + //判断自定义是不是存在邀请码了 + customTmp, _ := db.UserProfileFindByCustomInviteCodes(db.DBs[c.GetString("mid")], codes...) + //循环生成的邀请码 判断tmp里有没有这个邀请码 如果邀请码没有就赋值 再判断是否存在 存在就清空 + for _, v := range codes { + if code != "" { //如果存在并且数据库没有就跳过 + continue + } + code = v + for _, v1 := range *tmp { + //如果存在就清空 + if v1.InviteCode == v { + code = "" + } + } + for _, v1 := range *customTmp { + //如果存在就清空 + if v1.CustomInviteCode == v { + code = "" + } + } + } + //如果都没有就继续加一位继续查 + if code == "" { + return returnCode(c, l+1, types, num+1) + } + return code +} + +// 随机生成指定位数的大写字母和数字的组合 +func GetRandomString(l, isLetter int) string { + str := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + if isLetter != 1 { + str = "0123456789" + } + strs := []rune(str) + result := make([]rune, l) + for i := range result { + result[i] = strs[rand.Intn(len(strs))] + } + fmt.Println(result) + if IsLetter(string(result)) && isLetter == 1 { + return GetRandomString(l, isLetter) + } + return string(result) +} +func IsLetter(s string) bool { + for _, r := range s { + if !unicode.IsLetter(r) { + return false + } + } + return true +} diff --git a/app/svc/svc_file_img_upload.go b/app/svc/svc_file_img_upload.go new file mode 100644 index 0000000..050e9d1 --- /dev/null +++ b/app/svc/svc_file_img_upload.go @@ -0,0 +1,104 @@ +package svc + +import ( + "fmt" + "strings" + + "applet/app/e" + "applet/app/lib/qiniu" + "applet/app/md" + "applet/app/utils" + "applet/app/utils/logx" + + "github.com/gin-gonic/gin" +) + +// 请求文件上传 +func ImgReqUpload(c *gin.Context, uid, dirName, fname, callbackUrl string, fsize int64) (interface{}, error) { + ext := utils.FileExt(fname) + if err := initStg(c, fsize, ext); err != nil { + return nil, err + } + // logx.Warn(uid) + newName := dirName + "_" + fmt.Sprintf("%010s", uid) + + // if dirName == md.FILE_DIR_FEEDBACK || dirName == md.FILE_DIR_STYLE { + // newName += "_" + utils.FormatNanoUnix() + utils.RandString(4, "0123456789") + // } + // 默认都加时间戳 + newName += "_" + utils.FormatNanoUnix() + utils.RandString(4, "0123456789") + newName += "." + ext + + f := &md.FileCallback{ + Uid: uid, + DirId: md.FileUserDir[dirName], + FileName: newName, + } + // logx.Warn(f.Uid) + return qiniu.ReqImgUpload(f, callbackUrl), nil +} + +func initStg(c *gin.Context, fsize int64, ext string) error { + // 获取上传配置 + stgInfo := SysCfgFind( + c, + md.KEY_CFG_FILE_BUCKET, + md.KEY_CFG_FILE_HOST, + md.KEY_CFG_FILE_AK, + md.KEY_CFG_FILE_SK, + md.KEY_CFG_FILE_PVD, + md.KEY_CFG_FILE_REGION, + md.KEY_CFG_FILE_MAX_SIZE, + md.KEY_CFG_FILE_EXT, + md.KEY_CFG_FILE_SCHEME, + md.KEY_CFG_FILE_AVATAR_THUMBNAIL, + ) + //?imageView2/1/w/120/h/120/format/webp/interlace/1 + if stgInfo == nil { + return e.NewErrCode(e.ERR_CFG) + } + // todo 目前仅支持七牛 + if v, ok := stgInfo[md.KEY_CFG_FILE_PVD]; !ok || v != "qiniu" { + return e.NewErrCode(e.ERR_CFG) + } + if v, ok := stgInfo[md.KEY_CFG_FILE_REGION]; !ok || v == "" { + return e.NewErrCode(e.ERR_CFG) + } + if v, ok := stgInfo[md.KEY_CFG_FILE_AK]; !ok || v == "" { + return e.NewErrCode(e.ERR_CFG) + } + if v, ok := stgInfo[md.KEY_CFG_FILE_SK]; !ok || v == "" { + return e.NewErrCode(e.ERR_CFG) + } + if v, ok := stgInfo[md.KEY_CFG_FILE_BUCKET]; !ok || v == "" { + return e.NewErrCode(e.ERR_CFG) + } + if v, ok := stgInfo[md.KEY_CFG_FILE_SCHEME]; !ok || v == "" { + stgInfo[md.KEY_CFG_FILE_SCHEME] = "http" + SysCfgSet(c, md.KEY_CFG_FILE_SCHEME, stgInfo[md.KEY_CFG_FILE_SCHEME], "文件域名HTTP协议") + } + qiniu.Init(stgInfo[md.KEY_CFG_FILE_AK], stgInfo[md.KEY_CFG_FILE_SK], stgInfo[md.KEY_CFG_FILE_BUCKET], stgInfo[md.KEY_CFG_FILE_REGION], stgInfo[md.KEY_CFG_FILE_SCHEME]) + if v, ok := stgInfo[md.KEY_CFG_FILE_HOST]; !ok || v == "" { + var err error + stgInfo[md.KEY_CFG_FILE_HOST], err = qiniu.BucketGetDomain(stgInfo[md.KEY_CFG_FILE_BUCKET]) + if err != nil { + logx.Error(err) + return e.NewErrCode(e.ERR_CFG) + } + SysCfgSet(c, md.KEY_CFG_FILE_HOST, stgInfo[md.KEY_CFG_FILE_HOST], "文件域名地址") + } + // 头像缩略图参数 + if v, ok := stgInfo[md.KEY_CFG_FILE_AVATAR_THUMBNAIL]; !ok || v == "" { + SysCfgSet(c, md.KEY_CFG_FILE_AVATAR_THUMBNAIL, "?imageView2/1/w/200/h/200/format/png", "文件用户头像缩略图参数") + } + + // 检查文件大小限制 + if v, ok := stgInfo[md.KEY_CFG_FILE_MAX_SIZE]; ok && v != "" && utils.StrToInt64(v) < fsize { + return e.NewErrCode(e.ERR_FILE_MAX_SIZE) + } + // 检查文件后缀 + if v, ok := stgInfo[md.KEY_CFG_FILE_EXT]; ok && v != "" && !strings.Contains(v, ext) { + return e.NewErrCode(e.ERR_FILE_EXT) + } + return nil +} diff --git a/app/svc/svc_file_save.go b/app/svc/svc_file_save.go new file mode 100644 index 0000000..e41bff4 --- /dev/null +++ b/app/svc/svc_file_save.go @@ -0,0 +1,44 @@ +package svc + +import ( + "time" + + "applet/app/db" + "applet/app/db/model" + "applet/app/md" + "applet/app/utils" + + "github.com/gin-gonic/gin" +) + +func FileSave(c *gin.Context, f *md.FileCallback) error { + // todo 校验时间是否超时, 目前没必要做时间校验,如果已经上传,但超时,那么会造成三方存储存在,可我方表不存在,导致冗余 + // 校验签名是否正确 + //if qiniu.Sign(f.Time) != f.Sign { + // return e.NewErrCode(e.ERR_SIGN) + //} + newFile := &model.SysFile{ + ParentFid: utils.StrToInt64(f.DirId), + FileType: 1, + ShowName: f.FileName, + SaveName: f.FileName, + Uid: utils.StrToInt(f.Uid), + Ext: utils.FileExt(f.FileName), + Hash: f.Hash, + Mime: f.Mime, + Provider: f.Provider, + Width: utils.StrToInt(f.Width), + Height: utils.StrToInt(f.Height), + Bucket: f.Bucket, + FileSize: utils.StrToInt64(f.FileSize), + CreateAt: int(time.Now().Unix()), + } + + file, _ := db.FileGetByPFidAndName(db.DBs[c.GetString("mid")], f.DirId, f.FileName) + if file != nil { + newFile.Fid = file.Fid + // 更新数据 + return db.FileUpdate(db.DBs[c.GetString("mid")], newFile) + } + return db.FileInsert(db.DBs[c.GetString("mid")], newFile) +}