huangjiajun 3 months ago
parent
commit
f2f61ab620
40 changed files with 3007 additions and 3 deletions
  1. +57
    -0
      app/agent/hdl/hdl_file_img_callback.go
  2. +95
    -0
      app/agent/hdl/hdl_file_img_req_upload.go
  3. +33
    -0
      app/db/db_file.go
  4. +3
    -0
      app/db/db_good.go
  5. +8
    -0
      app/db/db_good_cate.go
  6. +0
    -1
      app/db/db_order.go
  7. +15
    -0
      app/db/db_store_audit.go
  8. +8
    -1
      app/db/db_user.go
  9. +35
    -0
      app/db/db_user_store_activity.go
  10. +30
    -0
      app/db/model/community_team_store_audit.go
  11. +21
    -0
      app/db/model/sys_file.go
  12. +19
    -0
      app/db/model/user_store_activity.go
  13. +57
    -0
      app/hdl/hdl_file_img_callback.go
  14. +95
    -0
      app/hdl/hdl_file_img_req_upload.go
  15. +66
    -0
      app/lib/zhimeng/api.go
  16. +151
    -0
      app/lib/zhimeng/sdk.go
  17. +70
    -0
      app/lib/zhimeng/sms_send.go
  18. +12
    -0
      app/md/cfg_key.go
  19. +62
    -0
      app/md/file.go
  20. +29
    -1
      app/md/md_store.go
  21. +22
    -0
      app/md/store_audit.go
  22. +36
    -0
      app/router/router.go
  23. +17
    -0
      app/store/hdl/hdl_agent_goods.go
  24. +13
    -0
      app/store/hdl/hdl_audit.go
  25. +57
    -0
      app/store/hdl/hdl_file_img_callback.go
  26. +95
    -0
      app/store/hdl/hdl_file_img_req_upload.go
  27. +32
    -0
      app/store/hdl/hdl_goods.go
  28. +26
    -0
      app/store/hdl/hdl_login.go
  29. +465
    -0
      app/store/hdl/hdl_store.go
  30. +87
    -0
      app/store/hdl/hdl_user.go
  31. +179
    -0
      app/store/svc/svc_agent_goods.go
  32. +75
    -0
      app/store/svc/svc_audit.go
  33. +1
    -0
      app/store/svc/svc_base.go
  34. +386
    -0
      app/store/svc/svc_goods.go
  35. +388
    -0
      app/store/svc/svc_login.go
  36. +1
    -0
      app/store/svc/svc_order.go
  37. +1
    -0
      app/store/svc/svc_store.go
  38. +112
    -0
      app/store/svc/svc_user_invitecode.go
  39. +104
    -0
      app/svc/svc_file_img_upload.go
  40. +44
    -0
      app/svc/svc_file_save.go

+ 57
- 0
app/agent/hdl/hdl_file_img_callback.go View File

@@ -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
}

+ 95
- 0
app/agent/hdl/hdl_file_img_req_upload.go View File

@@ -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)
}

+ 33
- 0
app/db/db_file.go View File

@@ -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
}

+ 3
- 0
app/db/db_good.go View File

@@ -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"])
}


+ 8
- 0
app/db/db_good_cate.go View File

@@ -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)


+ 0
- 1
app/db/db_order.go View File

@@ -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)


+ 15
- 0
app/db/db_store_audit.go View File

@@ -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
}

+ 8
- 1
app/db/db_user.go View File

@@ -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{})
}


+ 35
- 0
app/db/db_user_store_activity.go View File

@@ -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
}

+ 30
- 0
app/db/model/community_team_store_audit.go View File

@@ -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)"`
}

+ 21
- 0
app/db/model/sys_file.go View File

@@ -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)"`
}

+ 19
- 0
app/db/model/user_store_activity.go View File

@@ -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)"`
}

+ 57
- 0
app/hdl/hdl_file_img_callback.go View File

@@ -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
}

+ 95
- 0
app/hdl/hdl_file_img_req_upload.go View File

@@ -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)
}

+ 66
- 0
app/lib/zhimeng/api.go View File

@@ -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)
}

+ 151
- 0
app/lib/zhimeng/sdk.go View File

@@ -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
}

+ 70
- 0
app/lib/zhimeng/sms_send.go View File

@@ -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
}

+ 12
- 0
app/md/cfg_key.go View File

@@ -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.
)

+ 62
- 0
app/md/file.go View File

@@ -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"`
}

+ 29
- 1
app/md/md_store.go View File

@@ -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)"`
}

+ 22
- 0
app/md/store_audit.go View File

@@ -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)"`
}

+ 36
- 0
app/router/router.go View File

@@ -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 获取数据库名


+ 17
- 0
app/store/hdl/hdl_agent_goods.go View File

@@ -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)
}

+ 13
- 0
app/store/hdl/hdl_audit.go View File

@@ -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)
}

+ 57
- 0
app/store/hdl/hdl_file_img_callback.go View File

@@ -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
}

+ 95
- 0
app/store/hdl/hdl_file_img_req_upload.go View File

@@ -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)
}

+ 32
- 0
app/store/hdl/hdl_goods.go View File

@@ -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)
}

+ 26
- 0
app/store/hdl/hdl_login.go View File

@@ -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)
}

+ 465
- 0
app/store/hdl/hdl_store.go View File

@@ -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
}

+ 87
- 0
app/store/hdl/hdl_user.go View File

@@ -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
}

+ 179
- 0
app/store/svc/svc_agent_goods.go View File

@@ -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
}

+ 75
- 0
app/store/svc/svc_audit.go View File

@@ -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
}

+ 1
- 0
app/store/svc/svc_base.go View File

@@ -0,0 +1 @@
package svc

+ 386
- 0
app/store/svc/svc_goods.go View File

@@ -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
}

+ 388
- 0
app/store/svc/svc_login.go View File

@@ -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))
}

+ 1
- 0
app/store/svc/svc_order.go View File

@@ -0,0 +1 @@
package svc

+ 1
- 0
app/store/svc/svc_store.go View File

@@ -0,0 +1 @@
package svc

+ 112
- 0
app/store/svc/svc_user_invitecode.go View File

@@ -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
}

+ 104
- 0
app/svc/svc_file_img_upload.go View File

@@ -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
}

+ 44
- 0
app/svc/svc_file_save.go View File

@@ -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)
}

Loading…
Cancel
Save