wangfei 6 年之前
父節點
當前提交
4ae5f695a2
共有 47 個檔案被更改,包括 1894 行新增165 行删除
  1. 4
    0
      conf/log.conf
  2. 7
    0
      conf/sms.conf
  3. 136
    6
      controllers/auth.go
  4. 6
    1
      controllers/base.go
  5. 52
    0
      controllers/config.go
  6. 2
    0
      controllers/context.go
  7. 130
    0
      controllers/customer/customer.go
  8. 4
    5
      controllers/file.go
  9. 42
    0
      controllers/message.go
  10. 6
    2
      controllers/session.go
  11. 0
    7
      controllers/types.go
  12. 62
    0
      controllers/user/user.go
  13. 0
    0
      log/common.log
  14. 19
    0
      models/constant.go
  15. 193
    0
      models/customer/customer.go
  16. 12
    0
      models/customer/types.go
  17. 6
    8
      models/model/sys_case_user.go
  18. 1
    2
      models/model/sys_wechat_conf.go
  19. 15
    21
      models/model/ta_account_change.go
  20. 2
    3
      models/model/ta_cms_case_image.go
  21. 2
    2
      models/model/ta_cms_location.go
  22. 1
    0
      models/model/ta_customer.go
  23. 0
    25
      models/model/ta_experience_card.go
  24. 20
    21
      models/model/ta_goods_orders.go
  25. 4
    6
      models/model/ta_user_mapping.go
  26. 120
    0
      models/sys.go
  27. 43
    0
      models/system/user.go
  28. 51
    38
      routers/common.go
  29. 19
    4
      routers/guest.go
  30. 3
    0
      routers/router.go
  31. 78
    0
      routers/wechat.go
  32. 238
    0
      service/customer/customer.go
  33. 16
    0
      service/customer/types.go
  34. 1
    1
      service/events/events.go
  35. 98
    1
      service/sys.go
  36. 23
    5
      service/user.go
  37. 二進制
      swagger.zip
  38. 99
    0
      utils/captcha.go
  39. 18
    0
      utils/captcha_test.go
  40. 1
    1
      utils/event.go
  41. 34
    0
      utils/jwt.go
  42. 68
    4
      utils/log.go
  43. 61
    0
      utils/pagenavi.go
  44. 71
    0
      utils/pagenavi_test.go
  45. 79
    0
      utils/sms.go
  46. 24
    2
      utils/utils.go
  47. 23
    0
      utils/wechat.go

+ 4
- 0
conf/log.conf 查看文件

@@ -0,0 +1,4 @@
1
+[common]
2
+filename="E:\\GoProjects\\src\\spaceofcheng\\services\\log\\common.log"
3
+# log level "emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"
4
+level="debug"

+ 7
- 0
conf/sms.conf 查看文件

@@ -0,0 +1,7 @@
1
+# 短信接口
2
+url = http://localhost:8080/sms
3
+method = POST
4
+contentType = "application/json;charset=UTF-8"
5
+
6
+[captcha]
7
+code = 0107

+ 136
- 6
controllers/auth.go 查看文件

@@ -1,6 +1,10 @@
1 1
 package controllers
2 2
 
3 3
 import (
4
+	"errors"
5
+	"net/http"
6
+	"spaceofcheng/services/service"
7
+	"spaceofcheng/services/utils"
4 8
 	"strings"
5 9
 
6 10
 	"github.com/astaxie/beego"
@@ -8,23 +12,127 @@ import (
8 12
 
9 13
 // Authenticate 权限验证
10 14
 func (c *BaseController) authenticate() {
15
+	// 默认 service
16
+	serv := service.NewSysServ(c.Context)
17
+
18
+	// 客户端类型
19
+	clientType := utils.GetClientType(c.Ctx.Request)
20
+
21
+	switch clientType {
22
+	case utils.ClientAdmin:
23
+		c.authPCAdmin(serv)
24
+	case utils.ClientWechat:
25
+		c.authWechat(serv)
26
+	default:
27
+		c.ResponseError(
28
+			errors.New("暂不支持的 API 场景"),
29
+			http.StatusBadRequest,
30
+		)
31
+	}
32
+}
33
+
34
+// authPCAdmin PC管理端
35
+func (c *BaseController) authPCAdmin(serv *service.SysServ) {
11 36
 	if !c.needAuth() {
12 37
 		return
13 38
 	}
14 39
 
15
-	userID, _ := c.GetSession(SNUserID).(string)
16
-	// userType := c.GetSession(SNUserType).(string)
40
+	// 用户ID
41
+	userID := ""
42
+	userIDRaw := c.GetSession(SNUserID)
43
+	if userIDRaw != nil {
44
+		userID = userIDRaw.(string)
45
+	}
17 46
 
18
-	// 未登录状态
19 47
 	if userID == "" {
48
+		c.ResponseError(
49
+			errors.New("用户未登录"),
50
+			http.StatusUnauthorized,
51
+		)
52
+	}
53
+
54
+	if err := serv.SetUserProfile(userID); err != nil {
55
+		utils.LogError(err.Error())
56
+
57
+		c.ResponseError(
58
+			errors.New("内部错误, 请重试"),
59
+			http.StatusInternalServerError,
60
+		)
61
+	}
62
+
63
+	// 设置 Session
64
+	c.SetSession(SNUserID, userID)
65
+}
66
+
67
+// authWechat 微信端
68
+func (c *BaseController) authWechat(serv *service.SysServ) {
69
+	custID := ""
70
+	custIDRaw := c.GetSession(SNCustID)
71
+	if custIDRaw != nil {
72
+		custID = custIDRaw.(string)
73
+	}
74
+
75
+	// 用户微信信息
76
+	var wxDetail map[string]interface{}
77
+	detailRaw := c.GetSession("wechat_user")
78
+	if detailRaw != nil {
79
+		wxDetail = detailRaw.(map[string]interface{})
80
+	}
81
+
82
+	if custID == "" && wxDetail == nil {
83
+		wxDetail = c.getWechatDetail()
84
+		c.SetSession("wechat_user", wxDetail)
85
+	}
86
+
87
+	c.Context.Set("wxInfo", wxDetail)
88
+
89
+	// 普通客户映射检查
90
+	userMap, err := serv.CheckWechatUserMapping(wxDetail)
91
+	if err != nil {
92
+		c.ResponseError(
93
+			utils.LogError("获取人员映射账户失败: "+err.Error()),
94
+			http.StatusInternalServerError,
95
+		)
96
+	}
97
+
98
+	if !c.needAuth() {
20 99
 		return
21 100
 	}
22 101
 
23
-	// clientType := utils.GetClientType()
24
-	// if clientType == utils.ClientWechat {
102
+	// 未登录或者绑定, 返回 401
103
+	if custID == "" && userMap.UserId == "" {
104
+		wxConf, ok := c.Configer[WeChatConf]
105
+		if ok {
106
+			c.ResponseData(
107
+				map[string]interface{}{
108
+					"appid": wxConf.String("appid"),
109
+				},
110
+				errors.New("用户未登录"),
111
+				http.StatusUnauthorized,
112
+			)
113
+		} else {
114
+			c.ResponseError(
115
+				errors.New("用户未登录"),
116
+				http.StatusUnauthorized,
117
+			)
118
+		}
119
+	}
120
+
121
+	if custID == "" {
122
+		custID = userMap.UserId
123
+	}
25 124
 
26
-	// }
125
+	if err := serv.SetCustomer(custID); err != nil {
126
+		utils.LogError(err.Error())
27 127
 
128
+		c.ResponseError(
129
+			errors.New("内部错误, 请重试"),
130
+			http.StatusInternalServerError,
131
+		)
132
+	}
133
+
134
+	// 设置 Session
135
+	c.SetSession(SNCustID, custID)
28 136
 }
29 137
 
30 138
 func (c *BaseController) needAuth() bool {
@@ -38,3 +146,25 @@ func (c *BaseController) needAuth() bool {
38 146
 
39 147
 	return true
40 148
 }
149
+
150
+// getWechatDetail 获取微信个人信息详情
151
+func (c *BaseController) getWechatDetail() map[string]interface{} {
152
+	// 微信 code
153
+	code := c.GetString("code")
154
+	if code == "" {
155
+		c.ResponseError(
156
+			errors.New("没有接收到微信 code"),
157
+			http.StatusBadRequest,
158
+		)
159
+	}
160
+
161
+	usr, err := utils.GetWxUserInfo(code)
162
+	if err != nil {
163
+		c.ResponseError(
164
+			utils.LogError("获取微信个人信息失败: "+err.Error()),
165
+			http.StatusInternalServerError,
166
+		)
167
+	}
168
+
169
+	return usr
170
+}

+ 6
- 1
controllers/base.go 查看文件

@@ -6,16 +6,21 @@ import (
6 6
 	"spaceofcheng/services/utils"
7 7
 
8 8
 	"github.com/astaxie/beego"
9
+	"github.com/astaxie/beego/config"
9 10
 )
10 11
 
11 12
 //BaseController 基础controller
12 13
 type BaseController struct {
13 14
 	beego.Controller
14
-	Context *utils.Context
15
+	Context  *utils.Context
16
+	Configer map[string]config.Configer
15 17
 }
16 18
 
17 19
 //Prepare 继承beego的
18 20
 func (c *BaseController) Prepare() {
21
+	// 读取配置文件
22
+	c.initConfig()
23
+
19 24
 	// 初始化上下文
20 25
 	c.initContext()
21 26
 

+ 52
- 0
controllers/config.go 查看文件

@@ -0,0 +1,52 @@
1
+package controllers
2
+
3
+import (
4
+	"spaceofcheng/services/utils"
5
+
6
+	"github.com/astaxie/beego/config"
7
+)
8
+
9
+// 配置文件列表
10
+const (
11
+	AliYunConf = "aliyun"
12
+	WeChatConf = "wechat"
13
+	SMSConf    = "sms"
14
+)
15
+
16
+func (c *BaseController) initConfig() {
17
+	if c.Configer == nil {
18
+		c.Configer = make(map[string]config.Configer)
19
+	}
20
+
21
+	// 阿里云
22
+	aliConf := c.getConfig("conf/aliyun.conf")
23
+	if aliConf != nil {
24
+		c.Configer[AliYunConf] = aliConf
25
+	}
26
+
27
+	// 微信
28
+	clientType := utils.GetClientType(c.Ctx.Request)
29
+	if clientType == utils.ClientWechat {
30
+		wxConf := c.getConfig("conf/wechat.conf")
31
+		if wxConf != nil {
32
+			c.Configer[WeChatConf] = wxConf
33
+		}
34
+	}
35
+
36
+	// 短信
37
+	smsConf := c.getConfig("conf/sms.conf")
38
+	if smsConf != nil {
39
+		c.Configer[SMSConf] = smsConf
40
+	}
41
+	utils.ResetSMSEngine(smsConf)
42
+}
43
+
44
+func (c *BaseController) getConfig(confPath string) config.Configer {
45
+	aliConf, err := config.NewConfig("ini", confPath)
46
+	if err != nil {
47
+		utils.LogError("读取配置文件失败: " + err.Error())
48
+		return nil
49
+	}
50
+
51
+	return aliConf
52
+}

+ 2
- 0
controllers/context.go 查看文件

@@ -11,6 +11,8 @@ import (
11 11
 * - 包含内容如下
12 12
 * user					用户基本信息
13 13
 * customer			会员基本信息
14
+* userMap				用户/会员 映射第三方账户
15
+* wxInfo				微信信息
14 16
 * cases					用户所有案场信息
15 17
 * currentCase 	当前案场
16 18
 * org						用户当前组织

+ 130
- 0
controllers/customer/customer.go 查看文件

@@ -0,0 +1,130 @@
1
+package customer
2
+
3
+import (
4
+	"errors"
5
+	"net/http"
6
+	"spaceofcheng/services/controllers"
7
+	"spaceofcheng/services/models"
8
+	"spaceofcheng/services/models/model"
9
+	"spaceofcheng/services/service/customer"
10
+	"spaceofcheng/services/utils"
11
+)
12
+
13
+// CustomerController 用户
14
+type CustomerController struct {
15
+	serv *customer.CustomerServ
16
+	controllers.BaseController
17
+}
18
+
19
+// Constructor 初始化 Controller
20
+// @Title Constructor
21
+// @Description 初始化 Controller, 系统自动调用
22
+func (c *CustomerController) Constructor() {
23
+	c.serv = customer.NewCustomerServ(c.Context)
24
+}
25
+
26
+// CustWXList 获取客户列表
27
+func (c *CustomerController) CustWXList() {
28
+	phone := c.GetString("phone")
29
+	page, _ := c.GetInt("page")
30
+
31
+	custList, total, err := c.serv.GetCustWithWXList(phone, page)
32
+	if err != nil {
33
+		utils.LogError("获取客户列表失败: " + err.Error())
34
+		c.ResponseError(
35
+			errors.New("获取客户列表失败"),
36
+			http.StatusInternalServerError,
37
+		)
38
+	}
39
+
40
+	c.ResponseJSON(map[string]interface{}{
41
+		"list":  custList,
42
+		"total": total,
43
+	})
44
+}
45
+
46
+// GetCustWXByID 获取用户信息
47
+func (c *CustomerController) GetCustWXByID() {
48
+	userMapRaw := c.Context.Get("userMap")
49
+	if userMapRaw == nil {
50
+		c.ResponseError(errors.New("获取用户信息失败, 请确认使用微信浏览"))
51
+	}
52
+
53
+	userMap := userMapRaw.(model.TaUserMapping)
54
+
55
+	if userMap.UserType == models.USERMAP_USER {
56
+		// 如果是用户
57
+		userID := userMap.UserId
58
+		user, err := c.serv.GetCustUserByID(userID)
59
+		if err != nil {
60
+			utils.LogError(err)
61
+			c.ResponseError(errors.New("获取用户信息失败, 请重试"))
62
+		}
63
+
64
+		c.ResponseJSON(map[string]interface{}{
65
+			"user":     user,
66
+			"userType": userMap.UserType,
67
+		})
68
+	} else {
69
+		// 如果是客户
70
+		custID := userMap.UserId
71
+		cust, err := c.serv.GetCustWithWXByID(custID)
72
+		if err != nil {
73
+			utils.LogError(err)
74
+			c.ResponseError(errors.New("获取用户信息失败, 请重试"))
75
+		}
76
+
77
+		c.ResponseJSON(map[string]interface{}{
78
+			"customer": cust,
79
+			"userType": userMap.UserType,
80
+		})
81
+	}
82
+}
83
+
84
+// SignIn 微信登录
85
+func (c *CustomerController) SignIn() {
86
+	phone := c.GetString("phone")
87
+	captcha := c.GetString("captcha")
88
+
89
+	if err := utils.ValidCaptcha(phone, captcha); err != nil {
90
+		c.ResponseError(err)
91
+	}
92
+
93
+	userMapping := c.Context.Get("userMap").(model.TaUserMapping)
94
+
95
+	cust, err := c.serv.BindWechatUser(&userMapping, phone)
96
+	if err != nil {
97
+		c.ResponseError(err)
98
+	}
99
+
100
+	c.SetSession(controllers.SNCustID, cust.CustomerId)
101
+
102
+	c.ResponseJSON("ok")
103
+}
104
+
105
+// SignUp 注册会员
106
+func (c *CustomerController) SignUp() {
107
+	phone := c.GetString("phone")
108
+	captcha := c.GetString("captcha")
109
+	csID := c.GetString("case")
110
+	arID := c.GetString("sales")
111
+
112
+	if phone == "" || captcha == "" || csID == "" || arID == "" {
113
+		c.ResponseError(errors.New("请填写完整注册信息"))
114
+	}
115
+
116
+	if err := utils.ValidCaptcha(phone, captcha); err != nil {
117
+		c.ResponseError(err)
118
+	}
119
+
120
+	userMapping := c.Context.Get("userMap").(model.TaUserMapping)
121
+
122
+	cust, err := c.serv.BindWechatCust(&userMapping, phone, csID, arID)
123
+	if err != nil {
124
+		c.ResponseError(err)
125
+	}
126
+
127
+	c.SetSession(controllers.SNCustID, cust.CustomerId)
128
+
129
+	c.ResponseJSON("ok")
130
+}

+ 4
- 5
controllers/file.go 查看文件

@@ -1,13 +1,12 @@
1 1
 package controllers
2 2
 
3 3
 import (
4
+	"errors"
4 5
 	"spaceofcheng/services/utils"
5 6
 	"strconv"
6 7
 	"time"
7 8
 
8 9
 	"net/http"
9
-
10
-	"github.com/astaxie/beego/config"
11 10
 )
12 11
 
13 12
 // FileUpload 文件上传
@@ -23,9 +22,9 @@ func (c *BaseController) FileUpload() {
23 22
 }
24 23
 
25 24
 func (c *BaseController) uploadFileToOSS(field string) (string, error) {
26
-	aliConf, err := config.NewConfig("ini", "conf/aliyun.conf")
27
-	if err != nil {
28
-		return "", err
25
+	aliConf, ok := c.Configer[AliYunConf]
26
+	if !ok {
27
+		return "", errors.New("没有找到阿里云相关配置")
29 28
 	}
30 29
 
31 30
 	endpoint := aliConf.String("oss::Endpoint")

+ 42
- 0
controllers/message.go 查看文件

@@ -0,0 +1,42 @@
1
+package controllers
2
+
3
+import (
4
+	"errors"
5
+	"spaceofcheng/services/utils"
6
+)
7
+
8
+// SendCaptcha 发送验证码
9
+func (c *BaseController) SendCaptcha() {
10
+	phone := c.GetString("phone")
11
+
12
+	if phone == "" {
13
+		c.ResponseError(errors.New("请确定手机号码"))
14
+	}
15
+
16
+	if err := utils.SendCaptcha(phone); err != nil {
17
+		utils.LogError(err)
18
+		c.ResponseError(errors.New("验证码发送失败, 请重试"))
19
+	}
20
+
21
+	c.ResponseJSON("ok")
22
+}
23
+
24
+// ValidCaptcha 发送验证码
25
+func (c *BaseController) ValidCaptcha() {
26
+	phone := c.GetString("phone")
27
+
28
+	if phone == "" {
29
+		c.ResponseError(errors.New("请确定手机号码"))
30
+	}
31
+
32
+	captcha := c.GetString("captcha")
33
+	if captcha == "" {
34
+		c.ResponseError(errors.New("验证码不能为空"))
35
+	}
36
+
37
+	if err := utils.ValidCaptcha(phone, captcha); err != nil {
38
+		c.ResponseError(err)
39
+	}
40
+
41
+	c.ResponseJSON("ok")
42
+}

+ 6
- 2
controllers/session.go 查看文件

@@ -4,6 +4,10 @@ package controllers
4 4
 const (
5 5
 	// 用户ID
6 6
 	SNUserID = "userid"
7
-	// 用户类型
8
-	SNUserType = "userType"
7
+
8
+	// 客户ID
9
+	SNCustID = "custid"
10
+
11
+	// 内置 wechat_user
12
+	// 请勿使用 wechat_user 作为 session 的key
9 13
 )

+ 0
- 7
controllers/types.go 查看文件

@@ -1,12 +1,5 @@
1 1
 package controllers
2 2
 
3
-// 用户类型列表
4
-const (
5
-	UserGuest    = "guest"
6
-	UserCommon   = "common"
7
-	UserCustomer = "customer"
8
-)
9
-
10 3
 // JSONMessage 主要用于 Response 返回
11 4
 type JSONMessage struct {
12 5
 	Code    int         `json:"code"`

+ 62
- 0
controllers/user/user.go 查看文件

@@ -1,10 +1,14 @@
1 1
 package user
2 2
 
3 3
 import (
4
+	"errors"
5
+	"net/http"
4 6
 	"spaceofcheng/services/controllers"
5 7
 	"spaceofcheng/services/models/model"
6 8
 	"spaceofcheng/services/models/system"
7 9
 	"spaceofcheng/services/service"
10
+	"spaceofcheng/services/utils"
11
+	"time"
8 12
 )
9 13
 
10 14
 // UserController 用户
@@ -127,3 +131,61 @@ func (c *UserController) GetUserCustomer() {
127 131
 	}
128 132
 	c.ResponseJSON(customers)
129 133
 }
134
+
135
+// SignIn 用户登录
136
+func (c *UserController) SignIn() {
137
+	userName := c.GetString("username")
138
+	userPassword := c.GetString("userpassword")
139
+	token := c.GetString("token")
140
+	doRemember, _ := c.GetInt("doremember")
141
+
142
+	if token != "" {
143
+		tokenMap, err := utils.PareseToken(token)
144
+		if err != nil {
145
+			utils.LogError("解析用户 token 失败: " + err.Error())
146
+
147
+			c.ResponseError(
148
+				errors.New("登录失败, 用户名或者密码不正确"),
149
+				http.StatusBadRequest,
150
+			)
151
+		}
152
+
153
+		userName = tokenMap["user"].(string)
154
+		userPassword = tokenMap["password"].(string)
155
+	}
156
+
157
+	user, err := c.dao.CheckUserSignIn(userName, userPassword)
158
+	if err != nil {
159
+		utils.LogError("用户登录失败: " + err.Error())
160
+		c.ResponseError(
161
+			errors.New("登录失败, 用户名或者密码不正确"),
162
+			http.StatusBadRequest,
163
+		)
164
+	}
165
+
166
+	// 成功之后, 设置 session
167
+	c.SetSession(controllers.SNUserID, user.UserId)
168
+
169
+	if token == "" && doRemember != 0 {
170
+		var err error
171
+		token, err = utils.CreateToken(map[string]interface{}{
172
+			"user":     userName,
173
+			"password": userPassword,
174
+			"exp":      time.Now().Local().Add(7 * 24 * time.Hour), // 有效期是 7 天
175
+		})
176
+
177
+		if err != nil {
178
+			utils.LogError("生成 用户登录 token 失败: " + err.Error())
179
+		}
180
+	}
181
+
182
+	c.ResponseJSON(map[string]interface{}{
183
+		token: token,
184
+	})
185
+}
186
+
187
+// SignOut 用户登出
188
+func (c *UserController) SignOut() {
189
+	c.DestroySession()
190
+	c.ResponseJSON("ok")
191
+}

+ 0
- 0
log/common.log 查看文件


+ 19
- 0
models/constant.go 查看文件

@@ -1,11 +1,30 @@
1 1
 package models
2 2
 
3
+// 状态列表
3 4
 const (
4 5
 	STATUS_NORMAL = 1
5 6
 	STATUS_DEL    = -1
6 7
 )
7 8
 
9
+// 映射数据库的布尔型
10
+const (
11
+	BOOL_FALSE = 0
12
+	BOOL_TRUE  = 1
13
+)
14
+
15
+// 映射表账户类型
16
+const (
17
+	ACCMAP_WECHAT = "wechat"
18
+	ACCMAP_MINI   = "mini"
19
+)
20
+
8 21
 const (
9 22
 	IMAGETYPE_COVER  = "cover"
10 23
 	IMAGETYPE_DETAIL = "detail"
11 24
 )
25
+
26
+// 映射表用户类型
27
+const (
28
+	USERMAP_USER     = "user"
29
+	USERMAP_CUSTOMER = "customer"
30
+)

+ 193
- 0
models/customer/customer.go 查看文件

@@ -0,0 +1,193 @@
1
+package customer
2
+
3
+import (
4
+	"errors"
5
+	"spaceofcheng/services/models"
6
+	"spaceofcheng/services/models/model"
7
+	"spaceofcheng/services/utils"
8
+	"time"
9
+
10
+	"github.com/yl10/kit/guid"
11
+
12
+	"github.com/go-xorm/xorm"
13
+)
14
+
15
+// CustomerDAO 当前数据库操作对象
16
+type CustomerDAO struct {
17
+	ctx *utils.Context
18
+	db  *xorm.Session
19
+}
20
+
21
+// NewCustomerDAO New Inst
22
+func NewCustomerDAO(ctx *utils.Context) *CustomerDAO {
23
+	return &CustomerDAO{
24
+		ctx: ctx,
25
+		db:  ctx.DB,
26
+	}
27
+}
28
+
29
+// CustWithWXList 客户列表
30
+func (m *CustomerDAO) CustWithWXList(phone string, page ...int) ([]CustWithWX, int64, error) {
31
+	if phone == "" {
32
+		phone = "%"
33
+	} else {
34
+		phone = "%" + phone + "%"
35
+	}
36
+
37
+	pageNum := 10
38
+	if m.ctx.Get("pageNum") != nil {
39
+		pageNum = m.ctx.Get("pageNum").(int)
40
+	}
41
+
42
+	pg := 1
43
+	if len(page) > 0 {
44
+		pg = page[0]
45
+	}
46
+	offset := (pg - 1) * pageNum
47
+	if offset < 0 {
48
+		offset = 0
49
+	}
50
+
51
+	query := `
52
+		SELECT *
53
+		FROM
54
+			ta_customer t
55
+		LEFT JOIN ta_user_mapping s ON t.customer_id = s.user_id
56
+			AND s.user_type = '` + models.USERMAP_CUSTOMER + `'
57
+			AND s.account_type = '` + models.ACCMAP_WECHAT + `'
58
+		WHERE
59
+			t.phone like ?
60
+		AND t.status > ?
61
+		ORDER BY
62
+			t.create_date DESC
63
+	`
64
+
65
+	var cust []CustWithWX
66
+
67
+	cnt, err := utils.GetPageList(m.db, &cust, []int{pageNum, offset}, query, phone, models.STATUS_DEL)
68
+	if err != nil {
69
+		return nil, 0, err
70
+	}
71
+
72
+	return cust, cnt, nil
73
+}
74
+
75
+// GetCustWithWXByID 获取客户(微信)信息
76
+func (m *CustomerDAO) GetCustWithWXByID(custID string) (*CustWithWX, error) {
77
+	if custID == "" {
78
+		return nil, errors.New("获取客户信息失败")
79
+	}
80
+
81
+	cust := CustWithWX{}
82
+	query := `
83
+		SELECT *
84
+		FROM
85
+			ta_customer t
86
+		LEFT JOIN ta_user_mapping s ON t.customer_id = s.user_id
87
+			AND s.user_type = '` + models.USERMAP_CUSTOMER + `'
88
+			AND s.account_type = '` + models.ACCMAP_WECHAT + `'
89
+		WHERE
90
+			t.customer_id = ?
91
+	`
92
+
93
+	if _, err := m.db.SQL(query, custID).Get(&cust); err != nil {
94
+		return nil, err
95
+	}
96
+
97
+	return &cust, nil
98
+}
99
+
100
+// GetCustomerByPhone 依据手机号获取客户信息
101
+func (m *CustomerDAO) GetCustomerByPhone(phone string) (*model.TaCustomer, error) {
102
+	custs := []model.TaCustomer{}
103
+
104
+	if err := m.db.Where("phone=?", phone).Find(&custs); err != nil {
105
+		return nil, err
106
+	}
107
+
108
+	if len(custs) == 0 {
109
+		return nil, nil
110
+	}
111
+
112
+	if len(custs) > 0 {
113
+		return nil, errors.New("数据异常, 一个手机绑定了多个用户")
114
+	}
115
+
116
+	cust := custs[0]
117
+
118
+	return &cust, nil
119
+}
120
+
121
+// UpdateUserMapping 更新用户映射
122
+func (m *CustomerDAO) UpdateUserMapping(userMap *model.TaUserMapping, cols []string) error {
123
+	if userMap.MappingId == "" {
124
+		return errors.New("用户映射信息不存在")
125
+	}
126
+
127
+	_, err := m.db.Where("mapping_id=?", userMap.MappingId).Cols(cols...).Update(&userMap)
128
+	return err
129
+}
130
+
131
+// GetCaseByID 获取案场
132
+func (m *CustomerDAO) GetCaseByID(caseID string) (*model.SysCase, error) {
133
+	if caseID == "" {
134
+		return nil, errors.New("获取案场信息失败")
135
+	}
136
+
137
+	cs := model.SysCase{}
138
+	has, err := m.db.Where("case_id=?", caseID).Get(&cs)
139
+	if err != nil {
140
+		return nil, err
141
+	}
142
+
143
+	if !has {
144
+		return nil, nil
145
+	}
146
+
147
+	return &cs, nil
148
+}
149
+
150
+// GetUserByID 获取系统用户
151
+func (m *CustomerDAO) GetUserByID(userID string) (*model.SysUser, error) {
152
+	if userID == "" {
153
+		return nil, errors.New("获取相关人员信息失败")
154
+	}
155
+
156
+	user := model.SysUser{}
157
+	has, err := m.db.Where("user_id=?", userID).Get(&user)
158
+	if err != nil {
159
+		return nil, err
160
+	}
161
+
162
+	if !has {
163
+		return nil, nil
164
+	}
165
+
166
+	return &user, nil
167
+}
168
+
169
+// GetUserByPhone 依据手机号获取人员信息
170
+func (m *CustomerDAO) GetUserByPhone(phone string) (*model.SysUser, error) {
171
+	user := model.SysUser{}
172
+
173
+	has, err := m.db.Where("phone=?", phone).Get(&user)
174
+	if err != nil {
175
+		return nil, err
176
+	}
177
+
178
+	if !has {
179
+		return nil, nil
180
+	}
181
+
182
+	return &user, nil
183
+}
184
+
185
+// SaveCustomer 新增客户
186
+func (m *CustomerDAO) SaveCustomer(cust *model.TaCustomer) error {
187
+	cust.CustomerId = guid.NewGUIDString()
188
+	cust.CreateDate = time.Now().Local()
189
+	cust.Status = models.STATUS_NORMAL
190
+
191
+	_, err := m.db.Insert(&cust)
192
+	return err
193
+}

+ 12
- 0
models/customer/types.go 查看文件

@@ -0,0 +1,12 @@
1
+package customer
2
+
3
+import (
4
+	"spaceofcheng/services/models/model"
5
+)
6
+
7
+// CustWithWX 客户及微信相关信息
8
+type CustWithWX struct {
9
+	model.TaCustomer    `xorm:"extends"`
10
+	model.TaUserMapping `xorm:"extends"`
11
+	Points              int
12
+}

+ 6
- 8
models/model/sys_case_user.go 查看文件

@@ -5,14 +5,12 @@ import (
5 5
 )
6 6
 
7 7
 type SysCaseUser struct {
8
-	CaseUserId string `xorm:"not null pk VARCHAR(64)"`
9
-	OrgId      string `xorm:"VARCHAR(64)"`
10
-	CaseId     string `xorm:"VARCHAR(64)"`
11
-	UserName   string `xorm:"VARCHAR(50)"`
12
-	Tel        string `xorm:"VARCHAR(50)"`
13
-	UserType   string `xorm:"comment('案场管理员
14
-            咖啡师
15
-            消息收发员') VARCHAR(20)"`
8
+	CaseUserId string    `xorm:"not null pk VARCHAR(64)"`
9
+	OrgId      string    `xorm:"VARCHAR(64)"`
10
+	CaseId     string    `xorm:"VARCHAR(64)"`
11
+	UserName   string    `xorm:"VARCHAR(50)"`
12
+	Tel        string    `xorm:"VARCHAR(50)"`
13
+	UserType   string    `xorm:"comment('案场管理员 咖啡师 消息收发员') VARCHAR(20)"`
16 14
 	Status     int       `xorm:"SMALLINT(6)"`
17 15
 	CreateDate time.Time `xorm:"DATETIME"`
18 16
 }

+ 1
- 2
models/model/sys_wechat_conf.go 查看文件

@@ -3,8 +3,7 @@ package model
3 3
 type SysWechatConf struct {
4 4
 	ConfId string `xorm:"VARCHAR(64)"`
5 5
 	OrgId  string `xorm:"VARCHAR(64)"`
6
-	Type   int    `xorm:"comment('wechat 微信公众号
7
-            mini 小程序') SMALLINT(6)"`
6
+	Type   int    `xorm:"comment('wechat 微信公众号  mini 小程序') SMALLINT(6)"`
8 7
 	Appid  string `xorm:"VARCHAR(50)"`
9 8
 	Secret string `xorm:"VARCHAR(50)"`
10 9
 	Token  string `xorm:"VARCHAR(50)"`

+ 15
- 21
models/model/ta_account_change.go 查看文件

@@ -5,25 +5,19 @@ import (
5 5
 )
6 6
 
7 7
 type TaAccountChange struct {
8
-	DetailId   string `xorm:"not null pk VARCHAR(64)"`
9
-	AccountId  string `xorm:"VARCHAR(64)"`
10
-	UserId     string `xorm:"VARCHAR(64)"`
11
-	UserName   string `xorm:"VARCHAR(50)"`
12
-	OrgId      string `xorm:"VARCHAR(64)"`
13
-	CaseId     string `xorm:"VARCHAR(64)"`
14
-	ChangeType string `xorm:"comment('integral 积分
15
-            amount 城币') VARCHAR(20)"`
16
-	ChangeSource string `xorm:"comment('vip vip卡充值
17
-            orders 订单消费
18
-            register 注册
19
-            perfect 完善资料
20
-            recommend 推荐') VARCHAR(20)"`
21
-	SourceId   string  `xorm:"VARCHAR(64)"`
22
-	SourceName string  `xorm:"VARCHAR(255)"`
23
-	Amount     float32 `xorm:"FLOAT(8,2)"`
24
-	FloatType  string  `xorm:"comment('+
25
-            -') VARCHAR(5)"`
26
-	CreateDate time.Time `xorm:"DATETIME"`
27
-	CreateUser string    `xorm:"VARCHAR(64)"`
28
-	Status     int       `xorm:"SMALLINT(6)"`
8
+	DetailId     string    `xorm:"not null pk VARCHAR(64)"`
9
+	AccountId    string    `xorm:"VARCHAR(64)"`
10
+	UserId       string    `xorm:"VARCHAR(64)"`
11
+	UserName     string    `xorm:"VARCHAR(50)"`
12
+	OrgId        string    `xorm:"VARCHAR(64)"`
13
+	CaseId       string    `xorm:"VARCHAR(64)"`
14
+	ChangeType   string    `xorm:"comment('integral 积分  amount 城币') VARCHAR(20)"`
15
+	ChangeSource string    `xorm:"comment('vip vip卡充值  orders 订单消费  register 注册  perfect 完善资料  recommend 推荐') VARCHAR(20)"`
16
+	SourceId     string    `xorm:"VARCHAR(64)"`
17
+	SourceName   string    `xorm:"VARCHAR(255)"`
18
+	Amount       float32   `xorm:"FLOAT(8,2)"`
19
+	FloatType    string    `xorm:"comment('+  -') VARCHAR(5)"`
20
+	CreateDate   time.Time `xorm:"DATETIME"`
21
+	CreateUser   string    `xorm:"VARCHAR(64)"`
22
+	Status       int       `xorm:"SMALLINT(6)"`
29 23
 }

+ 2
- 3
models/model/ta_cms_case_image.go 查看文件

@@ -5,7 +5,6 @@ type TaCmsCaseImage struct {
5 5
 	CmsCaseId      string `xorm:"VARCHAR(64)"`
6 6
 	CaseImageUrl   string `xorm:"TEXT"`
7 7
 	Status         int    `xorm:"SMALLINT(6)"`
8
-	ImageType      string `xorm:"comment('cover:封面
9
-            detail:详情') VARCHAR(32)"`
10
-	Sort int `xorm:"INT(11)"`
8
+	ImageType      string `xorm:"comment('cover:封面  detail:详情') VARCHAR(32)"`
9
+	Sort           int    `xorm:"INT(11)"`
11 10
 }

+ 2
- 2
models/model/ta_cms_location.go 查看文件

@@ -1,6 +1,6 @@
1 1
 package model
2 2
 
3 3
 type TaCmsLocation struct {
4
-	LocationId string `xorm:"VARCHAR(64)"`
5
-	NewsId     string `xorm:"VARCHAR(64)"`
4
+	LocationId string `xorm:"not null pk VARCHAR(64)"`
5
+	NewsId     string `xorm:"not null pk VARCHAR(64)"`
6 6
 }

+ 1
- 0
models/model/ta_customer.go 查看文件

@@ -17,4 +17,5 @@ type TaCustomer struct {
17 17
 	RecommendName string    `xorm:"VARCHAR(50)"`
18 18
 	CreateDate    time.Time `xorm:"DATETIME"`
19 19
 	Status        int       `xorm:"SMALLINT(6)"`
20
+	UserId        string    `xorm:"VARCHAR(64)"`
20 21
 }

+ 0
- 25
models/model/ta_experience_card.go 查看文件

@@ -1,25 +0,0 @@
1
-package model
2
-
3
-import (
4
-	"time"
5
-)
6
-
7
-type TaExperienceCard struct {
8
-	CardId     string    `xorm:"not null pk VARCHAR(64)"`
9
-	CardTypeId string    `xorm:"VARCHAR(64)"`
10
-	SendType   string    `xorm:"comment('0案场 1渠道') VARCHAR(32)"`
11
-	VideoUrl   string    `xorm:"TEXT"`
12
-	CoverUrl   string    `xorm:"TEXT"`
13
-	Price      float32   `xorm:"FLOAT(64)"`
14
-	StartDate  time.Time `xorm:"DATETIME"`
15
-	EndDate    time.Time `xorm:"DATETIME"`
16
-	TotalCount int       `xorm:"INT(11)"`
17
-	SentCount  int       `xorm:"INT(11)"`
18
-	UsedCount  int       `xorm:"INT(11)"`
19
-	Status     string    `xorm:"comment('private未发布 public发布 over过期') VARCHAR(32)"`
20
-	CaseId     string    `xorm:"VARCHAR(64)"`
21
-	OrgId      string    `xorm:"VARCHAR(64)"`
22
-	CreateDate time.Time `xorm:"DATETIME"`
23
-	CreateUser string    `xorm:"VARCHAR(64)"`
24
-	IsOver     int       `xorm:"TINYINT(1)"`
25
-}

+ 20
- 21
models/model/ta_goods_orders.go 查看文件

@@ -5,25 +5,24 @@ import (
5 5
 )
6 6
 
7 7
 type TaGoodsOrders struct {
8
-	OrdersId   string    `xorm:"not null pk VARCHAR(64)"`
9
-	OrdersNo   string    `xorm:"VARCHAR(32)"`
10
-	OrgId      string    `xorm:"VARCHAR(64)"`
11
-	CaseId     string    `xorm:"VARCHAR(64)"`
12
-	AreaId     string    `xorm:"VARCHAR(64)"`
13
-	AreaName   string    `xorm:"VARCHAR(50)"`
14
-	TableId    string    `xorm:"VARCHAR(64)"`
15
-	TableName  string    `xorm:"VARCHAR(50)"`
16
-	Amount     string    `xorm:"DECIMAL(8,2)"`
17
-	CreateDate time.Time `xorm:"DATETIME"`
18
-	Status     int       `xorm:"SMALLINT(6)"`
19
-	PayType    int       `xorm:"comment('vip VIP卡城币抵用
20
-            coupon 优惠券抵用') SMALLINT(6)"`
21
-	UserType     int    `xorm:"SMALLINT(6)"`
22
-	UserId       string `xorm:"VARCHAR(64)"`
23
-	UserName     string `xorm:"VARCHAR(50)"`
24
-	OrdersNum    int    `xorm:"INT(11)"`
25
-	Remark       string `xorm:"TEXT"`
26
-	IsPay        int    `xorm:"TINYINT(1)"`
27
-	ActualAmount string `xorm:"DECIMAL(8,2)"`
28
-	CouponAmount string `xorm:"DECIMAL(8,2)"`
8
+	OrdersId     string    `xorm:"not null pk VARCHAR(64)"`
9
+	OrdersNo     string    `xorm:"VARCHAR(32)"`
10
+	OrgId        string    `xorm:"VARCHAR(64)"`
11
+	CaseId       string    `xorm:"VARCHAR(64)"`
12
+	AreaId       string    `xorm:"VARCHAR(64)"`
13
+	AreaName     string    `xorm:"VARCHAR(50)"`
14
+	TableId      string    `xorm:"VARCHAR(64)"`
15
+	TableName    string    `xorm:"VARCHAR(50)"`
16
+	Amount       string    `xorm:"DECIMAL(8,2)"`
17
+	CreateDate   time.Time `xorm:"DATETIME"`
18
+	Status       int       `xorm:"SMALLINT(6)"`
19
+	PayType      int       `xorm:"comment('vip VIP卡城币抵用 coupon 优惠券抵用') SMALLINT(6)"`
20
+	UserType     int       `xorm:"SMALLINT(6)"`
21
+	UserId       string    `xorm:"VARCHAR(64)"`
22
+	UserName     string    `xorm:"VARCHAR(50)"`
23
+	OrdersNum    int       `xorm:"INT(11)"`
24
+	Remark       string    `xorm:"TEXT"`
25
+	IsPay        int       `xorm:"TINYINT(1)"`
26
+	ActualAmount string    `xorm:"DECIMAL(8,2)"`
27
+	CouponAmount string    `xorm:"DECIMAL(8,2)"`
29 28
 }

+ 4
- 6
models/model/ta_user_mapping.go 查看文件

@@ -1,12 +1,10 @@
1 1
 package model
2 2
 
3 3
 type TaUserMapping struct {
4
-	MappingId string `xorm:"not null pk VARCHAR(64)"`
5
-	UserId    string `xorm:"VARCHAR(64)"`
6
-	UserType  string `xorm:"comment('customer 为会员
7
-            user 为后台用户') VARCHAR(50)"`
8
-	AccountType string `xorm:"comment('wechat 微信公众号
9
-            mini 小程序') VARCHAR(50)"`
4
+	MappingId   string `xorm:"not null pk VARCHAR(64)"`
5
+	UserId      string `xorm:"VARCHAR(64)"`
6
+	UserType    string `xorm:"comment('customer 为会员  user 为后台用户') VARCHAR(50)"`
7
+	AccountType string `xorm:"comment('wechat 微信公众号 mini 小程序') VARCHAR(50)"`
10 8
 	Openid      string `xorm:"VARCHAR(200)"`
11 9
 	Uuid        string `xorm:"VARCHAR(200)"`
12 10
 	AccountInfo string `xorm:"TEXT"`

+ 120
- 0
models/sys.go 查看文件

@@ -1,8 +1,12 @@
1 1
 package models
2 2
 
3 3
 import (
4
+	"errors"
5
+	"spaceofcheng/services/models/model"
4 6
 	"spaceofcheng/services/utils"
5 7
 
8
+	"github.com/yl10/kit/guid"
9
+
6 10
 	"github.com/go-xorm/xorm"
7 11
 )
8 12
 
@@ -19,3 +23,119 @@ func NewSysDAO(ctx *utils.Context) *SysDAO {
19 23
 		db:  ctx.DB,
20 24
 	}
21 25
 }
26
+
27
+// GetPureUserInfo 获取用户基本信息
28
+func (m *SysDAO) GetPureUserInfo(id string) (*model.SysUser, error) {
29
+	user := model.SysUser{}
30
+
31
+	has, err := m.db.Where("user_id=?", id).Get(&user)
32
+	if err != nil {
33
+		return nil, err
34
+	}
35
+
36
+	if !has {
37
+		return nil, errors.New("没有查询到 ID (" + id + ") 对应的用户")
38
+	}
39
+
40
+	if user.Status != STATUS_NORMAL {
41
+		return nil, errors.New("用户状态不正确")
42
+	}
43
+
44
+	return &user, nil
45
+}
46
+
47
+// GetUserMenu 获取用户菜单
48
+func (m *SysDAO) GetUserMenu(userID string) ([]model.SysMenu, error) {
49
+	query := `
50
+		SELECT t.*
51
+		FROM sys_menu t
52
+			JOIN sys_user_menu s ON t.menu_id = s.menu_id
53
+		WHERE s.user_id = ?
54
+			AND t.status = ?
55
+		ORDER BY t.order_no ASC
56
+	`
57
+
58
+	var menus []model.SysMenu
59
+	if err := m.db.SQL(query, userID, STATUS_NORMAL).Find(&menus); err != nil {
60
+		return nil, err
61
+	}
62
+
63
+	return menus, nil
64
+}
65
+
66
+// GetUserCase 获取用户案场
67
+func (m *SysDAO) GetUserCase(userID string) ([]model.SysUserCase, error) {
68
+	query := `
69
+		SELECT t.*
70
+		FROM sys_user_case t
71
+		WHERE s.user_id = ?
72
+			AND t.status = ?
73
+	`
74
+
75
+	var cases []model.SysUserCase
76
+	if err := m.db.SQL(query, userID, STATUS_NORMAL).Find(&cases); err != nil {
77
+		return nil, err
78
+	}
79
+
80
+	return cases, nil
81
+}
82
+
83
+// GetOrg 获取机构信息
84
+func (m *SysDAO) GetOrg(orgID string) (*model.SysOrg, error) {
85
+	var org model.SysOrg
86
+	has, err := m.db.Where("org_id=?", orgID).And("status=?", STATUS_NORMAL).Get(&org)
87
+	if err != nil {
88
+		return nil, err
89
+	}
90
+
91
+	if !has {
92
+		return nil, errors.New("没有查询到机构信息")
93
+	}
94
+
95
+	return &org, nil
96
+}
97
+
98
+// GetCustomer 获取用户信息
99
+// 暂时无法解决 一个用户 多组织架构的问题
100
+func (m *SysDAO) GetCustomer(custID string) (*model.TaCustomer, error) {
101
+	var cust model.TaCustomer
102
+
103
+	has, err := m.db.Where("customer_id=?", custID).And("status=?", STATUS_NORMAL).Get(&cust)
104
+	if err != nil {
105
+		return nil, err
106
+	}
107
+
108
+	if !has {
109
+		return nil, errors.New("没有查询到客户 (id: " + custID + ") 信息")
110
+	}
111
+
112
+	return &cust, nil
113
+}
114
+
115
+// GetUserMappingByOpenID 获取用户映射信息
116
+func (m *SysDAO) GetUserMappingByOpenID(openID string) ([]model.TaUserMapping, error) {
117
+	var users []model.TaUserMapping
118
+
119
+	err := m.db.Where("openid=?", openID).Find(&users)
120
+	return users, err
121
+}
122
+
123
+// UpdateUserMapping 保存用户映射信息
124
+func (m *SysDAO) UpdateUserMapping(user *model.TaUserMapping) error {
125
+	// 如果没有映射ID, 则新增记录
126
+	if user.MappingId == "" {
127
+		user.MappingId = guid.NewGUIDString()
128
+		_, err := m.db.Insert(user)
129
+		return err
130
+	}
131
+
132
+	// 否则更新记录
133
+	cols := []string{
134
+		"account_info",
135
+	}
136
+	_, err := m.db.Cols(cols...).
137
+		Where("account_type=?", user.AccountType).
138
+		And("openid=?", user.Openid).
139
+		Update(&user)
140
+	return err
141
+}

+ 43
- 0
models/system/user.go 查看文件

@@ -1,6 +1,7 @@
1 1
 package system
2 2
 
3 3
 import (
4
+	"errors"
4 5
 	"spaceofcheng/services/models"
5 6
 	"spaceofcheng/services/models/model"
6 7
 	"spaceofcheng/services/utils"
@@ -328,3 +329,45 @@ func (m *UserDAO) GetUserCustomer(userid string, page int, pageSize int) ([]mode
328 329
 	err := m.db.Where("status>"+strconv.Itoa(models.STATUS_DEL)).And("recommend_id=?", userid).Limit(pageSize, page*pageSize).Desc("create_date").Find(&customers)
329 330
 	return customers, err
330 331
 }
332
+
333
+// GetUserByName 依据账户获取人员信息
334
+func (m *UserDAO) GetUserByName(userName string) (*model.SysUser, error) {
335
+	user := model.SysUser{}
336
+
337
+	has, err := m.db.Where("user_name=?", userName).Get(&user)
338
+	if err != nil {
339
+		return nil, err
340
+	}
341
+
342
+	if !has {
343
+		return nil, nil
344
+	}
345
+
346
+	return &user, nil
347
+}
348
+
349
+// GetUserByPhone 依据手机号获取人员信息
350
+func (m *UserDAO) GetUserByPhone(phone string) (*model.SysUser, error) {
351
+	user := model.SysUser{}
352
+
353
+	has, err := m.db.Where("phone=?", phone).Get(&user)
354
+	if err != nil {
355
+		return nil, err
356
+	}
357
+
358
+	if !has {
359
+		return nil, nil
360
+	}
361
+
362
+	return &user, nil
363
+}
364
+
365
+// UpdateUserMapping 更新用户映射
366
+func (m *UserDAO) UpdateUserMapping(userMap *model.TaUserMapping, cols []string) error {
367
+	if userMap.MappingId == "" {
368
+		return errors.New("用户映射信息不存在")
369
+	}
370
+
371
+	_, err := m.db.Where("mapping_id=?", userMap.MappingId).Cols(cols...).Update(&userMap)
372
+	return err
373
+}

+ 51
- 38
routers/common.go 查看文件

@@ -2,6 +2,7 @@ package routers
2 2
 
3 3
 import (
4 4
 	"spaceofcheng/services/controllers"
5
+	"spaceofcheng/services/controllers/customer"
5 6
 	"spaceofcheng/services/controllers/goods"
6 7
 	"spaceofcheng/services/controllers/message"
7 8
 	"spaceofcheng/services/controllers/user"
@@ -13,53 +14,61 @@ func getCommonRoutes() beego.LinkNamespace {
13 14
 	prefix := beego.AppConfig.String("api::common")
14 15
 
15 16
 	return beego.NSNamespace(prefix,
16
-		beego.NSRouter("/goodstype", &goods.GoodsController{}, "get:GetGoodsType"),
17
-		beego.NSRouter("/goodstype/:typeid", &goods.GoodsController{}, "get:GetGoodsTypeByID"),
18
-		beego.NSRouter("/goodstype", &goods.GoodsController{}, "post:SaveGoodsType"),
19
-		beego.NSRouter("/goodstype", &goods.GoodsController{}, "put:SaveGoodsType"),
20
-		beego.NSRouter("/goodstype/:typeid", &goods.GoodsController{}, "delete:DelGoodsType"),
17
+		// 商品分类
18
+		beego.NSRouter("/type/goods", &goods.GoodsController{}, "get:GetGoodsType"),
19
+		beego.NSRouter("/type/goods/:typeid", &goods.GoodsController{}, "get:GetGoodsTypeByID"),
20
+		beego.NSRouter("/type/goods", &goods.GoodsController{}, "post:SaveGoodsType"),
21
+		beego.NSRouter("/type/goods/:typeid", &goods.GoodsController{}, "put:SaveGoodsType"),
22
+		beego.NSRouter("/type/goods/:typeid", &goods.GoodsController{}, "delete:DelGoodsType"),
21 23
 
22
-		beego.NSRouter("/goodspec", &goods.GoodsController{}, "get:GetGoodsSpec"),
23
-		beego.NSRouter("/goodspec/:specid", &goods.GoodsController{}, "get:GetGoodsSpecByID"),
24
-		beego.NSRouter("/goodspec", &goods.GoodsController{}, "post:SaveGoodsSpec"),
25
-		beego.NSRouter("/goodspec", &goods.GoodsController{}, "put:SaveGoodsSpec"),
26
-		beego.NSRouter("/goodspec/:specid", &goods.GoodsController{}, "delete:DelGoodsSpec"),
24
+		// 商品规格
25
+		beego.NSRouter("/spec/goods", &goods.GoodsController{}, "get:GetGoodsSpec"),
26
+		beego.NSRouter("/spec/goods/:specid", &goods.GoodsController{}, "get:GetGoodsSpecByID"),
27
+		beego.NSRouter("/spec/goods", &goods.GoodsController{}, "post:SaveGoodsSpec"),
28
+		beego.NSRouter("/spec/goods/:specid", &goods.GoodsController{}, "put:SaveGoodsSpec"),
29
+		beego.NSRouter("/spec/goods/:specid", &goods.GoodsController{}, "delete:DelGoodsSpec"),
27 30
 
31
+		// 系统用户
28 32
 		beego.NSRouter("/user", &user.UserController{}, "get:GetUserList"),
29 33
 		beego.NSRouter("/user/:userid", &user.UserController{}, "get:GetUserByID"),
34
+		beego.NSRouter("/user/:userid/password", &user.UserController{}, "put:UpdatePassword"),
35
+		beego.NSRouter("/user/password/reset", &user.UserController{}, "put:ResetPassword"),
36
+		beego.NSRouter("/signout", &user.UserController{}, "post:SignOut"),
30 37
 
31
-		beego.NSRouter("/pwd/reset", &user.UserController{}, "put:ResetPassword"),
32
-		beego.NSRouter("/pwd/update", &user.UserController{}, "put:UpdatePassword"),
38
+		// cms 位置
39
+		beego.NSRouter("/cms/location", &message.MessageController{}, "get:GetLocations"),
40
+		beego.NSRouter("/cms/location/:locationid", &message.MessageController{}, "get:GetLocationById"),
41
+		beego.NSRouter("/cms/location", &message.MessageController{}, "post:SaveLocation"),
42
+		beego.NSRouter("/cms/location/:locationid", &message.MessageController{}, "put:SaveLocation"),
43
+		beego.NSRouter("/cms/location/:locationid", &message.MessageController{}, "delete:DelLocation"),
33 44
 
34
-		beego.NSRouter("/location", &message.MessageController{}, "get:GetLocations"),
35
-		beego.NSRouter("/location/:locationid", &message.MessageController{}, "get:GetLocationById"),
36
-		beego.NSRouter("/location", &message.MessageController{}, "post:SaveLocation"),
37
-		beego.NSRouter("/location", &message.MessageController{}, "put:SaveLocation"),
38
-		beego.NSRouter("/location/:locationid", &message.MessageController{}, "delete:DelLocation"),
45
+		// cms
46
+		beego.NSRouter("/cms/info", &message.MessageController{}, "get:GetCmsInfoList"),
47
+		beego.NSRouter("/cms/info/:infoid", &message.MessageController{}, "get:GetCmsInfoByID"),
48
+		beego.NSRouter("/cms/info", &message.MessageController{}, "post:SaveCmsInfo"),
49
+		beego.NSRouter("/cms/info/:infoid", &message.MessageController{}, "put:SaveCmsInfo"),
50
+		beego.NSRouter("/cms/info/:infoid", &message.MessageController{}, "delete:DelCmsInfo"),
39 51
 
40
-		beego.NSRouter("/cmsinfo", &message.MessageController{}, "get:GetCmsInfoList"),
41
-		beego.NSRouter("/cmsinfo/:infoid", &message.MessageController{}, "get:GetCmsInfoByID"),
42
-		beego.NSRouter("/cmsinfo", &message.MessageController{}, "post:SaveCmsInfo"),
43
-		beego.NSRouter("/cmsinfo", &message.MessageController{}, "put:SaveCmsInfo"),
44
-		beego.NSRouter("/cmsinfo/:infoid", &message.MessageController{}, "delete:DelCmsInfo"),
52
+		// cms 图片
53
+		beego.NSRouter("/cms/image", &message.MessageController{}, "get:GetImgList"),
54
+		beego.NSRouter("/cms/image/:imgid", &message.MessageController{}, "get:GetImgByID"),
55
+		beego.NSRouter("/cms/image", &message.MessageController{}, "post:SaveImage"),
56
+		beego.NSRouter("/cms/image/:imgid", &message.MessageController{}, "put:SaveImage"),
57
+		beego.NSRouter("/cms/image/:imgid", &message.MessageController{}, "delete:DelImg"),
45 58
 
46
-		beego.NSRouter("/cmsimg", &message.MessageController{}, "get:GetImgList"),
47
-		beego.NSRouter("/cmsimg/:imgid", &message.MessageController{}, "get:GetImgByID"),
48
-		beego.NSRouter("/cmsimg", &message.MessageController{}, "post:SaveImage"),
49
-		beego.NSRouter("/cmsimg", &message.MessageController{}, "put:SaveImage"),
50
-		beego.NSRouter("/cmsimg/:imgid", &message.MessageController{}, "delete:DelImg"),
59
+		// cms 消息
60
+		beego.NSRouter("/cms/news", &message.MessageController{}, "get:GetNews"),
61
+		beego.NSRouter("/cms/news/:newsid", &message.MessageController{}, "get:GetNewsByID"),
62
+		beego.NSRouter("/cms/news", &message.MessageController{}, "post:SaveNews"),
63
+		beego.NSRouter("/cms/news/:newsid", &message.MessageController{}, "put:SaveNews"),
64
+		beego.NSRouter("/cms/news/:newsid", &message.MessageController{}, "delete:DelNews"),
51 65
 
52
-		beego.NSRouter("/news", &message.MessageController{}, "get:GetNews"),
53
-		beego.NSRouter("/news/:newsid", &message.MessageController{}, "get:GetNewsByID"),
54
-		beego.NSRouter("/news", &message.MessageController{}, "post:SaveNews"),
55
-		beego.NSRouter("/news", &message.MessageController{}, "put:SaveNews"),
56
-		beego.NSRouter("/news/:newsid", &message.MessageController{}, "delete:DelNews"),
57
-
58
-		beego.NSRouter("/cmscase", &message.MessageController{}, "get:GetCmsCase"),
59
-		beego.NSRouter("/cmscase/:cmscaseid", &message.MessageController{}, "get:GetCmsCaseByID"),
60
-		beego.NSRouter("/cmscase", &message.MessageController{}, "post:SaveCmsCase"),
61
-		beego.NSRouter("/cmscase", &message.MessageController{}, "put:SaveCmsCase"),
62
-		beego.NSRouter("/cmscase/:cmscaseid", &message.MessageController{}, "delete:DelCmsCase"),
66
+		// cms 案场
67
+		beego.NSRouter("/cms/case", &message.MessageController{}, "get:GetCmsCase"),
68
+		beego.NSRouter("/cms/case/:cmscaseid", &message.MessageController{}, "get:GetCmsCaseByID"),
69
+		beego.NSRouter("/cms/case", &message.MessageController{}, "post:SaveCmsCase"),
70
+		beego.NSRouter("/cms/case/:cmscaseid", &message.MessageController{}, "put:SaveCmsCase"),
71
+		beego.NSRouter("/cms/case/:cmscaseid", &message.MessageController{}, "delete:DelCmsCase"),
63 72
 
64 73
 		beego.NSRouter("/caseuser", &message.MessageController{}, "get:GetCaseUserByCase"),
65 74
 		beego.NSRouter("/caseuserbytype", &message.MessageController{}, "get:GetCaseUserByType"),
@@ -68,6 +77,10 @@ func getCommonRoutes() beego.LinkNamespace {
68 77
 		beego.NSRouter("/caseuser", &message.MessageController{}, "put:SaveCaseUser"),
69 78
 		beego.NSRouter("/caseuser/:userid", &message.MessageController{}, "delete:DelCaseUser"),
70 79
 
80
+		// 文件
71 81
 		beego.NSRouter("/file", &controllers.BaseController{}, "post:FileUpload"),
82
+
83
+		// 会员
84
+		beego.NSRouter("/customer", &customer.CustomerController{}, "get:CustWXList"),
72 85
 	)
73 86
 }

+ 19
- 4
routers/guest.go 查看文件

@@ -1,7 +1,10 @@
1 1
 package routers
2 2
 
3 3
 import (
4
+	"spaceofcheng/services/controllers"
5
+	"spaceofcheng/services/controllers/customer"
4 6
 	"spaceofcheng/services/controllers/message"
7
+	"spaceofcheng/services/controllers/user"
5 8
 
6 9
 	"github.com/astaxie/beego"
7 10
 )
@@ -10,9 +13,21 @@ func getGuestRoutes() beego.LinkNamespace {
10 13
 	prefix := beego.AppConfig.String("api::guest")
11 14
 
12 15
 	return beego.NSNamespace(prefix,
13
-		beego.NSRouter("/cmsinfo", &message.MessageController{}, "get:GetCmsInfoByLocation"),
14
-		beego.NSRouter("/cmsimg", &message.MessageController{}, "get:GetImgByLocation"),
15
-		beego.NSRouter("/cmsnews", &message.MessageController{}, "get:GetNewsByLocation"),
16
-		beego.NSRouter("/cmscase", &message.MessageController{}, "get:GetCmsCaseList"),
16
+		// cms
17
+		beego.NSRouter("/cms/info", &message.MessageController{}, "get:GetCmsInfoByLocation"),
18
+		beego.NSRouter("/cms/img", &message.MessageController{}, "get:GetImgByLocation"),
19
+		beego.NSRouter("/cms/news", &message.MessageController{}, "get:GetNewsByLocation"),
20
+		beego.NSRouter("/cms/case", &message.MessageController{}, "get:GetCmsCaseList"),
21
+
22
+		// 验证码 获取, 校验
23
+		beego.NSRouter("/captcha", &controllers.BaseController{}, "get:SendCaptcha"),
24
+		beego.NSRouter("/captcha", &controllers.BaseController{}, "post:ValidCaptcha"),
25
+
26
+		// 微信 登录, 注册
27
+		beego.NSRouter("/wxsignin", &customer.CustomerController{}, "post:SignIn"),
28
+		beego.NSRouter("/wxsignup", &customer.CustomerController{}, "post:SignUp"),
29
+
30
+		// 登录
31
+		beego.NSRouter("/signin", &user.UserController{}, "post:SignIn"),
17 32
 	)
18 33
 }

+ 3
- 0
routers/router.go 查看文件

@@ -23,6 +23,9 @@ func init() {
23 23
 		// 通用需要鉴权路由
24 24
 		getCommonRoutes(),
25 25
 
26
+		// 微信路由
27
+		getWechatRoutes(),
28
+
26 29
 		// 不需要鉴权的路由
27 30
 		getGuestRoutes(),
28 31
 	)

+ 78
- 0
routers/wechat.go 查看文件

@@ -1 +1,79 @@
1 1
 package routers
2
+
3
+import (
4
+	"spaceofcheng/services/controllers"
5
+	"spaceofcheng/services/controllers/customer"
6
+	"spaceofcheng/services/controllers/goods"
7
+	"spaceofcheng/services/controllers/message"
8
+	"spaceofcheng/services/controllers/user"
9
+
10
+	"github.com/astaxie/beego"
11
+)
12
+
13
+func getWechatRoutes() beego.LinkNamespace {
14
+	prefix := beego.AppConfig.String("api::wechat")
15
+
16
+	return beego.NSNamespace(prefix,
17
+		// 商品分类
18
+		beego.NSRouter("/type/goods", &goods.GoodsController{}, "get:GetGoodsType"),
19
+		beego.NSRouter("/type/goods/:typeid", &goods.GoodsController{}, "get:GetGoodsTypeByID"),
20
+		beego.NSRouter("/type/goods", &goods.GoodsController{}, "post:SaveGoodsType"),
21
+		beego.NSRouter("/type/goods/:typeid", &goods.GoodsController{}, "put:SaveGoodsType"),
22
+		beego.NSRouter("/type/goods/:typeid", &goods.GoodsController{}, "delete:DelGoodsType"),
23
+
24
+		// 商品规格
25
+		beego.NSRouter("/spec/goods", &goods.GoodsController{}, "get:GetGoodsSpec"),
26
+		beego.NSRouter("/spec/goods/:specid", &goods.GoodsController{}, "get:GetGoodsSpecByID"),
27
+		beego.NSRouter("/spec/goods", &goods.GoodsController{}, "post:SaveGoodsSpec"),
28
+		beego.NSRouter("/spec/goods/:specid", &goods.GoodsController{}, "put:SaveGoodsSpec"),
29
+		beego.NSRouter("/spec/goods/:specid", &goods.GoodsController{}, "delete:DelGoodsSpec"),
30
+
31
+		// 系统用户
32
+		beego.NSRouter("/user", &user.UserController{}, "get:GetUserList"),
33
+		beego.NSRouter("/user/:userid", &user.UserController{}, "get:GetUserByID"),
34
+		beego.NSRouter("/user/:userid/password", &user.UserController{}, "put:UpdatePassword"),
35
+		beego.NSRouter("/user/password/reset", &user.UserController{}, "put:ResetPassword"),
36
+		beego.NSRouter("/signout", &user.UserController{}, "post:SignOut"),
37
+
38
+		// cms 位置
39
+		beego.NSRouter("/cms/location", &message.MessageController{}, "get:GetLocations"),
40
+		beego.NSRouter("/cms/location/:locationid", &message.MessageController{}, "get:GetLocationById"),
41
+		beego.NSRouter("/cms/location", &message.MessageController{}, "post:SaveLocation"),
42
+		beego.NSRouter("/cms/location/:locationid", &message.MessageController{}, "put:SaveLocation"),
43
+		beego.NSRouter("/cms/location/:locationid", &message.MessageController{}, "delete:DelLocation"),
44
+
45
+		// cms
46
+		beego.NSRouter("/cms/info", &message.MessageController{}, "get:GetCmsInfoList"),
47
+		beego.NSRouter("/cms/info/:infoid", &message.MessageController{}, "get:GetCmsInfoByID"),
48
+		beego.NSRouter("/cms/info", &message.MessageController{}, "post:SaveCmsInfo"),
49
+		beego.NSRouter("/cms/info/:infoid", &message.MessageController{}, "put:SaveCmsInfo"),
50
+		beego.NSRouter("/cms/info/:infoid", &message.MessageController{}, "delete:DelCmsInfo"),
51
+
52
+		// cms 图片
53
+		beego.NSRouter("/cms/image", &message.MessageController{}, "get:GetImgList"),
54
+		beego.NSRouter("/cms/image/:imgid", &message.MessageController{}, "get:GetImgByID"),
55
+		beego.NSRouter("/cms/image", &message.MessageController{}, "post:SaveImage"),
56
+		beego.NSRouter("/cms/image/:imgid", &message.MessageController{}, "put:SaveImage"),
57
+		beego.NSRouter("/cms/image/:imgid", &message.MessageController{}, "delete:DelImg"),
58
+
59
+		// cms 消息
60
+		beego.NSRouter("/cms/news", &message.MessageController{}, "get:GetNews"),
61
+		beego.NSRouter("/cms/news/:newsid", &message.MessageController{}, "get:GetNewsByID"),
62
+		beego.NSRouter("/cms/news", &message.MessageController{}, "post:SaveNews"),
63
+		beego.NSRouter("/cms/news/:newsid", &message.MessageController{}, "put:SaveNews"),
64
+		beego.NSRouter("/cms/news/:newsid", &message.MessageController{}, "delete:DelNews"),
65
+
66
+		// cms 案场
67
+		beego.NSRouter("/cms/case", &message.MessageController{}, "get:GetCmsCase"),
68
+		beego.NSRouter("/cms/case/:cmscaseid", &message.MessageController{}, "get:GetCmsCaseByID"),
69
+		beego.NSRouter("/cms/case", &message.MessageController{}, "post:SaveCmsCase"),
70
+		beego.NSRouter("/cms/case/:cmscaseid", &message.MessageController{}, "put:SaveCmsCase"),
71
+		beego.NSRouter("/cms/case/:cmscaseid", &message.MessageController{}, "delete:DelCmsCase"),
72
+
73
+		// 文件
74
+		beego.NSRouter("/file", &controllers.BaseController{}, "post:FileUpload"),
75
+
76
+		// 会员
77
+		beego.NSRouter("/customer", &customer.CustomerController{}, "get:CustWXList"),
78
+	)
79
+}

+ 238
- 0
service/customer/customer.go 查看文件

@@ -0,0 +1,238 @@
1
+package customer
2
+
3
+import (
4
+	"errors"
5
+	"spaceofcheng/services/models"
6
+	"spaceofcheng/services/models/customer"
7
+	"spaceofcheng/services/models/model"
8
+	"spaceofcheng/services/service/events"
9
+	"spaceofcheng/services/utils"
10
+	"strconv"
11
+)
12
+
13
+// CustomerServ 系统处理
14
+type CustomerServ struct {
15
+	ctx *utils.Context
16
+	dao *customer.CustomerDAO
17
+}
18
+
19
+// NewCustomerServ 初始化
20
+func NewCustomerServ(ctx *utils.Context) *CustomerServ {
21
+	return &CustomerServ{
22
+		ctx: ctx,
23
+		dao: customer.NewCustomerDAO(ctx),
24
+	}
25
+}
26
+
27
+// GetCustWithWXList 获取客户列表
28
+func (s *CustomerServ) GetCustWithWXList(phone string, page ...int) ([]customer.CustWithWX, int64, error) {
29
+	return s.dao.CustWithWXList(phone, page...)
30
+}
31
+
32
+// GetCustWithWXByID 获取客户列表
33
+func (s *CustomerServ) GetCustWithWXByID(custID string) (*customer.CustWithWX, error) {
34
+	cust, err := s.dao.GetCustWithWXByID(custID)
35
+	if err != nil {
36
+		return nil, err
37
+	}
38
+
39
+	if cust.Status != models.STATUS_NORMAL {
40
+		return nil, errors.New("用户状态异常")
41
+	}
42
+
43
+	return cust, nil
44
+}
45
+
46
+// GetCustUserByID 获取用户信息(自定义内容)
47
+func (s *CustomerServ) GetCustUserByID(userID string) (*UserProfile, error) {
48
+	user, err := s.dao.GetUserByID(userID)
49
+	if err != nil {
50
+		return nil, err
51
+	}
52
+
53
+	if user.Status != models.STATUS_NORMAL {
54
+		return nil, errors.New("用户状态异常")
55
+	}
56
+
57
+	userProfile := UserProfile{
58
+		UserId:     user.UserId,
59
+		UserName:   user.UserName,
60
+		RealName:   user.RealName,
61
+		Sex:        user.Sex,
62
+		WorkNo:     user.WorkNo,
63
+		Email:      user.Email,
64
+		Phone:      user.Phone,
65
+		Headimgurl: user.Headimgurl,
66
+	}
67
+
68
+	return &userProfile, nil
69
+}
70
+
71
+// BindWechatUser 绑定微信用户
72
+func (s *CustomerServ) BindWechatUser(userMap *model.TaUserMapping, phone string) (*model.TaCustomer, error) {
73
+	user, err := s.dao.GetUserByPhone(phone)
74
+	if err != nil {
75
+		return nil, err
76
+	}
77
+
78
+	if user == nil || user.Status == models.STATUS_DEL {
79
+		return nil, errors.New("当前手机号未绑定管理员")
80
+	}
81
+
82
+	cust, err := s.dao.GetCustomerByPhone(phone)
83
+	if err != nil {
84
+		return nil, err
85
+	}
86
+
87
+	if cust == nil {
88
+		wxInfoRaw := s.ctx.Get("wxInfo")
89
+		if wxInfoRaw == nil {
90
+			return nil, errors.New("请确定使用微信端登录")
91
+		}
92
+
93
+		wxInfo := wxInfoRaw.(map[string]interface{})
94
+		newCust, err := s.SaveNewCustomer(wxInfo, "", "", user.UserId)
95
+		if err != nil {
96
+			return nil, err
97
+		}
98
+		cust = newCust
99
+	}
100
+
101
+	if cust.Status != models.STATUS_NORMAL {
102
+		return nil, errors.New("用户状态不正确")
103
+	}
104
+
105
+	// triggerRegiteEvent 触发注册事件
106
+	utils.EmitEvent(events.EvtRegiste, *cust)
107
+
108
+	if cust.CustomerId == userMap.UserId {
109
+		return cust, nil
110
+	}
111
+
112
+	// 更新用户映射信息
113
+	userMap.UserId = cust.CustomerId
114
+	if err := s.dao.UpdateUserMapping(userMap, []string{"user_id"}); err != nil {
115
+		utils.LogError("更新用户映射信息失败:" + err.Error())
116
+		return nil, errors.New("映射用户信息失败")
117
+	}
118
+
119
+	return cust, nil
120
+}
121
+
122
+// BindWechatCust 绑定微信用户
123
+func (s *CustomerServ) BindWechatCust(userMap *model.TaUserMapping, phone, caseID, userID string) (*model.TaCustomer, error) {
124
+	cust, err := s.dao.GetCustomerByPhone(phone)
125
+	if err != nil {
126
+		return nil, err
127
+	}
128
+
129
+	// 用户不存在, 则新增
130
+	if cust == nil {
131
+		wxInfoRaw := s.ctx.Get("wxInfo")
132
+		if wxInfoRaw == nil {
133
+			return nil, errors.New("请确定使用微信端登录")
134
+		}
135
+
136
+		wxInfo := wxInfoRaw.(map[string]interface{})
137
+		newCust, err := s.SaveNewCustomer(wxInfo, caseID, userID, "")
138
+		if err != nil {
139
+			return nil, err
140
+		}
141
+
142
+		cust = newCust
143
+	}
144
+
145
+	if cust.Status != models.STATUS_NORMAL {
146
+		return nil, errors.New("用户状态不正确")
147
+	}
148
+
149
+	// triggerRegiteEvent 触发注册事件
150
+	utils.EmitEvent(events.EvtRegiste, *cust)
151
+
152
+	if cust.CustomerId == userMap.UserId {
153
+		return cust, nil
154
+	}
155
+
156
+	// 更新用户映射信息
157
+	userMap.UserId = cust.CustomerId
158
+	if err := s.dao.UpdateUserMapping(userMap, []string{"user_id"}); err != nil {
159
+		utils.LogError("更新用户映射信息失败:" + err.Error())
160
+		return nil, errors.New("映射用户信息失败")
161
+	}
162
+
163
+	return cust, nil
164
+}
165
+
166
+// SaveNewCustomer 新增客户
167
+func (s *CustomerServ) SaveNewCustomer(wxInfo map[string]interface{}, caseID, arID, userID string) (*model.TaCustomer, error) {
168
+	if caseID == "" && arID == "" && userID == "" {
169
+		return nil, errors.New("新增信息失败, 无法确认人员类型")
170
+	}
171
+
172
+	// 微信相关字段
173
+	nickyName := wxInfo["nickname"].(string)
174
+	sex := wxInfo["sex"].(string)
175
+	headimgurl := wxInfo["headimgurl"].(string)
176
+
177
+	sexInt, _ := strconv.Atoi(sex)
178
+	if sexInt == 0 {
179
+		sexInt = 1 // 默认男性
180
+	}
181
+
182
+	cust := model.TaCustomer{
183
+		CustomerName: nickyName,
184
+		Name:         nickyName,
185
+		Sex:          sexInt,
186
+		Headimgurl:   headimgurl,
187
+	}
188
+
189
+	// 校验案场信息
190
+	if caseID != "" {
191
+		cs, err := s.dao.GetCaseByID(caseID)
192
+		if err != nil {
193
+			return nil, err
194
+		}
195
+
196
+		if cs == nil || cs.Status == models.STATUS_DEL {
197
+			return nil, errors.New("系统无该推荐案场")
198
+		}
199
+
200
+		cust.OrgId = cs.OrgId
201
+		cust.RecommendCase = cs.CaseId
202
+	}
203
+
204
+	// 校验推荐人
205
+	if arID != "" {
206
+		ar, err := s.dao.GetUserByID(arID)
207
+		if err != nil {
208
+			return nil, err
209
+		}
210
+
211
+		if ar == nil || ar.Status == models.STATUS_DEL {
212
+			return nil, errors.New("系统无该推荐人")
213
+		}
214
+
215
+		cust.OrgId = ar.OrgId
216
+		cust.RecommendId = ar.UserId
217
+		cust.RecommendName = ar.RealName
218
+	}
219
+
220
+	// 系统用户
221
+	if userID != "" {
222
+		user, err := s.dao.GetUserByID(userID)
223
+		if err != nil {
224
+			return nil, err
225
+		}
226
+
227
+		if user != nil && user.Status != models.STATUS_DEL {
228
+			cust.UserId = userID
229
+		}
230
+	}
231
+
232
+	if err := s.dao.SaveCustomer(&cust); err != nil {
233
+		utils.LogError("更新客户信息失败: " + err.Error())
234
+		return nil, errors.New("更新客户信息失败")
235
+	}
236
+
237
+	return &cust, nil
238
+}

+ 16
- 0
service/customer/types.go 查看文件

@@ -0,0 +1,16 @@
1
+package customer
2
+
3
+type UserProfile struct {
4
+	UserId     string
5
+	UserName   string
6
+	RealName   string
7
+	Sex        int
8
+	WorkNo     string
9
+	Email      string
10
+	Phone      string
11
+	Headimgurl string
12
+}
13
+
14
+func (t *UserProfile) TableName() string {
15
+	return "sys_user"
16
+}

+ 1
- 1
service/events/events.go 查看文件

@@ -54,7 +54,7 @@ func getAllEvents() (map[string][]string, error) {
54 54
 }
55 55
 
56 56
 var tsAction = func(e tinyevent.Event) error {
57
-	str := string(e.Payload)
57
+	str := e.Payload.(string)
58 58
 	fmt.Println(str)
59 59
 	return nil
60 60
 }

+ 98
- 1
service/sys.go 查看文件

@@ -1,7 +1,9 @@
1 1
 package service
2 2
 
3 3
 import (
4
+	"encoding/json"
4 5
 	"spaceofcheng/services/models"
6
+	"spaceofcheng/services/models/model"
5 7
 	"spaceofcheng/services/utils"
6 8
 )
7 9
 
@@ -23,6 +25,101 @@ func NewSysServ(ctx *utils.Context) *SysServ {
23 25
 	}
24 26
 }
25 27
 
26
-func (s *SysServ) GetUserByID(id string) error {
28
+// SetUserProfile 设置用户信息
29
+func (s *SysServ) SetUserProfile(id string) error {
30
+	user, err := s.dao.GetPureUserInfo(id)
31
+	if err != nil {
32
+		return utils.LogError("获取用户基本信息失败: " + err.Error())
33
+	}
34
+	s.ctx.Set("user", *user)
35
+
36
+	cases, err := s.dao.GetUserCase(id)
37
+	if err != nil {
38
+		return utils.LogError("获取用户案场信息失败: " + err.Error())
39
+	}
40
+	s.ctx.Set("cases", cases)
41
+
42
+	found := false
43
+	for _, cs := range cases {
44
+		if cs.IsBelong == models.BOOL_TRUE {
45
+			found = true
46
+			s.ctx.Set("currentCase", cs)
47
+		}
48
+	}
49
+
50
+	if !found {
51
+		return utils.LogError("用户没有设置默认案场")
52
+	}
53
+
54
+	org, err := s.dao.GetOrg(user.OrgId)
55
+	if err != nil {
56
+		return utils.LogError("获取用户组织信息失败: " + err.Error())
57
+	}
58
+	s.ctx.Set("org", *org)
59
+
60
+	return nil
61
+}
62
+
63
+// SetCustomer 设置客户信息
64
+func (s *SysServ) SetCustomer(id string) error {
65
+	cust, err := s.dao.GetCustomer(id)
66
+	if err != nil {
67
+		return utils.LogError("获取客户基本信息失败: " + err.Error())
68
+	}
69
+
70
+	s.ctx.Set("customer", *cust)
27 71
 	return nil
28 72
 }
73
+
74
+// CheckWechatUserMapping 校验并更新客户信息
75
+// 如果不存在, 则插入新数据
76
+func (s *SysServ) CheckWechatUserMapping(user map[string]interface{}) (*model.TaUserMapping, error) {
77
+	openID := user["openid"].(string)
78
+
79
+	uuID := ""
80
+	uuidRaw, ok := user["unionid"]
81
+	if ok {
82
+		uuID = uuidRaw.(string)
83
+	}
84
+
85
+	accountRaw, err := json.Marshal(user)
86
+	if err != nil {
87
+		return nil, err
88
+	}
89
+	account := string(accountRaw)
90
+
91
+	userMapping := model.TaUserMapping{
92
+		UserType:    models.USERMAP_CUSTOMER,
93
+		AccountType: models.ACCMAP_WECHAT,
94
+		Openid:      openID,
95
+		Uuid:        uuID,
96
+		AccountInfo: account,
97
+	}
98
+
99
+	// 查询数据库是否存在已有映射
100
+	userMapList, err := s.dao.GetUserMappingByOpenID(openID)
101
+	if err != nil {
102
+		return nil, err
103
+	}
104
+
105
+	// 如果存在
106
+	if len(userMapList) > 0 {
107
+		for _, um := range userMapList {
108
+			if userMapping.Openid == um.Openid &&
109
+				userMapping.AccountType == um.AccountType &&
110
+				userMapping.UserType == um.UserType {
111
+
112
+				// 存在的用户, 使用 ID 作为检查条件去更新
113
+				userMapping.MappingId = um.MappingId
114
+			}
115
+		}
116
+	}
117
+
118
+	// 更新数据库内容, 没有的话则插入
119
+	err = s.dao.UpdateUserMapping(&userMapping)
120
+	if err != nil {
121
+		return nil, err
122
+	}
123
+
124
+	return &userMapping, nil
125
+}

+ 23
- 5
service/user.go 查看文件

@@ -2,6 +2,7 @@ package service
2 2
 
3 3
 import (
4 4
 	"errors"
5
+	"spaceofcheng/services/models"
5 6
 	"spaceofcheng/services/models/model"
6 7
 	"spaceofcheng/services/models/system"
7 8
 	"spaceofcheng/services/utils"
@@ -9,11 +10,6 @@ import (
9 10
 	"github.com/yl10/kit/encrypt"
10 11
 )
11 12
 
12
-const (
13
-	USERTYPE_USER     = "user"
14
-	USERTYPE_CUSTOMER = "customer"
15
-)
16
-
17 13
 // UserServ 系统处理
18 14
 type UserServ struct {
19 15
 	ctx     *utils.Context
@@ -244,3 +240,25 @@ func (s *UserServ) GetUserCustomer(userid string, page int, pageSize int) ([]mod
244 240
 	customers, err := s.dao.GetUserCustomer(userid, page, pageSize)
245 241
 	return customers, err
246 242
 }
243
+
244
+// CheckUserSignIn 校验用户登录
245
+func (s *UserServ) CheckUserSignIn(userName, userPassword string) (*model.SysUser, error) {
246
+	user, err := s.dao.GetUserByName(userName)
247
+	if err != nil {
248
+		return nil, err
249
+	}
250
+
251
+	if user == nil {
252
+		return nil, errors.New("账户不存在")
253
+	}
254
+
255
+	if user.Status != models.STATUS_NORMAL {
256
+		return nil, errors.New("用户账户异常")
257
+	}
258
+
259
+	if !s.dao.ValidatePassword(user, userPassword) {
260
+		return nil, errors.New("用户密码不正确")
261
+	}
262
+
263
+	return user, nil
264
+}

二進制
swagger.zip 查看文件


+ 99
- 0
utils/captcha.go 查看文件

@@ -0,0 +1,99 @@
1
+package utils
2
+
3
+import (
4
+	"errors"
5
+	"math/rand"
6
+	"strconv"
7
+	"strings"
8
+	"time"
9
+)
10
+
11
+type cap struct {
12
+	Phone   string
13
+	Captcha string
14
+	Expire  time.Time
15
+}
16
+
17
+// CaptchaEngine 验证码引擎
18
+type CaptchaEngine struct {
19
+	capList map[string]cap
20
+}
21
+
22
+var capEngine *CaptchaEngine
23
+
24
+// NewCaptchaEngine 创建验证码引擎
25
+func NewCaptchaEngine() *CaptchaEngine {
26
+	return &CaptchaEngine{
27
+		capList: make(map[string]cap),
28
+	}
29
+}
30
+
31
+// SendCaptcha 发送验证码
32
+func SendCaptcha(phone string) error {
33
+	if phone == "" {
34
+		return errors.New("验证码发送错误: 没有手机号")
35
+	}
36
+
37
+	capEngine.SendCaptcha(phone)
38
+	return nil
39
+}
40
+
41
+// ValidCaptcha 校验 验证码
42
+func ValidCaptcha(phone, cap string) error {
43
+	if phone == "" {
44
+		return errors.New("验证码校验失败: 没有手机号")
45
+	}
46
+
47
+	return capEngine.ValidCaptcha(phone, cap)
48
+}
49
+
50
+// Random 获取随机数
51
+// 连续调用会有随机数不随机问题
52
+func (c *CaptchaEngine) Random(length int, phone string) string {
53
+	phoneInt, _ := strconv.ParseInt(phone, 10, 64)
54
+
55
+	r := rand.New(rand.NewSource(time.Now().UnixNano() + phoneInt))
56
+	dict := strings.Split("0123456789", "")
57
+
58
+	res := ""
59
+	for i := 0; i < length; i++ {
60
+		res = res + dict[r.Intn(10)]
61
+	}
62
+
63
+	return res
64
+}
65
+
66
+// SendCaptcha 发送验证码
67
+func (c *CaptchaEngine) SendCaptcha(phone string) {
68
+	theCap := cap{
69
+		Phone:   phone,
70
+		Captcha: capEngine.Random(6, phone),
71
+		Expire:  time.Now().Local().Add(1 * time.Minute),
72
+	}
73
+
74
+	c.capList[phone] = theCap
75
+
76
+	SendSMS("captcha", theCap.Phone, theCap.Captcha)
77
+}
78
+
79
+// ValidCaptcha 验证 验证码
80
+func (c *CaptchaEngine) ValidCaptcha(phone, cap string) error {
81
+	theCap, ok := c.capList[phone]
82
+	if !ok {
83
+		return errors.New("未发送过该号码的验证码")
84
+	}
85
+
86
+	if time.Now().Local().Before(theCap.Expire) {
87
+		return errors.New("验证码已过期")
88
+	}
89
+
90
+	if theCap.Captcha != cap {
91
+		return errors.New("验证码不正确")
92
+	}
93
+
94
+	return nil
95
+}
96
+
97
+func init() {
98
+	capEngine = NewCaptchaEngine()
99
+}

+ 18
- 0
utils/captcha_test.go 查看文件

@@ -0,0 +1,18 @@
1
+package utils_test
2
+
3
+import (
4
+	"spaceofcheng/services/utils"
5
+	"testing"
6
+	"time"
7
+)
8
+
9
+func TestRandom(t *testing.T) {
10
+	capEngine := utils.NewCaptchaEngine()
11
+	r1 := capEngine.Random(6, "13823838438")
12
+	time.Sleep(1 * time.Microsecond)
13
+	r2 := capEngine.Random(6, "13823838438")
14
+
15
+	if r1 == r2 {
16
+		t.Fatalf("Test CaptchaEngine Random fail, %s", r2)
17
+	}
18
+}

+ 1
- 1
utils/event.go 查看文件

@@ -7,7 +7,7 @@ import (
7 7
 var evtBus = &tinyevent.DefaultBus{}
8 8
 
9 9
 // EmitEvent 执行事件
10
-func EmitEvent(evt string, payload []byte) {
10
+func EmitEvent(evt string, payload interface{}) {
11 11
 	e := tinyevent.Event{
12 12
 		Name:    evt,
13 13
 		Payload: payload,

+ 34
- 0
utils/jwt.go 查看文件

@@ -0,0 +1,34 @@
1
+package utils
2
+
3
+import (
4
+	"errors"
5
+
6
+	jwt "github.com/dgrijalva/jwt-go"
7
+)
8
+
9
+var tokenSignedKey = []byte(`Yansen is so handsome!`)
10
+
11
+// CreateToken 获取token
12
+func CreateToken(info map[string]interface{}) (string, error) {
13
+	claims := jwt.MapClaims(info)
14
+	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
15
+	return token.SignedString(tokenSignedKey)
16
+}
17
+
18
+// PareseToken 解析 token
19
+func PareseToken(token string) (map[string]interface{}, error) {
20
+	tk, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
21
+		return tokenSignedKey, nil
22
+	})
23
+
24
+	if err != nil {
25
+		return nil, err
26
+	}
27
+
28
+	if claims, ok := tk.Claims.(jwt.MapClaims); ok && tk.Valid {
29
+		info := map[string]interface{}(claims)
30
+		return info, nil
31
+	}
32
+
33
+	return nil, errors.New("Token 解析 未知错误")
34
+}

+ 68
- 4
utils/log.go 查看文件

@@ -3,23 +3,87 @@ package utils
3 3
 import (
4 4
 	"errors"
5 5
 
6
-	"github.com/astaxie/beego"
6
+	"github.com/astaxie/beego/config"
7
+	"github.com/astaxie/beego/logs"
7 8
 )
8 9
 
10
+var defaultLogger *logs.BeeLogger
11
+var instances map[string]*logs.BeeLogger
12
+
13
+// NewLog 构造日志对象
14
+func NewLog(tp ...string) *logs.BeeLogger {
15
+	logType := "common"
16
+	if len(tp) > 0 {
17
+		if tp[0] != "" {
18
+			logType = tp[0]
19
+		}
20
+	}
21
+
22
+	if v, ok := instances[logType]; ok {
23
+		return v
24
+	}
25
+
26
+	log := logs.NewLogger()
27
+	instances[logType] = log
28
+
29
+	// 读取配置文件
30
+	conf, err := config.NewConfig("ini", "./conf/log.conf")
31
+	if err != nil {
32
+		log.SetLogger(logs.AdapterConsole)
33
+		return log
34
+	}
35
+
36
+	// 读文件存储位置
37
+	filename := conf.String(logType + "::filename")
38
+	// 输出级别
39
+	level := conf.String(logType + "::level")
40
+	if level == "" {
41
+		level = "error"
42
+	}
43
+
44
+	if filename == "" {
45
+		filename = "./" + logType + ".log"
46
+	}
47
+
48
+	log.Async()
49
+	log.SetLogger(logs.AdapterFile, `{"filename":"`+filename+`"}`)
50
+	return log
51
+}
52
+
9 53
 // LogError 错误日志
10 54
 func LogError(v ...interface{}) error {
11
-	beego.Error(v...)
55
+	log := instances["common"]
12 56
 
13 57
 	if len(v) > 0 {
14
-		switch err := v[0].(type) {
58
+		firstV := v[0]
59
+		leftV := v[1:]
60
+
61
+		switch err := firstV.(type) {
15 62
 		case string:
63
+			log.Error(err, leftV...)
16 64
 			return errors.New(err)
17 65
 		case error:
66
+			log.Error(err.Error(), leftV...)
18 67
 			return err
19 68
 		default:
20
-			return errors.New("Unknown error type")
69
+			msg := "Unknown error type"
70
+			log.Error(msg, leftV...)
71
+			return errors.New(msg)
21 72
 		}
22 73
 	}
23 74
 
24 75
 	return nil
25 76
 }
77
+
78
+// GetDefaultLogger 获取默认 logger
79
+func GetDefaultLogger() *logs.BeeLogger {
80
+	log := instances["common"]
81
+	return log
82
+}
83
+
84
+func init() {
85
+	instances = make(map[string]*logs.BeeLogger)
86
+	NewLog()
87
+
88
+	defaultLogger = GetDefaultLogger()
89
+}

+ 61
- 0
utils/pagenavi.go 查看文件

@@ -0,0 +1,61 @@
1
+package utils
2
+
3
+import (
4
+	"errors"
5
+	"regexp"
6
+	"strconv"
7
+
8
+	"github.com/go-xorm/xorm"
9
+)
10
+
11
+// GetPageList 获取列表
12
+func GetPageList(db *xorm.Session, target interface{}, limit []int, sqlorArgs ...interface{}) (int64, error) {
13
+	if sqlorArgs == nil || len(sqlorArgs) == 0 {
14
+		return 0, errors.New("SQL 语句不存在")
15
+	}
16
+
17
+	countSQLorArgs := GetCountSQL(sqlorArgs...)
18
+	cntRes, err := db.Query(countSQLorArgs...)
19
+	if err != nil {
20
+		return 0, err
21
+	}
22
+
23
+	cntStr := string(cntRes[0]["cnt"])
24
+	cnt, _ := strconv.ParseInt(cntStr, 10, 64)
25
+
26
+	sql, args := PackLimitToSQL(limit, sqlorArgs...)
27
+
28
+	err = db.SQL(sql, args...).Find(target)
29
+	if err != nil {
30
+		return 0, err
31
+	}
32
+
33
+	return cnt, nil
34
+}
35
+
36
+// GetCountSQL 获取计算 Count 的相关 SQL 脚本
37
+func GetCountSQL(sqlorArgs ...interface{}) []interface{} {
38
+	sql := sqlorArgs[0].(string)
39
+
40
+	re := regexp.MustCompile("(?ims)(select .* from)")
41
+	cntSQL := re.ReplaceAllString(sql, "select count(*) as cnt from")
42
+
43
+	newSQLorArgs := []interface{}{cntSQL}
44
+	newSQLorArgs = append(newSQLorArgs, sqlorArgs[1:])
45
+	return newSQLorArgs
46
+}
47
+
48
+// PackLimitToSQL 添加 limit 语句到 sql 最后
49
+func PackLimitToSQL(limit []int, sqlorArgs ...interface{}) (string, []interface{}) {
50
+	sql := sqlorArgs[0].(string)
51
+	args := sqlorArgs[1:]
52
+
53
+	switch len(limit) {
54
+	case 1:
55
+		return sql + " LIMIT " + strconv.Itoa(limit[0]), args
56
+	case 2:
57
+		return sql + " LIMIT " + strconv.Itoa(limit[0]) + " OFFSET " + strconv.Itoa(limit[1]), args
58
+	default:
59
+		return sql, args
60
+	}
61
+}

+ 71
- 0
utils/pagenavi_test.go 查看文件

@@ -0,0 +1,71 @@
1
+package utils_test
2
+
3
+import (
4
+	"spaceofcheng/services/utils"
5
+	"testing"
6
+)
7
+
8
+func TestGetCountSQL(t *testing.T) {
9
+	testCases := []map[string]string{
10
+		map[string]string{
11
+			"sql":      "Select field1, field2 From table",
12
+			"expected": "select count(*) as cnt from table",
13
+		},
14
+		map[string]string{
15
+			"sql": `Select 
16
+								field1, field2 From table where status = ?`,
17
+			"expected": "select count(*) as cnt from table where status = ?",
18
+		},
19
+	}
20
+
21
+	for inx, cs := range testCases {
22
+		sql := cs["sql"]
23
+		expected := cs["expected"]
24
+
25
+		var res []interface{}
26
+		if inx < 1 {
27
+			res = utils.GetCountSQL(sql)
28
+		} else {
29
+			res = utils.GetCountSQL(sql, inx)
30
+		}
31
+
32
+		if res == nil || len(res) == 0 {
33
+			t.Fatalf("Test GetCountSQL fail --1")
34
+		}
35
+
36
+		newSQL := res[0].(string)
37
+		if newSQL != expected {
38
+			t.Fatalf("Test GetCountSQL fail: %s", newSQL)
39
+		}
40
+	}
41
+}
42
+
43
+func TestPackLimitToSQL(t *testing.T) {
44
+	testCases := []map[string]string{
45
+		map[string]string{
46
+			"sql":      "Select * From table",
47
+			"expected": "Select * From table LIMIT 1 OFFSET 0",
48
+		},
49
+		map[string]string{
50
+			"sql":      "Select * From table",
51
+			"expected": "Select * From table LIMIT 1",
52
+		},
53
+	}
54
+
55
+	for inx, cs := range testCases {
56
+		sql := cs["sql"]
57
+		expected := cs["expected"]
58
+
59
+		var sqlRes string
60
+		if inx < 1 {
61
+			sqlRes, _ = utils.PackLimitToSQL([]int{inx + 1, inx}, sql)
62
+		} else {
63
+			sqlRes, _ = utils.PackLimitToSQL([]int{inx}, sql, inx)
64
+		}
65
+
66
+		if sqlRes != expected {
67
+			t.Fatalf("\n%v: Test PackLimitToSQL fail: %s", inx+1, sqlRes)
68
+		}
69
+	}
70
+
71
+}

+ 79
- 0
utils/sms.go 查看文件

@@ -0,0 +1,79 @@
1
+package utils
2
+
3
+import (
4
+	"bytes"
5
+	"fmt"
6
+	"net/http"
7
+	"strings"
8
+	"sync"
9
+
10
+	"github.com/astaxie/beego/config"
11
+)
12
+
13
+// SMSEngine 短信
14
+type SMSEngine struct {
15
+	url         string
16
+	method      string
17
+	contentType string
18
+	setting     config.Configer
19
+}
20
+
21
+var defaultSMS *SMSEngine
22
+var mtx *sync.Mutex
23
+
24
+// ResetSMSEngine 重置引擎
25
+func ResetSMSEngine(conf config.Configer) {
26
+	mtx.Lock()
27
+	defer mtx.Unlock()
28
+
29
+	newAPIURL := conf.String("url")
30
+
31
+	if defaultSMS == nil || defaultSMS.url != newAPIURL {
32
+		defaultSMS = &SMSEngine{
33
+			url:         conf.String("url"),
34
+			method:      strings.ToUpper(conf.String("method")),
35
+			contentType: conf.String("contentType"),
36
+			setting:     conf,
37
+		}
38
+	}
39
+}
40
+
41
+// SendSMS 发送短信
42
+func SendSMS(smsType, tel string, messages ...string) {
43
+	go func() {
44
+		if defaultSMS == nil {
45
+			LogError("没有成功初始化短信引擎")
46
+			return
47
+		}
48
+
49
+		// 接口内容
50
+		paramsTpl := `{"code": "%s", "tel": "%s", "params": "[%s]"}`
51
+		// 发送消息
52
+		message := strings.Join(messages, `","`)
53
+		if message != "" {
54
+			message = fmt.Sprintf(`"%s"`, message)
55
+		}
56
+
57
+		code := defaultSMS.setting.String(smsType + "::code")
58
+
59
+		// 接口 data
60
+		data := bytes.NewBuffer([]byte(fmt.Sprintf(paramsTpl, code, tel, message)))
61
+
62
+		// 暂时只支持 post 发送数据
63
+		if defaultSMS.method == http.MethodPost {
64
+			resp, err := http.Post(defaultSMS.url, defaultSMS.contentType, data)
65
+			if err != nil {
66
+				LogError("短信发送错误: " + err.Error())
67
+			}
68
+
69
+			if resp.StatusCode != http.StatusOK {
70
+				LogError("短信发送失败: " + resp.Status)
71
+			}
72
+		}
73
+
74
+	}()
75
+}
76
+
77
+func init() {
78
+	mtx = new(sync.Mutex)
79
+}

+ 24
- 2
utils/utils.go 查看文件

@@ -1,5 +1,10 @@
1 1
 package utils
2 2
 
3
+import (
4
+	"net/http"
5
+	"strings"
6
+)
7
+
3 8
 // 客户端类型
4 9
 const (
5 10
 	ClientAdmin  = "client-admin"
@@ -7,7 +12,24 @@ const (
7 12
 	ClientMini   = "client-mini"
8 13
 )
9 14
 
15
+// 一些 UA 列表
16
+const (
17
+	UAWechat      = "micromessenger"
18
+	UAMiniProgram = "miniprogram"
19
+)
20
+
10 21
 // GetClientType 获取客户端类型
11
-func GetClientType() string {
12
-	return ""
22
+// 默认返回是 管理端
23
+func GetClientType(r *http.Request) string {
24
+	ua := strings.ToLower(r.Header.Get("User-Agent"))
25
+
26
+	if strings.Index(ua, UAWechat) > -1 {
27
+		if strings.Index(ua, UAMiniProgram) > -1 {
28
+			return ClientMini
29
+		}
30
+
31
+		return ClientWechat
32
+	}
33
+
34
+	return ClientAdmin
13 35
 }

+ 23
- 0
utils/wechat.go 查看文件

@@ -0,0 +1,23 @@
1
+package utils
2
+
3
+import (
4
+	"github.com/zjxpcyc/wechat/wx"
5
+)
6
+
7
+var wxCli *wx.Client
8
+
9
+// InitWeChatClient 初始化
10
+func InitWeChatClient(cert map[string]string) {
11
+	wxCli = wx.NewClient(cert)
12
+	wx.SetLogInst(defaultLogger)
13
+}
14
+
15
+// GetWxUserInfo 微信获取用户信息
16
+func GetWxUserInfo(code string) (map[string]interface{}, error) {
17
+	return wxCli.GetUserInfo(code)
18
+}
19
+
20
+// WechatSignature 启用 Wechat 接口
21
+func WechatSignature(timestamp, nonce string) string {
22
+	return wxCli.Signature(timestamp, nonce)
23
+}