zhengchengwu 5 years ago
parent
commit
25e6acbdf3

+ 2 - 0
.gitignore View File

@@ -0,0 +1,2 @@
1
+/*.exe
2
+/*.exe~

+ 113 - 2
conf/app.conf View File

@@ -1,3 +1,114 @@
1 1
 appname = wsc-go
2
-httpport = 8080
3
-runmode = dev
2
+httpport = 9531
3
+runmode = prod
4
+
5
+copyrequestbody = true
6
+sessionon = true
7
+sessiongcmaxlifetime = 64800
8
+
9
+tokencookiemaxlifetime = 7200
10
+
11
+enablexsrf = false
12
+xsrfkey = 61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o
13
+xsrfexpire = 3600
14
+
15
+qiniu_accesskey = -l_Pcc1YJs0gh3w0YwN2uoaZO_5fY5J9SIYnSjg0
16
+qiniu_secretkey = DmZSp_Bmnp-9aUB7xUvoyViZpzmx1Rs2RL69GvlW
17
+qiniu_domain = https://images.shengws.com/
18
+qiniu_bucket = syhclub-storage
19
+
20
+aes_key = "xuetou-201807319"
21
+
22
+
23
+sms_appId = dcabb3aa7afd402794046ebbbf652bce
24
+sms_sid = a26cb0ceb3a811ca82143972f4ef38a4
25
+sms_token = ea475ed8d3de6c54c2b3f9d78db76d1e
26
+sms_baseUrl = https://open.ucpaas.com/ol/sms/
27
+ip_max_send_count = 20
28
+moblie_max_send_count = 5
29
+sms_verification_code_templateid = 329532
30
+
31
+
32
+[dev]
33
+httpdomain = http://api.mall.test.sgjyun.com
34
+sso_domain = http://testsso.sgjyun.com
35
+front_end_domain = "http://mall.test.sgjyun.com/#"
36
+
37
+
38
+readmysqlhost = rm-wz9rg531npf61q03tro.mysql.rds.aliyuncs.com
39
+readmysqlport = 3306
40
+readmysqluser = root
41
+readmysqlpass = 1Q2W3e4r!@#$
42
+readmysqlname = sgj_xt
43
+
44
+writemysqlhost = rm-wz9rg531npf61q03tro.mysql.rds.aliyuncs.com
45
+writemysqlport = 3306
46
+writemysqluser = root
47
+writemysqlpass = 1Q2W3e4r!@#$
48
+writemysqlname = sgj_xt
49
+
50
+readuserhost = rm-wz9rg531npf61q03tro.mysql.rds.aliyuncs.com
51
+readuserport = 3306
52
+readuseruser = root
53
+readuserpass = 1Q2W3e4r!@#$
54
+readusername = sgj_users
55
+
56
+writeuserhost = rm-wz9rg531npf61q03tro.mysql.rds.aliyuncs.com
57
+writeuserport = 3306
58
+writeuseruser = root
59
+writeuserpass = 1Q2W3e4r!@#$
60
+writeusername = sgj_users
61
+
62
+redishost = 120.77.235.13
63
+redisport = 6379
64
+redispasswrod = syh@#$%123456!
65
+redisdb = 0
66
+
67
+fxlink = "http://shop-dev.shengws.com/app/index.php?i=2&c=entry&m=ewei_shopv2&do=mobile&r=commission"
68
+sylink = "http://shop-dev.shengws.com/app/index.php?i=2&c=entry&m=ewei_shopv2&do=mobile"
69
+zxlink = "http://shop-dev.shengws.com/app/index.php?i=2&c=entry&m=ewei_shopv2&do=mobile&r=member"
70
+
71
+fxtokenkey = "kN*5&AHqLP7&IGRKvHoElJm*2YY6Nw*QSScJ4ff&DH&ofGnbfQIks1A1NT9AbIDB"
72
+
73
+[prod]
74
+httpdomain = http://api.mall.kuyicloud.com
75
+sso_domain = http://sso.kuyicloud.com
76
+front_end_domain = "http://mall.kuyicloud.com/#"
77
+
78
+
79
+readmysqlhost = shengws1.mysql.rds.aliyuncs.com
80
+readmysqlport = 3306
81
+readmysqluser = syh
82
+readmysqlpass = xhPECP2nFObR8aUK
83
+readmysqlname = sgj_xt
84
+
85
+writemysqlhost = shengws1.mysql.rds.aliyuncs.com
86
+writemysqlport = 3306
87
+writemysqluser = syh
88
+writemysqlpass = xhPECP2nFObR8aUK
89
+writemysqlname = sgj_xt
90
+
91
+
92
+readuserhost = shengws1.mysql.rds.aliyuncs.com
93
+readuserport = 3306
94
+readuseruser = syh
95
+readuserpass = xhPECP2nFObR8aUK
96
+readusername = sgj_users
97
+
98
+writeuserhost = shengws1.mysql.rds.aliyuncs.com
99
+writeuserport = 3306
100
+writeuseruser = syh
101
+writeuserpass = xhPECP2nFObR8aUK
102
+writeusername = sgj_users
103
+
104
+redishost = 349e580b2a524290.redis.rds.aliyuncs.com
105
+redisport = 6379
106
+redispasswrod = TZtBW098WId3i27clkpj3q8dnUaVFP
107
+redisdb = 0
108
+
109
+
110
+fxlink = "http://shop.kuyicloud.com/app/index.php?i=2&c=entry&m=ewei_shopv2&do=mobile&r=commission"
111
+sylink = "http://shop.kuyicloud.com/app/index.php?i=2&c=entry&m=ewei_shopv2&do=mobile"
112
+zxlink = "http://shop.kuyicloud.com/app/index.php?i=2&c=entry&m=ewei_shopv2&do=mobile&r=member"
113
+
114
+fxtokenkey = "8&o!5VSz^iWe*PzhDogC5%m*S$ZlyB3c%5R4CrWjTwJJSJdEbop6do@eFR*7deTY"

+ 140 - 0
controllers/base_api_controller.go View File

@@ -0,0 +1,140 @@
1
+package controllers
2
+
3
+import (
4
+	"wsc-go/enums"
5
+	"wsc-go/service"
6
+)
7
+
8
+type BaseAPIController struct {
9
+	BaseController
10
+}
11
+
12
+// func (this *BaseAPIController) Prepare() {
13
+// 	this.BaseController.Prepare()
14
+// 	beego.Trace("============================================================")
15
+// 	beego.Trace("session ID: %v", this.Ctx.Input.Cookie("beegosessionID"))
16
+// 	beego.Trace("session : %v", this.GetSession("info"))
17
+// 	this.SetSession("info", time.Now().Format("2006/01/02 15:04:05"))
18
+// 	beego.Trace("============================================================")
19
+// }
20
+
21
+// 输出数据格式化
22
+/*
23
+	success json:
24
+	{
25
+		"state": 1,
26
+		"code": 0,
27
+		"data": json,
28
+	}
29
+
30
+	fail json:
31
+	{
32
+		"state": 0,
33
+		"code": int,
34
+		"msg": string,
35
+	}
36
+*/
37
+func (this *BaseAPIController) ServeSuccessJSON(data map[string]interface{}) {
38
+	this.Data["json"] = enums.MakeSuccessResponseJSON(data)
39
+	this.ServeJSON()
40
+}
41
+
42
+func (this *BaseAPIController) ServeFailJSONWithSGJErrorCode(code int) {
43
+	this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(code)
44
+	this.ServeJSON()
45
+}
46
+
47
+func (this *BaseAPIController) ServeFailJSONWithSGJError(err *enums.SGJError) {
48
+	this.Data["json"] = enums.MakeFailResponseJSONWithSGJError(err)
49
+	this.ServeJSON()
50
+}
51
+
52
+func (this *BaseAPIController) ServeFailJsonSend(code int, msg string) {
53
+	this.Data["json"] = enums.MakeFailResponseJSON(msg, code)
54
+	this.ServeJSON()
55
+}
56
+
57
+type BaseAuthAPIController struct {
58
+	BaseAPIController
59
+}
60
+
61
+func (this *BaseAuthAPIController) Prepare() {
62
+	this.BaseAPIController.Prepare()
63
+	if this.GetAdminUserInfo() == nil {
64
+		//var userAdmin models.AdminUser
65
+		//userAdmin.Id = 380
66
+		//userAdmin.Mobile = "13532250447"
67
+		//userAdmin.IsSuperAdmin = true
68
+		//userAdmin.Status = 1
69
+		//userAdmin.CreateTime = 1530786071
70
+		//userAdmin.ModifyTime = 1530786071
71
+		//var subscibe models.ServeSubscibe
72
+		//subscibe.ID = 1
73
+		//subscibe.OrgId = 4
74
+		//subscibe.PeriodStart = 1538035409
75
+		//subscibe.PeriodEnd = 1569571409
76
+		//subscibe.State = 1
77
+		//subscibe.Status = 1
78
+		//subscibe.CreatedTime = 1538035409
79
+		//subscibe.UpdatedTime = 1538035409
80
+		//subscibes := make(map[int64]*models.ServeSubscibe, 0)
81
+		//subscibes[4] = &subscibe
82
+		//var adminUserInfo service.AdminUserInfo
83
+		//adminUserInfo.CurrentOrgId = 4
84
+		//adminUserInfo.CurrentAppId = 5
85
+		//adminUserInfo.AdminUser = &userAdmin
86
+		//adminUserInfo.Subscibes = subscibes
87
+		//this.SetSession("admin_user_info", &adminUserInfo)
88
+
89
+		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeNotLogin)
90
+		this.StopRun()
91
+	}
92
+
93
+	if this.Ctx.Request.Method != "GET" {
94
+		adminUserInfo := this.GetAdminUserInfo()
95
+
96
+		err := service.GetOrgSubscibeState(adminUserInfo.Subscibes[adminUserInfo.CurrentOrgId])
97
+		if err != nil || adminUserInfo.Subscibes[adminUserInfo.CurrentOrgId].State == 3 {
98
+			this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeNotSubscibe)
99
+			this.StopRun()
100
+		}
101
+	}
102
+
103
+}
104
+
105
+type BaseServeAPIController struct {
106
+	BaseAPIController
107
+}
108
+
109
+func (this *BaseServeAPIController) Prepare() {
110
+	this.BaseAPIController.Prepare()
111
+	if this.GetAdminUserInfo() == nil {
112
+		//var userAdmin models.AdminUser
113
+		//userAdmin.Id = 380
114
+		//userAdmin.Mobile = "13532250447"
115
+		//userAdmin.IsSuperAdmin = true
116
+		//userAdmin.Status = 1
117
+		//userAdmin.CreateTime = 1530786071
118
+		//userAdmin.ModifyTime = 1530786071
119
+		//var subscibe models.ServeSubscibe
120
+		//subscibe.ID = 1
121
+		//subscibe.OrgId = 4
122
+		//subscibe.PeriodStart = 1538035409
123
+		//subscibe.PeriodEnd = 1569571409
124
+		//subscibe.State = 1
125
+		//subscibe.Status = 1
126
+		//subscibe.CreatedTime = 1538035409
127
+		//subscibe.UpdatedTime = 1538035409
128
+		//subscibes := make(map[int64]*models.ServeSubscibe, 0)
129
+		//subscibes[4] = &subscibe
130
+		//var adminUserInfo service.AdminUserInfo
131
+		//adminUserInfo.CurrentOrgId = 4
132
+		//adminUserInfo.CurrentAppId = 5
133
+		//adminUserInfo.AdminUser = &userAdmin
134
+		//adminUserInfo.Subscibes = subscibes
135
+		//this.SetSession("admin_user_info", &adminUserInfo)
136
+
137
+		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeNotLogin)
138
+		this.StopRun()
139
+	}
140
+}

+ 40 - 0
controllers/base_controller.go View File

@@ -0,0 +1,40 @@
1
+package controllers
2
+
3
+import (
4
+	"wsc-go/service"
5
+
6
+	"github.com/astaxie/beego"
7
+)
8
+
9
+type BaseController struct {
10
+	beego.Controller
11
+}
12
+
13
+func (this *BaseController) GetAdminUserInfo() *service.AdminUserInfo {
14
+	userInfo := this.GetSession("admin_user_info")
15
+	if userInfo == nil {
16
+		return nil
17
+	} else {
18
+		return userInfo.(*service.AdminUserInfo)
19
+	}
20
+}
21
+
22
+func (this *BaseController) ErrorLog(format string, a ...interface{}) {
23
+	//beego.Error(fmt.Sprintf(format, a...))
24
+}
25
+
26
+func (this *BaseController) WarnLog(format string, a ...interface{}) {
27
+	//beego.Warn(fmt.Sprintf(format, a...))
28
+}
29
+
30
+func (this *BaseController) InfoLog(format string, a ...interface{}) {
31
+	//beego.Info(fmt.Sprintf(format, a...))
32
+}
33
+
34
+func (this *BaseController) DebugLog(format string, a ...interface{}) {
35
+	//beego.Debug(fmt.Sprintf(format, a...))
36
+}
37
+
38
+func (this *BaseController) TraceLog(format string, a ...interface{}) {
39
+	//beego.Trace(fmt.Sprintf(format, a...))
40
+}

+ 58 - 0
controllers/base_view_controller.go View File

@@ -0,0 +1,58 @@
1
+package controllers
2
+
3
+type BaseViewController struct {
4
+	BaseController
5
+}
6
+
7
+// 设置模板
8
+// 第一个参数模板,第二个参数为layout
9
+func (this *BaseViewController) SetTpl(template ...string) {
10
+	var tplName string
11
+	layout := ""
12
+	switch {
13
+	case len(template) == 1:
14
+		tplName = template[0]
15
+	case len(template) == 2:
16
+		tplName = template[0]
17
+		layout = template[1]
18
+	default:
19
+		tplName = "index.tpl"
20
+	}
21
+	this.Layout = layout
22
+	this.TplName = tplName
23
+}
24
+
25
+// 重定向
26
+func (this *BaseViewController) Redirect302(url string) {
27
+	this.Redirect(url, 302)
28
+	this.StopRun()
29
+}
30
+
31
+// 错误页面
32
+func (this *BaseViewController) Abort404() {
33
+	this.Abort("404")
34
+}
35
+
36
+// // 微信错误页面
37
+// func (this *BaseViewController) WxAbort404(title, desc string) {
38
+// 	this.Data["Title"] = title
39
+// 	this.Data["Desc"] = desc
40
+// 	this.SetTpl("view_wx/error/404.html")
41
+// }
42
+
43
+// type BaseAuthViewController struct {
44
+// 	BaseViewController
45
+// }
46
+
47
+// func (this *BaseAuthViewController) Prepare() {
48
+// 	this.BaseController.Prepare()
49
+// 	backUrl := utils.SetThisRequestURI(this.Ctx.Request.RequestURI)
50
+// 	backUrl = base64.URLEncoding.EncodeToString([]byte(backUrl))
51
+// 	if this.GetUserInfo() == nil {
52
+// 		if strings.HasPrefix(this.Ctx.Request.RequestURI, "/web/") {
53
+// 			this.Redirect302(beego.URLFor("WebLoginViewController.Login") + "?backUrl=" + backUrl)
54
+// 		} else {
55
+// 			this.Redirect302(beego.URLFor("WxLoginViewController.Login") + "?backUrl=" + backUrl)
56
+// 		}
57
+// 	}
58
+// }

+ 40 - 0
controllers/fxlink_api_controller.go View File

@@ -0,0 +1,40 @@
1
+package controllers
2
+
3
+import (
4
+	"fmt"
5
+	"wsc-go/enums"
6
+	"wsc-go/service"
7
+
8
+	"github.com/astaxie/beego"
9
+)
10
+
11
+type FxlinkApiController struct {
12
+	BaseAuthAPIController
13
+}
14
+
15
+func FxlinkApiRegistRouters() {
16
+	beego.Router("/api/getfxlink", &FxlinkApiController{}, "get:GetFxlink")
17
+}
18
+
19
+func (c *FxlinkApiController) GetFxlink() {
20
+	link := c.GetString("link", "")
21
+	if link != "fxlink" && link != "sylink" && link != "zxlink" {
22
+		c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "参数错误:link(sylink,zxlink,fxlink)")
23
+		return
24
+	}
25
+
26
+	fxlink := beego.AppConfig.String(link)
27
+	adminUserInfo := c.GetAdminUserInfo()
28
+	orgId := adminUserInfo.CurrentOrgId
29
+	appId := adminUserInfo.CurrentAppId
30
+	thisApp := adminUserInfo.OrgApps[orgId][appId]
31
+	creator := thisApp.Creator
32
+	fxToken, fxTime := service.CreateFxToken(orgId, creator)
33
+
34
+	fxlink = fxlink + fmt.Sprintf("&fxtoken=%s&fxorgid=%d&timestamp=%d&fxadmin=%d", fxToken, orgId, fxTime, creator)
35
+
36
+	c.ServeSuccessJSON(map[string]interface{}{
37
+		"fxlink": fxlink,
38
+	})
39
+	return
40
+}

+ 292 - 0
controllers/orginfo_api_controller.go View File

@@ -0,0 +1,292 @@
1
+package controllers
2
+
3
+import (
4
+	"encoding/json"
5
+	"reflect"
6
+	"time"
7
+	"wsc-go/enums"
8
+	"wsc-go/models"
9
+	"wsc-go/service"
10
+	"wsc-go/utils"
11
+
12
+	"github.com/astaxie/beego"
13
+)
14
+
15
+type OrgInfoApiController struct {
16
+	BaseAuthAPIController
17
+}
18
+
19
+func OrgInfoApiRegistRouters() {
20
+	beego.Router("/api/orginfo/getinfo", &OrgInfoApiController{}, "get:GetOrgInfo")
21
+	beego.Router("/api/orginfo/savegallery", &OrgInfoApiController{}, "post:SaveOrgGallery")
22
+	beego.Router("/api/orginfo/deletegallery", &OrgInfoApiController{}, "delete:DeleteOrgGallery")
23
+	beego.Router("/api/orginfo/edit", &OrgInfoApiController{}, "post:EditOrgInfo")
24
+
25
+}
26
+
27
+func (c *OrgInfoApiController) GetOrgInfo() {
28
+
29
+	adminUserInfo := c.GetAdminUserInfo()
30
+
31
+	orgInfo := adminUserInfo.Orgs[adminUserInfo.CurrentOrgId]
32
+	provinces, _ := service.GetDistrictsByUpid(0)
33
+	var citys []*models.District
34
+	var districts []*models.District
35
+	if orgInfo.Province > 0 {
36
+		citys, _ = service.GetDistrictsByUpid(orgInfo.Province)
37
+	}
38
+	if orgInfo.City > 0 {
39
+		districts, _ = service.GetDistrictsByUpid(orgInfo.City)
40
+	}
41
+
42
+	orgtypes, _ := service.GetOrgTypes()
43
+
44
+	illness, _ := service.GetIllnessList()
45
+
46
+	c.ServeSuccessJSON(map[string]interface{}{
47
+		"orginfo":   orgInfo,
48
+		"provinces": provinces,
49
+		"citys":     citys,
50
+		"districts": districts,
51
+		"orgtypes":  orgtypes,
52
+		"illness":   illness,
53
+	})
54
+	return
55
+}
56
+
57
+func (c *OrgInfoApiController) EditOrgInfo() {
58
+	adminUserInfo := c.GetAdminUserInfo()
59
+
60
+	if !adminUserInfo.AdminUser.IsSuperAdmin {
61
+		c.ServeFailJsonSend(enums.ErrorCodePermissionDenied, "权限不足")
62
+		return
63
+	}
64
+
65
+	dataBody := make(map[string]interface{}, 0)
66
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &dataBody)
67
+	if err != nil {
68
+		utils.ErrorLog(err.Error())
69
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
70
+		return
71
+	}
72
+
73
+	orgInfo := adminUserInfo.Orgs[adminUserInfo.CurrentOrgId]
74
+	org := *orgInfo
75
+
76
+	if dataBody["org_name"] == nil || reflect.TypeOf(dataBody["org_name"]).String() != "string" {
77
+		c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "缺少参数:机构名称")
78
+		return
79
+	}
80
+	orgName, _ := dataBody["org_name"].(string)
81
+	if len(orgName) == 0 {
82
+		c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "机构名称不能为空")
83
+		return
84
+	}
85
+	org.OrgName = orgName
86
+
87
+	if dataBody["contact_name"] == nil || reflect.TypeOf(dataBody["contact_name"]).String() != "string" {
88
+		c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "缺少参数:联系人姓名")
89
+		return
90
+	}
91
+	contactName, _ := dataBody["contact_name"].(string)
92
+	if len(contactName) == 0 {
93
+		c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "联系人姓名不能为空")
94
+		return
95
+	}
96
+	org.ContactName = contactName
97
+
98
+	// if dataBody["org_short_name"] == nil || reflect.TypeOf(dataBody["org_short_name"]).String() != "string" {
99
+	// 	c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "缺少参数:商家简称")
100
+	// 	return
101
+	// }
102
+	// orgShortName, _ := dataBody["org_short_name"].(string)
103
+	// if len(orgShortName) == 0 {
104
+	// 	c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "商家简称不能为空")
105
+	// 	return
106
+	// }
107
+	org.OrgShortName = orgName
108
+
109
+	if dataBody["org_introduction"] == nil || reflect.TypeOf(dataBody["org_introduction"]).String() != "string" {
110
+		c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "缺少参数:机构介绍")
111
+		return
112
+	}
113
+	orgIntroduction, _ := dataBody["org_introduction"].(string)
114
+	if len(orgIntroduction) == 0 {
115
+		c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "机构介绍不能为空")
116
+		return
117
+	}
118
+	org.OrgIntroduction = orgIntroduction
119
+
120
+	if dataBody["org_logo"] == nil || reflect.TypeOf(dataBody["org_logo"]).String() != "string" {
121
+		c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "缺少参数:机构头像")
122
+		return
123
+	}
124
+	orgLogo, _ := dataBody["org_logo"].(string)
125
+	if len(orgLogo) == 0 {
126
+		c.ServeFailJsonSend(enums.ErrorCodeParamWrong, "机构头像不能为空")
127
+		return
128
+	}
129
+	org.OrgLogo = orgLogo
130
+
131
+	if dataBody["province"] != nil || reflect.TypeOf(dataBody["province"]).String() == "float64" {
132
+		province := int64(dataBody["province"].(float64))
133
+		org.Province = province
134
+	}
135
+
136
+	if dataBody["city"] != nil || reflect.TypeOf(dataBody["city"]).String() == "float64" {
137
+		city := int64(dataBody["city"].(float64))
138
+		org.City = city
139
+	}
140
+
141
+	if dataBody["district"] != nil || reflect.TypeOf(dataBody["district"]).String() == "float64" {
142
+		district := int64(dataBody["district"].(float64))
143
+		org.District = district
144
+	}
145
+
146
+	if dataBody["address"] != nil || reflect.TypeOf(dataBody["address"]).String() == "string" {
147
+		address, _ := dataBody["address"].(string)
148
+		org.Address = address
149
+	}
150
+
151
+	if dataBody["org_type"] != nil || reflect.TypeOf(dataBody["org_type"]).String() == "float64" {
152
+		orgType := int64(dataBody["org_type"].(float64))
153
+		org.OrgType = orgType
154
+	}
155
+
156
+	if dataBody["telephone"] != nil || reflect.TypeOf(dataBody["telephone"]).String() == "string" {
157
+		telephone, _ := dataBody["telephone"].(string)
158
+		org.Telephone = telephone
159
+	}
160
+
161
+	if dataBody["operating_state"] != nil || reflect.TypeOf(dataBody["operating_state"]).String() == "float64" {
162
+		operatingState := int64(dataBody["operating_state"].(float64))
163
+		org.OperatingState = operatingState
164
+	}
165
+
166
+	if dataBody["business_week"] != nil || reflect.TypeOf(dataBody["business_week"]).String() == "string" {
167
+		businessWeek, _ := dataBody["business_week"].(string)
168
+		org.BusinessWeek = businessWeek
169
+	}
170
+
171
+	if dataBody["business_time"] != nil || reflect.TypeOf(dataBody["business_time"]).String() == "string" {
172
+		businessTime, _ := dataBody["business_time"].(string)
173
+		org.BusinessTime = businessTime
174
+	}
175
+	if dataBody["illness"] != nil || reflect.TypeOf(dataBody["illness"]).String() == "string" {
176
+		illness, _ := dataBody["illness"].(string)
177
+		org.Illness = illness
178
+	}
179
+
180
+	timeNow := time.Now().Unix()
181
+	org.ModifyTime = timeNow
182
+	org.OrgGallery = nil
183
+	err = service.UpdateOrgInfo(&org)
184
+	if err != nil {
185
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
186
+		return
187
+	}
188
+
189
+	orgInfo.OrgName = orgName
190
+	orgInfo.OrgShortName = orgName
191
+	orgInfo.OrgIntroduction = orgIntroduction
192
+	orgInfo.OrgLogo = orgLogo
193
+	orgInfo.Province = org.Province
194
+	orgInfo.District = org.District
195
+	orgInfo.City = org.City
196
+	orgInfo.OrgType = org.OrgType
197
+	orgInfo.Telephone = org.Telephone
198
+	orgInfo.OperatingState = org.OperatingState
199
+	orgInfo.BusinessWeek = org.BusinessWeek
200
+	orgInfo.BusinessTime = org.BusinessTime
201
+	orgInfo.Illness = org.Illness
202
+
203
+	c.ServeSuccessJSON(map[string]interface{}{
204
+		"msg": "ok",
205
+	})
206
+	return
207
+}
208
+
209
+func (c *OrgInfoApiController) SaveOrgGallery() {
210
+	adminUserInfo := c.GetAdminUserInfo()
211
+
212
+	dataBody := make(map[string]interface{}, 0)
213
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &dataBody)
214
+	if err != nil {
215
+		utils.ErrorLog(err.Error())
216
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
217
+		return
218
+	}
219
+
220
+	if dataBody["type"] == nil || reflect.TypeOf(dataBody["type"]).String() != "float64" {
221
+		utils.ErrorLog("type")
222
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
223
+		return
224
+	}
225
+	galleryType := int64(dataBody["type"].(float64))
226
+	if galleryType != 1 && galleryType != 2 {
227
+		utils.ErrorLog("galleryType != 1&&2")
228
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
229
+		return
230
+	}
231
+
232
+	if dataBody["url"] == nil || reflect.TypeOf(dataBody["url"]).String() != "string" {
233
+		utils.ErrorLog("url")
234
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
235
+		return
236
+	}
237
+	url, _ := dataBody["url"].(string)
238
+	if len(url) == 0 {
239
+		utils.ErrorLog("len(url) == 0")
240
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
241
+		return
242
+	}
243
+
244
+	timeNow := time.Now().Unix()
245
+	var gallery models.OrgGallery
246
+	gallery.Type = galleryType
247
+	gallery.Url = url
248
+	gallery.OrgId = adminUserInfo.CurrentOrgId
249
+	gallery.Status = 1
250
+	gallery.Ctime = timeNow
251
+	gallery.Mtime = timeNow
252
+	err = service.CreateOrgGalleryItem(&gallery)
253
+	if err != nil {
254
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
255
+		return
256
+	}
257
+
258
+	orgInfo := adminUserInfo.Orgs[adminUserInfo.CurrentOrgId]
259
+	orgInfo.OrgGallery = append(orgInfo.OrgGallery, &gallery)
260
+	c.ServeSuccessJSON(map[string]interface{}{
261
+		"msg": "ok",
262
+	})
263
+	return
264
+
265
+}
266
+
267
+func (c *OrgInfoApiController) DeleteOrgGallery() {
268
+	adminUserInfo := c.GetAdminUserInfo()
269
+	id, _ := c.GetInt64("id", 0)
270
+	if id <= 0 {
271
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
272
+		return
273
+	}
274
+
275
+	err := service.DeleteOrgGalleryItem(id)
276
+	if err != nil {
277
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
278
+		return
279
+	}
280
+
281
+	orgInfo := adminUserInfo.Orgs[adminUserInfo.CurrentOrgId]
282
+	for index, item := range orgInfo.OrgGallery {
283
+		if item.ID == id {
284
+			orgInfo.OrgGallery = append(orgInfo.OrgGallery[:index], orgInfo.OrgGallery[index+1:]...)
285
+		}
286
+	}
287
+	c.ServeSuccessJSON(map[string]interface{}{
288
+		"msg": "ok",
289
+	})
290
+	return
291
+
292
+}

+ 35 - 0
controllers/qiniiu_api_controller.go View File

@@ -0,0 +1,35 @@
1
+package controllers
2
+
3
+import (
4
+	"XT/enums"
5
+	"XT/service"
6
+	"fmt"
7
+
8
+	"github.com/astaxie/beego"
9
+)
10
+
11
+type QiNiuApiController struct {
12
+	BaseAPIController
13
+	// beego.Controller
14
+}
15
+
16
+func QiniuApiRegistRouters() {
17
+	beego.Router("/api/qiniu/uptoken", &QiNiuApiController{}, "get:GetQNUpToken")
18
+}
19
+
20
+func (c *QiNiuApiController) GetQNUpToken() {
21
+	redisClient := service.RedisClient()
22
+	defer redisClient.Close()
23
+
24
+	token, err := redisClient.Get("qn_token").Result()
25
+	if err != nil {
26
+		defer fmt.Println(err)
27
+		c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeGetQiniuUpToken)
28
+		return
29
+	}
30
+
31
+	c.ServeSuccessJSON(map[string]interface{}{
32
+		"uptoken": token,
33
+	})
34
+	return
35
+}

+ 293 - 0
controllers/verify_login_controller.go View File

@@ -0,0 +1,293 @@
1
+package controllers
2
+
3
+import (
4
+	"fmt"
5
+	"net/url"
6
+
7
+	"wsc-go/enums"
8
+	"wsc-go/service"
9
+	"wsc-go/utils"
10
+
11
+	"github.com/astaxie/beego"
12
+)
13
+
14
+func VerifyUserLoginControllerRegistRouters() {
15
+	beego.Router("/login", &VerifyUserLoginController{}, "get:Login")
16
+	beego.Router("/logout", &VerifyUserLoginController{}, "get,post:Logout")
17
+	beego.Router("/handle_error", &VerifyUserLoginController{}, "get:HandleError")
18
+
19
+	beego.Router("/api/token/verify", &VerifyUserLoginAPIController{}, "post:VerifyToken")
20
+	beego.Router("/api/admin/edit_info", &VerifyUserLoginAPIController{}, "post:EditAdminUserInfo")
21
+
22
+	beego.Router("/api/password/code", &PersonAPIController{}, "post:CodeOfModifyPwd")
23
+	beego.Router("/api/password/modify", &PersonAPIController{}, "post:ModifyPwd")
24
+}
25
+
26
+type VerifyUserLoginController struct {
27
+	BaseViewController
28
+}
29
+
30
+// /login [get]
31
+// @param token?:string
32
+// @param relogin?:bool
33
+func (this *VerifyUserLoginController) Login() {
34
+	token := this.Ctx.Input.Query("token")
35
+	if len(token) > 0 { // 带 token 参数的一般是从 SSO 回调回来的
36
+		utils.TraceLog("SSO Login 回调: token=%v", token)
37
+		xtFrontEndDomain := beego.AppConfig.String("front_end_domain") + "?lt=" + token
38
+		this.Redirect302(xtFrontEndDomain)
39
+
40
+	} else {
41
+		relogin, _ := this.GetBool("relogin", false)
42
+		returnURL := url.QueryEscape(fmt.Sprintf("%v%v", beego.AppConfig.String("httpdomain"), this.Ctx.Request.RequestURI))
43
+		ssoDomain := beego.AppConfig.String("sso_domain")
44
+		ssoLoginURL := fmt.Sprintf("%v/login?returnurl=%v&app_type=3&relogin=%v", ssoDomain, returnURL, relogin)
45
+		this.Redirect302(ssoLoginURL)
46
+	}
47
+}
48
+
49
+// /logout [get/post]
50
+func (this *VerifyUserLoginController) Logout() {
51
+	if this.Ctx.Request.Method == "GET" {
52
+		this.DelSession("admin_user_info")
53
+		this.Redirect302(fmt.Sprintf("%v/logout", beego.AppConfig.String("sso_domain")))
54
+	} else if this.Ctx.Request.Method == "POST" {
55
+		this.DelSession("admin_user_info")
56
+	}
57
+}
58
+
59
+// /handle_error [get]
60
+// @param code:int
61
+func (this *VerifyUserLoginController) HandleError() {
62
+	code, _ := this.GetInt("code")
63
+	if code == enums.ErrorCodeNeverCreateTypeApp {
64
+		ssoDomain := beego.AppConfig.String("sso_domain")
65
+		createAppURL := fmt.Sprintf("%v/org/app/create", ssoDomain)
66
+		this.Redirect302(createAppURL)
67
+
68
+	} else if code == enums.ErrorCodeContactSuperAdminCreateTypeApp {
69
+		ssoDomain := beego.AppConfig.String("sso_domain")
70
+		hitURL := fmt.Sprintf("%v/create_app_hint", ssoDomain)
71
+		this.Redirect302(hitURL)
72
+
73
+	} else {
74
+		this.Abort404()
75
+	}
76
+}
77
+
78
+type VerifyUserLoginAPIController struct {
79
+	BaseAPIController
80
+}
81
+
82
+// /api/token/verify [post]
83
+// @param token:string
84
+func (this *VerifyUserLoginAPIController) VerifyToken() {
85
+	if this.Ctx.Request.Method == "OPTIONS" {
86
+		this.Abort("200")
87
+
88
+	} else {
89
+		token := this.GetString("token")
90
+		utils.TraceLog("token: %v", token)
91
+		if len(token) == 0 {
92
+			this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
93
+			return
94
+		}
95
+
96
+		ip := utils.GetIP(this.Ctx.Request)
97
+		sessionID := this.Ctx.GetCookie("s")
98
+		this.TraceLog("cookie session id: %v", sessionID)
99
+		adminUserInfo, err, errCode := service.VerifyToken(token, ip, sessionID)
100
+		if err != nil {
101
+			if errCode == 903 { // 未创建应用
102
+				this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeNeverCreateTypeApp)
103
+
104
+			} else if errCode == 904 { // 联系超管来开通
105
+				this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeContactSuperAdminCreateTypeApp)
106
+
107
+			} else {
108
+				utils.ErrorLog("令牌验证失败:%v", err)
109
+				this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeInvalidToken)
110
+			}
111
+			return
112
+
113
+		} else {
114
+
115
+			this.SetSession("admin_user_info", adminUserInfo)
116
+
117
+			adminUser := adminUserInfo.AdminUser
118
+			appRole := adminUserInfo.AppRoles[adminUserInfo.CurrentAppId]
119
+			userInfo := map[string]interface{}{
120
+				"id":         adminUser.Id,
121
+				"mobile":     adminUser.Mobile,
122
+				"user_name":  appRole.UserName,
123
+				"avatar":     appRole.Avatar,
124
+				"intro":      appRole.Intro,
125
+				"user_type":  appRole.UserType,
126
+				"user_title": appRole.UserTitle,
127
+			}
128
+			curOrg := adminUserInfo.Orgs[adminUserInfo.CurrentOrgId]
129
+			org := map[string]interface{}{
130
+				"id":             curOrg.Id,
131
+				"org_name":       curOrg.OrgName,
132
+				"org_short_name": curOrg.OrgShortName,
133
+				"org_intro":      curOrg.OrgIntroduction,
134
+				"org_logo":       curOrg.OrgLogo,
135
+				"province":       curOrg.Province,
136
+				"city":           curOrg.City,
137
+				"district":       curOrg.District,
138
+				"address":        curOrg.Address,
139
+			}
140
+			curAppUrlfors := adminUserInfo.AppUrlfors[adminUserInfo.CurrentAppId]
141
+
142
+			subscibe := adminUserInfo.Subscibes[adminUserInfo.CurrentOrgId]
143
+			if err := service.GetOrgSubscibeState(subscibe); err != nil {
144
+				this.ErrorLog("没有机构订阅信息,数据有误")
145
+				this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
146
+				return
147
+			}
148
+
149
+			orgApps := adminUserInfo.OrgApps[curOrg.Id]
150
+			didRegistedForSCRM := false
151
+			didRegistedForMall := false
152
+			didRegistedForCDM := false
153
+			didRegistedForXT := false
154
+			for _, app := range orgApps {
155
+				if app.AppType == 1 {
156
+					didRegistedForSCRM = true
157
+				}
158
+				if app.AppType == 4 {
159
+					didRegistedForCDM = true
160
+				}
161
+				if app.AppType == 5 {
162
+					didRegistedForMall = true
163
+				}
164
+				if app.AppType == 3 {
165
+					didRegistedForXT = true
166
+				}
167
+			}
168
+
169
+			this.ServeSuccessJSON(map[string]interface{}{
170
+				"user":            userInfo,
171
+				"org":             org,
172
+				"urlfors":         curAppUrlfors,
173
+				"current_org_id":  adminUserInfo.CurrentOrgId,
174
+				"current_app_id":  adminUserInfo.CurrentAppId,
175
+				"subscibe":        subscibe,
176
+				"scrm_role_exist": didRegistedForSCRM,
177
+				"cdm_role_exist":  didRegistedForCDM,
178
+				"mall_role_exist": didRegistedForMall,
179
+				"xt_role_exist":   didRegistedForXT,
180
+			})
181
+			return
182
+		}
183
+	}
184
+}
185
+
186
+// /api/admin/edit_info [post]
187
+// @param avatar:string
188
+// @param name:string
189
+// @param opwd?:string 没有原始密码的时候,认为不修改密码
190
+// @param npwd?:string
191
+func (this *VerifyUserLoginAPIController) EditAdminUserInfo() {
192
+	adminUserInfo := this.GetAdminUserInfo()
193
+
194
+	avatar := this.GetString("avatar")
195
+	name := this.GetString("name")
196
+	if len(name) == 0 {
197
+		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeMissingUserName)
198
+		return
199
+	}
200
+	// oldPwd := this.GetString("opwd")
201
+	// newPwd := this.GetString("npwd")
202
+	// modifyPwd := len(oldPwd) != 0
203
+	// if modifyPwd {
204
+	// 	if len(newPwd) == 0 {
205
+	// 		this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(enums.ErrorCodePasswordEmpty)
206
+	// 		this.ServeJSON()
207
+	// 		return
208
+	// 	}
209
+	// 	pwdRight, err := service.IsPasswordRight(adminUserInfo.AdminUser.Id, oldPwd)
210
+	// 	if err != nil {
211
+	// 		utils.ErrorLog("判断旧密码是否错误失败:%v", err)
212
+	// 		this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(enums.ErrorCodeDataException)
213
+	// 		this.ServeJSON()
214
+	// 		return
215
+	// 	}
216
+	// 	if !pwdRight {
217
+	// 		this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(enums.ErrorCodeOldPasswordWrong)
218
+	// 		this.ServeJSON()
219
+	// 		return
220
+	// 	}
221
+	// } else {
222
+	// 	newPwd = ""
223
+	// }
224
+	modifyErr := service.ModifyAdminUserInfo(adminUserInfo.AdminUser.Id, adminUserInfo.CurrentOrgId, adminUserInfo.CurrentAppId, name, avatar, "")
225
+	if modifyErr != nil {
226
+		this.ErrorLog("修改个人信息失败:%v", modifyErr)
227
+		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDBUpdate)
228
+
229
+	} else {
230
+		appRole := adminUserInfo.AppRoles[adminUserInfo.CurrentAppId]
231
+		appRole.UserName = name
232
+		appRole.Avatar = avatar
233
+		this.ServeSuccessJSON(nil)
234
+	}
235
+}
236
+
237
+type PersonAPIController struct {
238
+	BaseAuthAPIController
239
+}
240
+
241
+// /api/password/code [post]
242
+func (this *PersonAPIController) CodeOfModifyPwd() {
243
+	adminUserInfo := this.GetAdminUserInfo()
244
+	mobile := adminUserInfo.AdminUser.Mobile
245
+	if err := service.SMSSendVerificationCode(mobile); err != nil {
246
+		utils.ErrorLog("修改密码发送验证码失败:%v", err)
247
+		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
248
+		return
249
+	} else {
250
+		this.ServeSuccessJSON(map[string]interface{}{
251
+			"msg": "短信发送成功,有效期为10分钟",
252
+		})
253
+	}
254
+}
255
+
256
+// /api/password/modify [post]
257
+// @param password:string
258
+// @param code:string
259
+func (this *PersonAPIController) ModifyPwd() {
260
+	new_pwd := this.GetString("password")
261
+	code := this.GetString("code")
262
+	if len(new_pwd) == 0 || len(code) == 0 {
263
+		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
264
+		return
265
+	}
266
+
267
+	adminUserInfo := this.GetAdminUserInfo()
268
+	mobile := adminUserInfo.AdminUser.Mobile
269
+
270
+	redisClient := service.RedisClient()
271
+	defer redisClient.Close()
272
+	cachedCode, err := redisClient.Get("xt_modify_pwd_" + mobile).Result()
273
+	if err != nil {
274
+		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeAccountOrVerCodeWrong)
275
+		return
276
+	}
277
+	if code != cachedCode {
278
+		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeAccountOrVerCodeWrong)
279
+		return
280
+	}
281
+
282
+	if modifyErr := service.ModifyPassword(adminUserInfo.AdminUser.Id, new_pwd); modifyErr != nil {
283
+		this.ErrorLog("修改密码失败:%v", modifyErr)
284
+		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
285
+		return
286
+	}
287
+
288
+	// 清除验证码
289
+	redisClient.Del("xt_modify_pwd_" + mobile)
290
+	this.ServeSuccessJSON(map[string]interface{}{
291
+		"msg": "密码已修改",
292
+	})
293
+}

+ 361 - 0
enums/error_code.go View File

@@ -0,0 +1,361 @@
1
+package enums
2
+
3
+import "wsc-go/utils"
4
+
5
+const ( // ErrorCode
6
+	// 登录注册错误 6000+
7
+	ErrorCodeLoginTimeout                   = 6001
8
+	ErrorCodeNotLogin                       = 6002
9
+	ErrorCodePermissionDenied               = 6003
10
+	ErrorCodeMobileRegistered               = 6004
11
+	ErrorCodePasswordEmpty                  = 6005
12
+	ErrorCodeVerificationCodeWrong          = 6006
13
+	ErrorCodeRegisterFail                   = 6007
14
+	ErrorCodeInvalidToken                   = 6008
15
+	ErrorCodeAccountOrPasswordWrong         = 6009
16
+	ErrorCodeMissingOrg                     = 6010
17
+	ErrorCodeMissingOrgApp                  = 6011
18
+	ErrorCodeAccountOrVerCodeWrong          = 6012
19
+	ErrorCodeMobileNotExit                  = 6013
20
+	ErrorCodeUserNotExist                   = 6014
21
+	ErrorCodeUserWasForbidden               = 6015
22
+	ErrorCodeNeverCreateTypeApp             = 6016
23
+	ErrorCodeContactSuperAdminCreateTypeApp = 6017
24
+
25
+	// 数据验证错误 7000+
26
+	ErrorCodeMobileFormat     = 7001
27
+	ErrorCodeTelphoneFormat   = 7002
28
+	ErrorCodeParamWrong       = 7003
29
+	ErrorCodeParamFormatWrong = 7004
30
+
31
+	// 数据库操作错误 8000+
32
+	ErrorCodeDBCreate         = 8001
33
+	ErrorCodeDBUpdate         = 8002
34
+	ErrorCodeDBDelete         = 8003
35
+	ErrorCodeDBSelectNoResult = 8004
36
+	ErrorCodeDataException    = 8005
37
+
38
+	// 业务逻辑操作错误 9000+
39
+	ErrorCodeRoleNotExist           = 9001
40
+	ErrorCodeAdminUserNotExist      = 9002
41
+	ErrorCodeMobileDidUsedInApp     = 9003
42
+	ErrorCodeMissingUserName        = 9004
43
+	ErrorCodeOldPasswordWrong       = 9005
44
+	ErrorCodeCannotRemoveRole       = 9006
45
+	ErrorCodeRoleMobileIsSuperAdmin = 9007
46
+
47
+	ErrorCodeGetQiniuUpToken                = 1001
48
+	ErrorCodeCreatePatient                  = 1002
49
+	ErrorCodeDialysisNoExist                = 1003
50
+	ErrorCodeIdCardNoExist                  = 1004
51
+	ErrorCodePatientNoExist                 = 1005
52
+	ErrorCodeUpdatePatient                  = 1006
53
+	ErrorCodeDialysisSolutionExist          = 1007
54
+	ErrorCodeDialysisSolutionCreate         = 1008
55
+	ErrorCodeDialysisSolutionUpdate         = 1009
56
+	ErrorCodeDialysisSolutionNotExist       = 1010
57
+	ErrorCodeParentDialysisSolutionNotExist = 1011
58
+	ErrorCodeAlReadyHadChildSolution        = 1012
59
+	ErrorCodeCanntCreateChildChildSolution  = 1013
60
+	ErrorCodeDialysisSolutionUsed           = 1014
61
+	ErrorCodeCreateDryWeightFail            = 1015
62
+	ErrorCodeCreateDoctorAdviceFail         = 1016
63
+	ErrorCodeDoctorAdviceNotExist           = 1017
64
+	ErrorCodeUpdateDoctorAdviceFail         = 1018
65
+	ErrorCodeLongTimeAdviceNotCanntEdit     = 1019
66
+	ErrorCodeAdviceStoped                   = 1020
67
+	ErrorCodeParentAdviceNotExist           = 1021
68
+	ErrorCodeStopAdviceFail                 = 1022
69
+	ErrorCodeDeleteAdviceFail               = 1023
70
+	ErrorCodeDialysisSolutionDelete         = 1024
71
+	ErrorCodeDeviceNumberNotTheZone         = 1025
72
+	ErrorCodeCreateScheduleFail             = 1026
73
+	ErrorCodeCantSetScheduleAgainOneDay     = 1027
74
+	ErrorCodeCantSetScheduleBeforeNow       = 1028
75
+	ErrorCodeScheduleNotExist               = 1029
76
+	ErrorCodeDeleteScheduleFail             = 1030
77
+	ErrorCodeChangeScheduleFail             = 1031
78
+	ErrorCodePatientPhoneUsed               = 1032
79
+	ErrorCodeAdviceExced                    = 1033
80
+	ErrorCodeAdviceChecked                  = 1034
81
+	ErrorCodePointScheduleExist             = 1035
82
+	ErrorCodeExceAndCheckNotOneUser         = 1036
83
+	ErrorCodeCanotEditOtherAdvice           = 1037
84
+	ErrorCodeEditLapsetoFail                = 1038
85
+	ErrorCodeAdviceCheckBeforeExce          = 1039
86
+	ErrorCodeAdviceExceBeforeStart          = 1040
87
+	ErrorCodeDelScheduleFailByDialysis      = 1041
88
+	ErrorCodeNotSelectLapsetoType           = 1042
89
+	ErrorCodeNotSelectLapsetoTime           = 1043
90
+
91
+	ErrorCodeInspectionDateExit    = 1201
92
+	ErrorCodeInspectionAddFail     = 1202
93
+	ErrorCodeInspectionEditFail    = 1204
94
+	ErrorCodeInspectionDateNotExit = 1203
95
+	ErrorCodeInspectionDeleteFail  = 1205
96
+
97
+	ErrorCodeMonitorCreate                  = 1128
98
+	ErrorCodeMonitorNotExist                = 1129
99
+	ErrorCodeMonitorUpdate                  = 1130
100
+	ErrorDialysisOrderNoStart               = 1132
101
+	ErrorDialysisOrderNoEND                 = 1133
102
+	ErrorDialysisOrderRepeatStart           = 1134
103
+	ErrorCodeDialysisPermissionDeniedModify = 1135
104
+
105
+	ErrorCodeNotSubscibe       = 4003
106
+	ErrorCodeServeNotExist     = 4004
107
+	ErrorCodeInvoiceExist      = 4005
108
+	ErrorCodeApplyInvoiceFail  = 4006
109
+	ErrorCodeHetongHad         = 4007
110
+	ErrorCodeCreateHetongFail  = 4008
111
+	ErrorCodePatientReachLimit = 4009
112
+
113
+	ErrorCodeDeviceZoneNotExist                      = 9021
114
+	ErrorCodeDeviceZoneNameRepeat                    = 9022
115
+	ErrorCodeDeviceGroupNotExist                     = 9023
116
+	ErrorCodeDeviceGroupNameRepeat                   = 9024
117
+	ErrorCodeDeviceNumberNotExist                    = 9025
118
+	ErrorCodeDeviceNumberRepeat                      = 9026
119
+	ErrorCodeDeviceNotExist                          = 9027
120
+	ErrorCodeDeviceZoneCannotDisable                 = 9028
121
+	ErrorCodeDeviceNumberCannotDisableCuzDevice      = 9029
122
+	ErrorCodeDeviceNumberCannotDisableCuzSchedule    = 9030
123
+	ErrorCodeDeviceNumberCannotDisableCuzSchTemplate = 9031
124
+
125
+	ErrorCommitFail = 90000
126
+
127
+	ErrorCodeCreateStockInFail = 20001
128
+
129
+	ErrorCodeScheduleTemplateNotExist = 10001
130
+
131
+	ErrorCodeSystemError  = 6666
132
+	ErrorCodeProductError = 6667
133
+	ErrorCodeFieldExist   = 100001
134
+	ErrorCodeCreateConfig = 100002
135
+	ErrorCodeUpdateConfig = 100003
136
+
137
+	ErrorCodeDoubleCheckWrong     = 200003
138
+	ErrorCodeDoubleCheckUserWrong = 200004
139
+	ErrorCodeGoodNoStockInError   = 200005
140
+	ErrorCodeCancelStockFail      = 200006
141
+	ErrorCodeDeleteGoodTypeFail   = 200007
142
+	ErrorCodeDeleteGoodInfoFail   = 200008
143
+	ErrorCodeDeleteFail           = 200009
144
+
145
+	ErrorCodeKeyFail                 = 200010
146
+	ErrorCodeDeleteStockInRecordFail = 200011
147
+	ErrorCodeNameWrong               = 200012
148
+
149
+	ErrorCodeParamEmptyWrong       = 200013
150
+	ErrorCodeParamAdviceEmptyWrong = 200014
151
+
152
+	ErrorCodeParamTemplateNOEXISTWrong = 200015
153
+
154
+	ErrorCodeDeleteDealerWrong       = 200016
155
+	ErrorCodeDeleteManufacturerWrong = 200017
156
+	ErrorCodeGoodTypeNameExistError  = 200018
157
+	ErrorCodeGoodInfoNameExistError  = 200019
158
+)
159
+
160
+var ErrCodeMsgs = map[int]string{
161
+	// 登录注册错误
162
+	ErrorCodeLoginTimeout:                   "登录超时",
163
+	ErrorCodeNotLogin:                       "未登录",
164
+	ErrorCodePermissionDenied:               "权限不足",
165
+	ErrorCodeMobileRegistered:               "手机号已被注册",
166
+	ErrorCodePasswordEmpty:                  "密码为空",
167
+	ErrorCodeVerificationCodeWrong:          "验证码错误",
168
+	ErrorCodeRegisterFail:                   "注册失败",
169
+	ErrorCodeInvalidToken:                   "令牌无效",
170
+	ErrorCodeAccountOrPasswordWrong:         "账号或密码错误",
171
+	ErrorCodeMissingOrg:                     "未创建机构",
172
+	ErrorCodeMissingOrgApp:                  "未创建任何应用",
173
+	ErrorCodeAccountOrVerCodeWrong:          "账号或验证码错误",
174
+	ErrorCodeMobileNotExit:                  "手机号不存在",
175
+	ErrorCodeUserNotExist:                   "用户不存在",
176
+	ErrorCodeUserWasForbidden:               "该用户被禁用",
177
+	ErrorCodeNeverCreateTypeApp:             "未创建此种应用",
178
+	ErrorCodeContactSuperAdminCreateTypeApp: "请联系超级管理员开通此种应用",
179
+
180
+	// 数据验证错误
181
+	ErrorCodeMobileFormat:     "手机号格式错误",
182
+	ErrorCodeTelphoneFormat:   "电话格式错误",
183
+	ErrorCodeParamWrong:       "参数错误",
184
+	ErrorCodeParamFormatWrong: "参数格式错误",
185
+
186
+	// 数据库操作错误
187
+	ErrorCodeDBCreate:         "数据库创建出错",
188
+	ErrorCodeDBUpdate:         "数据库更新出错",
189
+	ErrorCodeDBDelete:         "数据库删除出错",
190
+	ErrorCodeDBSelectNoResult: "查询无结果",
191
+	ErrorCodeDataException:    "数据异常",
192
+
193
+	// 业务逻辑操作错误
194
+	ErrorCodeRoleNotExist:           "角色不存在",
195
+	ErrorCodeAdminUserNotExist:      "管理员不存在",
196
+	ErrorCodeMobileDidUsedInApp:     "该手机号已在该应用中被注册为管理员",
197
+	ErrorCodeMissingUserName:        "缺少用户名",
198
+	ErrorCodeOldPasswordWrong:       "原密码不正确",
199
+	ErrorCodeCannotRemoveRole:       "存在该角色的管理员,不能删除该角色",
200
+	ErrorCodeRoleMobileIsSuperAdmin: "该手机号已注册为超级管理员",
201
+
202
+	ErrorCodeGetQiniuUpToken: "获取七牛uptoken失败",
203
+	ErrorCodeCreatePatient:   "创建患者失败",
204
+	ErrorCodeDialysisNoExist: "患者透析号重复!",
205
+	ErrorCodeIdCardNoExist:   "身份证号重复!",
206
+	ErrorCodePatientNoExist:  "患者信息不存在!",
207
+	ErrorCodeUpdatePatient:   "修改患者信息失败",
208
+
209
+	ErrorCodeDialysisSolutionExist:          "该处方已经存在",
210
+	ErrorCodeDialysisSolutionCreate:         "创建处方失败",
211
+	ErrorCodeDialysisSolutionUpdate:         "修改处方失败",
212
+	ErrorCodeDialysisSolutionNotExist:       "该处方不存在",
213
+	ErrorCodeParentDialysisSolutionNotExist: "上级处方不存在",
214
+	ErrorCodeAlReadyHadChildSolution:        "所选处方已经存在子方案",
215
+	ErrorCodeCanntCreateChildChildSolution:  "子方案不能添加子方案",
216
+	ErrorCodeDialysisSolutionUsed:           "处方已被使用,不能删除",
217
+	ErrorCodeCreateDryWeightFail:            "添加干体重失败",
218
+	ErrorCodeCreateDoctorAdviceFail:         "添加医嘱失败",
219
+	ErrorCodeUpdateDoctorAdviceFail:         "修改医嘱信息失败",
220
+	ErrorCodeDoctorAdviceNotExist:           "医嘱不存在",
221
+	ErrorCodeLongTimeAdviceNotCanntEdit:     "长期医嘱不能修改!",
222
+	ErrorCodeAdviceStoped:                   "所选医嘱已停止",
223
+	ErrorCodeParentAdviceNotExist:           "上级医嘱不存在",
224
+	ErrorCodeDeleteAdviceFail:               "删除医嘱失败",
225
+	ErrorCodeStopAdviceFail:                 "停止医嘱失败",
226
+	ErrorCodeDialysisSolutionDelete:         "删除方案失败",
227
+	ErrorCodeDeviceNumberNotTheZone:         "所选机号不在选择分区中",
228
+	ErrorCodeCreateScheduleFail:             "添加排班失败",
229
+	ErrorCodeCantSetScheduleAgainOneDay:     "同一天不可有两次排班",
230
+	ErrorCodeCantSetScheduleBeforeNow:       "不能给今天之前的日期排班",
231
+	ErrorCodeScheduleNotExist:               "排班不存在",
232
+	ErrorCodePointScheduleExist:             "所先位置排班已经存在",
233
+	ErrorCodeDeleteScheduleFail:             "取消排班失败",
234
+	ErrorCodeChangeScheduleFail:             "修改排班失败",
235
+	ErrorCodePatientPhoneUsed:               "手机号已经存在",
236
+	ErrorCodeAdviceExced:                    "医嘱已经执行",
237
+	ErrorCodeAdviceCheckBeforeExce:          "核对医嘱不能在执行医嘱之前",
238
+	ErrorCodeAdviceExceBeforeStart:          "执行医嘱不能在开始之前",
239
+	ErrorCodeAdviceChecked:                  "医嘱已经核对",
240
+	ErrorCodeExceAndCheckNotOneUser:         "核对与执行不能是同一人",
241
+	ErrorCodeCanotEditOtherAdvice:           "不能修改非本人添加的医嘱",
242
+	ErrorCodeEditLapsetoFail:                "转归失败",
243
+	ErrorCodeDelScheduleFailByDialysis:      "已经上机透析,不能取消排班",
244
+	ErrorCodeNotSelectLapsetoType:           "请选择转归状态",
245
+	ErrorCodeNotSelectLapsetoTime:           "请选择转归时间",
246
+
247
+	ErrorCodeInspectionDateExit:    "当天已经存在检验检查记录",
248
+	ErrorCodeInspectionAddFail:     "添加记录失败",
249
+	ErrorCodeInspectionDateNotExit: "当天不存在检验检查记录",
250
+	ErrorCodeInspectionEditFail:    "修改记录失败",
251
+	ErrorCodeInspectionDeleteFail:  "删除记录失败",
252
+
253
+	ErrorCodeDeviceZoneNotExist:                      "设备分区不存在",
254
+	ErrorCodeDeviceZoneNameRepeat:                    "该分区名已存在",
255
+	ErrorCodeDeviceGroupNotExist:                     "设备分组不存在",
256
+	ErrorCodeDeviceGroupNameRepeat:                   "该分组名已存在",
257
+	ErrorCodeDeviceNumberNotExist:                    "机号不存在",
258
+	ErrorCodeDeviceNumberRepeat:                      "该机号已存在",
259
+	ErrorCodeDeviceNotExist:                          "该设备不存在",
260
+	ErrorCodeDeviceZoneCannotDisable:                 "该分区存在床位号,不能删除",
261
+	ErrorCodeDeviceNumberCannotDisableCuzDevice:      "该床位存在设备,不能删除",
262
+	ErrorCodeDeviceNumberCannotDisableCuzSchedule:    "该床位尚有排班安排,不能删除",
263
+	ErrorCodeDeviceNumberCannotDisableCuzSchTemplate: "排班模板在该床位尚有排班安排,不能删除",
264
+
265
+	ErrorCodeNotSubscibe:       "没有订阅服务或服务已过期,请先购买服务!",
266
+	ErrorCodeServeNotExist:     "服务订单不存在!",
267
+	ErrorCodeInvoiceExist:      "已经申请了发票!",
268
+	ErrorCodeApplyInvoiceFail:  "申请发票失败!",
269
+	ErrorCodeHetongHad:         "合同已经存在!",
270
+	ErrorCodeCreateHetongFail:  "合同创建失败",
271
+	ErrorCodePatientReachLimit: "患者数已达到当前服务版本病人数,需要升级到更高的版本",
272
+
273
+	ErrorCodeMonitorCreate:                  "创建监测失败",
274
+	ErrorCodeMonitorNotExist:                "监测记录不存在",
275
+	ErrorCodeMonitorUpdate:                  "修改监测失败",
276
+	ErrorCodeDialysisPermissionDeniedModify: "您没有权限修改其他医护的数据!",
277
+
278
+	ErrorDialysisOrderNoStart:     "尚未上机,无法执行下机操作",
279
+	ErrorDialysisOrderNoEND:       "已处于下机状态",
280
+	ErrorDialysisOrderRepeatStart: "已上机",
281
+	//ErrorCodeScheduleTemplateNotExist: "排班模板不存在",
282
+
283
+	ErrorCodeSystemError:              "系统异常",
284
+	ErrorCodeProductError:             "该服务商品已丢失",
285
+	ErrorCodeScheduleTemplateNotExist: "排班模板不存在",
286
+
287
+	ErrorCodeCreateStockInFail: "入库失败",
288
+	//ErrorCodeSystemError:  "系统异常",
289
+	//ErrorCodeProductError: "该服务商品已丢失",
290
+	ErrorCodeFieldExist:   "配置字段已存在",
291
+	ErrorCodeCreateConfig: "创建配置失败",
292
+	ErrorCodeUpdateConfig: "修改配置失败",
293
+
294
+	ErrorCommitFail:               "提交失败",
295
+	ErrorCodeDoubleCheckWrong:     "核对已完成, 无法再次提交",
296
+	ErrorCodeDoubleCheckUserWrong: "你已完成核对,不能重复核对",
297
+	ErrorCodeGoodNoStockInError:   "该商品尚未入库",
298
+
299
+	ErrorCodeCancelStockFail:    "出库退库失败",
300
+	ErrorCodeDeleteGoodTypeFail: "该类型存在商品信息,无法删除",
301
+	ErrorCodeDeleteGoodInfoFail: "该商品已经入库无法删除",
302
+
303
+	ErrorCodeDeleteFail: "删除失败",
304
+
305
+	ErrorCodeKeyFail:                 "关键字不能为空",
306
+	ErrorCodeDeleteStockInRecordFail: "该记录已经有出库或退货操作,无法删除",
307
+	ErrorCodeNameWrong:               "该模版名字已存在",
308
+	ErrorCodeParamEmptyWrong:         "模版名称不能为空",
309
+	ErrorCodeParamAdviceEmptyWrong:   "医嘱名称不能为空",
310
+
311
+	ErrorCodeDeleteDealerWrong:       "该经销商所属商品已入库无法删除",
312
+	ErrorCodeDeleteManufacturerWrong: "该厂商所属商品已入库无法删除",
313
+	ErrorCodeGoodTypeNameExistError:  "该商品类型名字已存在",
314
+	ErrorCodeGoodInfoNameExistError:  "该规格名称名字已存在",
315
+}
316
+
317
+type SGJError struct {
318
+	Code int
319
+}
320
+
321
+func (e *SGJError) Error() string {
322
+	value, ok := ErrCodeMsgs[e.Code]
323
+	if ok {
324
+		return value
325
+	} else {
326
+		return "未知错误"
327
+	}
328
+}
329
+
330
+func MakeSuccessResponseJSON(data map[string]interface{}) map[string]interface{} {
331
+	json := make(map[string]interface{})
332
+	if data != nil {
333
+		json["data"] = data
334
+	} else {
335
+		json["data"] = make(map[string]interface{})
336
+	}
337
+	json["state"] = 1
338
+	json["code"] = 0
339
+	return json
340
+}
341
+
342
+func MakeFailResponseJSON(errMsg string, errCode int) map[string]interface{} {
343
+	json := make(map[string]interface{})
344
+	json["msg"] = errMsg
345
+	json["code"] = errCode
346
+	json["state"] = 0
347
+	return json
348
+}
349
+
350
+func MakeFailResponseJSONWithSGJError(err *SGJError) map[string]interface{} {
351
+	if err == nil {
352
+		utils.WarningLog("MakeFailResponseJSONWithSGJError 参数err 不能为空")
353
+		return nil
354
+	}
355
+	return MakeFailResponseJSON(err.Error(), err.Code)
356
+}
357
+
358
+func MakeFailResponseJSONWithSGJErrorCode(code int) map[string]interface{} {
359
+	err := &SGJError{Code: code}
360
+	return MakeFailResponseJSON(err.Error(), err.Code)
361
+}

+ 8 - 0
main.go View File

@@ -2,9 +2,17 @@ package main
2 2
 
3 3
 import (
4 4
 	_ "wsc-go/routers"
5
+
6
+	"wsc-go/service"
5 7
 	"github.com/astaxie/beego"
6 8
 )
7 9
 
10
+
11
+func init() {
12
+	service.ConnectDB()
13
+}
14
+
15
+
8 16
 func main() {
9 17
 	beego.Run()
10 18
 }

+ 69 - 0
models/admin_user_models.go View File

@@ -0,0 +1,69 @@
1
+package models
2
+
3
+type AdminUser struct {
4
+	Id           int64  `gorm:"PRIMARY_KEY;AUTO_INCREMENT" json:"id"` // 管理员用户 ID
5
+	Mobile       string `json:"mobile"`
6
+	Password     string `json:"password"`
7
+	IsSuperAdmin bool   `gorm:"column:is_super_admin" json:"is_super_admin"` // 是否为超级管理员
8
+	Status       int8   `json:"status"`                                      // 状态 0.无效 1.有效
9
+	CreateTime   int64  `gorm:"column:ctime" json:"ctime"`                   // 创建时间
10
+	ModifyTime   int64  `gorm:"column:mtime" json:"mtime"`                   // 修改时间
11
+}
12
+
13
+func (AdminUser) TableName() string {
14
+	return "sgj_user_admin"
15
+}
16
+
17
+type AdminUserLoginLog struct {
18
+	Id          int64  `gorm:"PRIMARY_KEY;AUTO_INCREMENT"` // 记录 ID
19
+	AdminUserId int64  `gorm:"column:admin_user_id"`
20
+	OrgId       int64  `gorm:"column:org_id"`
21
+	AppId       int64  `gorm:"column:app_id"`
22
+	IP          string `gorm:"column:ip"`
23
+	OperateType int8   `gorm:"column:operate_type"` // 操作类型(1.登录;2.退出;3.切换机构)
24
+	AppType     int8   `gorm:"column:app_type"`     // 应用类型,与 OrgApp.AppType 一致
25
+	CreateTime  int64  `gorm:"column:ctime"`        // 创建时间
26
+}
27
+
28
+func (AdminUserLoginLog) TableName() string {
29
+	return "sgj_user_admin_login_log"
30
+}
31
+
32
+type AdminUserElectronicSignature struct {
33
+	ID      int64  `gorm:"column:id" json:"id" form:"id"`
34
+	Creator int64  `gorm:"column:creator" json:"creator" form:"creator"`
35
+	OrgId   int64  `gorm:"column:org_id" json:"org_id" form:"org_id"`
36
+	AppId   int64  `gorm:"column:app_id" json:"app_id" form:"app_id"`
37
+	Url     string `gorm:"column:url" json:"url" form:"url"`
38
+	Hash    string `gorm:"column:hash" json:"hash" form:"hash"`
39
+	Status  int64  `gorm:"column:status" json:"status" form:"status"`
40
+	Ctime   int64  `gorm:"column:ctime" json:"ctime" form:"ctime"`
41
+	Mtime   int64  `gorm:"column:mtime" json:"mtime" form:"mtime"`
42
+}
43
+
44
+func (AdminUserElectronicSignature) TableName() string {
45
+	return "sgj_user_admin_electronic_signature"
46
+}
47
+
48
+// 管理员用户特殊权限,详见表注释
49
+type AdminUserSpecialPermission struct {
50
+	ID          int64 `gorm:"column:id" json:"id"`
51
+	OrgID       int64 `gorm:"column:org_id" json:"org_id"`
52
+	AppID       int64 `gorm:"column:app_id" json:"app_id"`
53
+	AdminUserID int64 `gorm:"column:admin_user_id" json:"admin_user_id"`
54
+	Permission  int64 `gorm:"column:permission" json:"permission"`
55
+	Status      int64 `gorm:"column:status" json:"-"`
56
+	CreateTime  int64 `gorm:"column:ctime" json:"-"`
57
+	ModifyTime  int64 `gorm:"column:mtime" json:"-"`
58
+}
59
+
60
+func (AdminUserSpecialPermission) TableName() string {
61
+	return "xt_admin_user_special_permission"
62
+}
63
+
64
+type SpecialPermissionType int64
65
+
66
+const (
67
+	_                              SpecialPermissionType = iota
68
+	SpecialPermissionTypeHeadNurse                       // 护士长
69
+)

+ 18 - 0
models/district_models.go View File

@@ -0,0 +1,18 @@
1
+package models
2
+
3
+type District struct {
4
+	ID        int64  `gorm:"column:id" json:"id" form:"id"`
5
+	Name      string `gorm:"column:name" json:"name" form:"name"`
6
+	Level     int64  `gorm:"column:level" json:"level" form:"level"`
7
+	Upid      int64  `gorm:"column:upid" json:"upid" form:"upid"`
8
+	Path      string `gorm:"column:path" json:"path" form:"path"`
9
+	Namepath  string `gorm:"column:namepath" json:"namepath" form:"namepath"`
10
+	Initial   string `gorm:"column:initial" json:"initial" form:"initial"`
11
+	Longitude string `gorm:"column:longitude" json:"longitude" form:"longitude"`
12
+	Latitude  string `gorm:"column:latitude" json:"latitude" form:"latitude"`
13
+	Adcode    int64  `gorm:"column:adcode" json:"adcode" form:"adcode"`
14
+}
15
+
16
+func (District) TableName() string {
17
+	return "sgj_user_district"
18
+}

+ 104 - 0
models/org_models.go View File

@@ -0,0 +1,104 @@
1
+package models
2
+
3
+type Org struct {
4
+	Id              int64  `gorm:"PRIMARY_KEY;AUTO_INCREMENT" json:"id"` // 机构 ID
5
+	Creator         int64  `json:"creator"`                              // 创建者,即管理员用户的 id
6
+	OrgName         string `gorm:"column:org_name" json:"org_name"`
7
+	OrgShortName    string `gorm:"column:org_short_name" json:"org_short_name"` // 简称
8
+	OrgLogo         string `gorm:"column:org_logo" json:"org_logo"`
9
+	OrgIntroduction string `gorm:"column:org_introduction" json:"org_introduction"`
10
+	Province        int64  `json:"province"` // 省,代号,下面的市、区也一样
11
+	City            int64  `json:"city"`
12
+	District        int64  `json:"district"`
13
+	Address         string `json:"address"`                   // 详细地址
14
+	Illness         string `json:"illness"`                   // 服务病种 多个并用“,”隔开
15
+	Status          int8   `json:"status"`                    // 状态 0.无效 1.有效 2.禁用
16
+	CreateTime      int64  `gorm:"column:ctime" json:"ctime"` // 创建时间
17
+	ModifyTime      int64  `gorm:"column:mtime" json:"mtime"` // 修改时间
18
+
19
+	OrgType        int64         `gorm:"column:org_type" json:"org_type"`
20
+	Evaluate       float64       `gorm:"column:evaluate" json:"evaluate"`
21
+	Comments       int64         `gorm:"column:comments" json:"comments"`
22
+	OperatingState int64         `gorm:"column:operating_state" json:"operating_state"`
23
+	Claim          int64         `gorm:"column:claim" json:"claim"`
24
+	Telephone      string        `gorm:"column:telephone" json:"telephone"`
25
+	BusinessWeek   string        `gorm:"column:business_week" json:"business_week"`
26
+	BusinessTime   string        `gorm:"column:business_time" json:"business_time"`
27
+	Gallery        string        `gorm:"column:gallery" json:"gallery"`
28
+	ContactName    string        `gorm:"column:contact_name" json:"contact_name"`
29
+	OrgGallery     []*OrgGallery `gorm:"ForeignKey:OrgId" json:"org_gallery"`
30
+}
31
+
32
+func (Org) TableName() string {
33
+	return "sgj_user_org"
34
+}
35
+
36
+type OrgGallery struct {
37
+	ID     int64  `gorm:"column:id" json:"id" form:"id"`
38
+	Url    string `gorm:"column:url" json:"url" form:"url"`
39
+	Type   int64  `gorm:"column:type" json:"type" form:"type"`
40
+	OrgId  int64  `gorm:"column:org_id" json:"org_id" form:"org_id"`
41
+	UserId int64  `gorm:"column:user_id" json:"user_id" form:"user_id"`
42
+	Status int64  `gorm:"column:status" json:"status" form:"status"`
43
+	Ctime  int64  `gorm:"column:ctime" json:"ctime" form:"ctime"`
44
+	Mtime  int64  `gorm:"column:mtime" json:"mtime" form:"mtime"`
45
+}
46
+
47
+func (OrgGallery) TableName() string {
48
+	return "sgj_user_org_gallery"
49
+}
50
+
51
+type OrgApp struct {
52
+	Id         int64 `gorm:"PRIMARY_KEY;AUTO_INCREMENT" json:"id"` // ID
53
+	AppType    int   `gorm:"column:app_type" json:"app_type"`      // 应用类型 1.病友经营;2.科普号;3.血透经营;4.慢病管理
54
+	Creator    int   `json:"creator"`                              // 创建者,即管理员用户的 id
55
+	OrgId      int   `gorm:"column:org_id" json:"org_id"`
56
+	Status     int8  `json:"status"`                    // 状态 0.无效 1.有效 2.禁用
57
+	CreateTime int64 `gorm:"column:ctime" json:"ctime"` // 创建时间
58
+	ModifyTime int64 `gorm:"column:mtime" json:"mtime"` // 修改时间
59
+}
60
+
61
+func (OrgApp) TableName() string {
62
+	return "sgj_user_org_app"
63
+}
64
+
65
+type OrgBan struct {
66
+	ID      int64  `gorm:"column:id" json:"id"`
67
+	OrgId   int64  `gorm:"column:org_id" json:"org_id"`
68
+	Reason  string `gorm:"column:reason" json:"reason"`
69
+	Ctime   int64  `gorm:"column:ctime" json:"ctime"`
70
+	BanTime int64  `gorm:"column:ban_time" json:"ban_time"`
71
+	Status  int64  `gorm:"column:status" json:"status"`
72
+	Mtime   int64  `gorm:"column:mtime" json:"mtime"`
73
+}
74
+
75
+func (OrgBan) TableName() string {
76
+	return "sgj_user_admin_org_ban"
77
+}
78
+
79
+type OrgType struct {
80
+	ID          int64  `gorm:"column:id" json:"id" form:"id"`
81
+	Name        string `gorm:"column:name" json:"name" form:"name"`
82
+	ShortName   string `gorm:"column:short_name" json:"short_name" form:"short_name"`
83
+	Pid         int64  `gorm:"column:pid" json:"pid" form:"pid"`
84
+	Status      int64  `gorm:"column:status" json:"status" form:"status"`
85
+	CreatedTime int64  `gorm:"column:created_time" json:"created_time" form:"created_time"`
86
+	UpdatedTime int64  `gorm:"column:updated_time" json:"updated_time" form:"updated_time"`
87
+	SortNo      int64  `gorm:"column:sort_no" json:"sort_no" form:"sort_no"`
88
+}
89
+
90
+func (OrgType) TableName() string {
91
+	return "sgj_user_org_type"
92
+}
93
+
94
+type Illness struct {
95
+	ID          int64  `gorm:"column:id" json:"id"`
96
+	IllnessName string `gorm:"column:illness_name" json:"illness_name"`
97
+	Status      int64  `gorm:"column:status" json:"status"`
98
+	CreatedTime int64  `gorm:"column:created_time" json:"created_time"`
99
+	UpdatedTime int64  `gorm:"column:updated_time" json:"updated_time"`
100
+}
101
+
102
+func (Illness) TableName() string {
103
+	return "sgj_user_illness"
104
+}

+ 37 - 0
models/purview_models.go View File

@@ -0,0 +1,37 @@
1
+package models
2
+
3
+type Purview struct {
4
+	Id                  int64  `gorm:"PRIMARY_KEY;AUTO_INCREMENT" json:"id"`
5
+	Parentid            int64  `json:"pid"`                                                // 父级ID
6
+	Module              int8   `json:"module"`                                             // 所属应用类型 1.病友经营;2.科普号;3.血透经营;4.慢病管理;
7
+	Name                string `json:"name"`                                               // 规则名称(也是菜单名)
8
+	Urlfor              string `json:"urlfor"`                                             // 规则唯一英文标识,(Controller.Method)
9
+	MenuIconClass       string `gorm:"menu_icon_class" json:"menu_icon_class"`             // 菜单图标的 css 样式
10
+	SuperAdminExclusive int8   `gorm:"super_admin_exclusive" json:"super_admin_exclusive"` // 是否为超级管理员专属 0否1是
11
+	Listorder           int    `json:"-"`                                                  // 排序ID
12
+	Status              int8   `json:"status"`                                             // 状态 0.无效 1.有效 2.禁用
13
+	CreateTime          int64  `gorm:"column:ctime" json:"-"`                              // 创建时间
14
+	ModifyTime          int64  `gorm:"column:mtime" json:"-"`                              // 修改时间
15
+
16
+	Link   string     `gorm:"-" json:"link"`   // urlfor 解析后的链接
17
+	Childs []*Purview `gorm:"-" json:"childs"` // 子节点
18
+}
19
+
20
+func (Purview) TableName() string {
21
+	return "sgj_user_purview"
22
+}
23
+
24
+type RolePurview struct {
25
+	Id         int64 `gorm:"PRIMARY_KEY;AUTO_INCREMENT"`
26
+	RoleId     int64
27
+	OrgId      int64
28
+	AppId      int64
29
+	PurviewIds string
30
+	Status     int8  // 状态 0.无效 1.有效 2.禁用
31
+	CreateTime int64 `gorm:"column:ctime"` // 创建时间
32
+	ModifyTime int64 `gorm:"column:mtime"` // 修改时间
33
+}
34
+
35
+func (RolePurview) TableName() string {
36
+	return "sgj_user_role_purview"
37
+}

+ 61 - 0
models/role_models.go View File

@@ -0,0 +1,61 @@
1
+package models
2
+
3
+type Role struct {
4
+	Id           int64  `gorm:"PRIMARY_KEY;AUTO_INCREMENT" json:"id"`
5
+	RoleName     string `gorm:"column:role_name" json:"name"`
6
+	RoleIntro    string `gorm:"column:role_introduction" json:"intro"`
7
+	Creator      int64  `json:"-"`
8
+	OrgId        int64  `gorm:"column:org_id" json:"-"`
9
+	AppId        int64  `gorm:"column:app_id" json:"-"`
10
+	IsSuperAdmin bool   `gorm:"column:is_super_admin" json:"-"`
11
+	Status       int8   `json:"status"`                // 状态 0.无效 1.有效 2.禁用
12
+	CreateTime   int64  `gorm:"column:ctime" json:"-"` // 创建时间
13
+	ModifyTime   int64  `gorm:"column:mtime" json:"-"` // 修改时间
14
+}
15
+
16
+func (Role) TableName() string {
17
+	return "sgj_user_role"
18
+}
19
+
20
+type App_Role struct {
21
+	Id          int64  `gorm:"PRIMARY_KEY;AUTO_INCREMENT" json:"id"`
22
+	AdminUserId int64  `gorm:"column:admin_user_id" json:"admin_user_id"`
23
+	OrgId       int64  `gorm:"column:org_id" json:"org_id"`
24
+	AppId       int64  `gorm:"column:app_id" json:"app_id"`
25
+	RoleId      int64  `gorm:"column:role_id" json:"role_id"`
26
+	Avatar      string `json:"avatar" json:"avatar"`
27
+	UserName    string `gorm:"column:user_name" json:"user_name"`   // 用户名称
28
+	Intro       string `json:"intro"`                               // 简介
29
+	UserType    int8   `gorm:"column:user_type" json:"user_type"`   // 用户类型(1.管理员;2.医生;3.护士;4.运营)
30
+	UserTitle   int8   `gorm:"column:user_title" json:"user_title"` // 用户职称(1.医士;2.医师;3.住院医师;4.主治医师;5.副主任医师;6.主任医师;7.护士;8.护师;9.主管护师;10.副主任护师;11.主任护师;12.运营专员;13.运营主管)
31
+	Status      int8   `json:"status"`                              // 状态 0.无效 1.有效
32
+	CreateTime  int64  `gorm:"column:ctime" json:"ctime"`           // 创建时间
33
+	ModifyTime  int64  `gorm:"column:mtime" json:"mtime"`           // 修改时间
34
+}
35
+
36
+func (App_Role) TableName() string {
37
+	return "sgj_user_admin_role"
38
+}
39
+
40
+var UserType = map[int]string{
41
+	1: "管理员",
42
+	2: "医生",
43
+	3: "护士",
44
+	4: "运营",
45
+}
46
+
47
+var UserTitle = map[int]string{
48
+	1:  "医士",
49
+	2:  "医师",
50
+	3:  "住院医师",
51
+	4:  "主治医师",
52
+	5:  "副主任医师",
53
+	6:  "主任医师",
54
+	7:  "护士",
55
+	8:  "护师",
56
+	9:  "主管护师",
57
+	10: "副主任护师",
58
+	11: "主任护师",
59
+	12: "运营专员",
60
+	13: "运营主管",
61
+}

+ 130 - 0
models/service_models.go View File

@@ -0,0 +1,130 @@
1
+package models
2
+
3
+import "time"
4
+
5
+type ServeOrder struct {
6
+	ID                    int64     `gorm:"column:id" json:"id"`
7
+	OrgId                 int64     `gorm:"column:org_id" json:"org_id"`
8
+	Period                int64     `gorm:"column:period" json:"period"`
9
+	PeriodStart           int64     `gorm:"column:period_start" json:"period_start"`
10
+	PeriodEnd             int64     `gorm:"column:period_end" json:"period_end"`
11
+	PeriodStartTime       time.Time `gorm:"column:period_start_time" json:"period_start_time"`
12
+	PeriodEndTime         time.Time `gorm:"column:period_end_time" json:"period_end_time"`
13
+	Status                int64     `gorm:"column:status" json:"status"`
14
+	CreatedTime           int64     `gorm:"column:created_time" json:"created_time"`
15
+	UpdatedTime           int64     `gorm:"column:updated_time" json:"updated_time"`
16
+	OrderNumber           string    `gorm:"column:order_number" json:"order_number"`
17
+	OrderStatus           int64     `gorm:"column:order_status" json:"order_status"`
18
+	PayType               int64     `gorm:"column:pay_type" json:"pay_type"`
19
+	PayTime               int64     `gorm:"column:pay_time" json:"pay_time"`
20
+	PaymentAmount         float64   `gorm:"column:payment_amount" json:"payment_amount"`
21
+	PayableAmount         float64   `gorm:"column:payable_amount" json:"payable_amount"`
22
+	DiscountableAmount    float64   `gorm:"column:discountable_amount" json:"discountable_amount"`
23
+	PaymentTransactionId  string    `gorm:"column:payment_transaction_id" json:"payment_transaction_id"`
24
+	ServeName             string    `gorm:"column:serve_name" json:"serve_name"`
25
+	ServeDesc             string    `gorm:"column:serve_desc" json:"serve_desc"`
26
+	ServeDuration         string    `gorm:"column:serve_duration" json:"serve_duration"`
27
+	OrderExpireTime       int64     `gorm:"column:order_expire_time" json:"order_expire_time"`
28
+	Price                 float64   `gorm:"column:price" json:"price"`
29
+	Quantity              int64     `gorm:"column:quantity" json:"quantity"`
30
+	ServeId              int64     `gorm:"column:serve_id" json:"serve_id"`
31
+	OrderExpireTimeFormat string    `gorm:"-"`
32
+}
33
+
34
+func (ServeOrder) TableName() string {
35
+	return "sgj_serve_order"
36
+}
37
+
38
+type ServeOrderInfomation struct {
39
+	ID          int64   `gorm:"column:id" json:"id"`
40
+	OrgId       int64   `gorm:"column:org_id" json:"org_id"`
41
+	OrderNumber string  `gorm:"column:order_number" json:"order_number"`
42
+	ProductId   int64   `gorm:"column:product_id" json:"product_id"`
43
+	ProductName string  `gorm:"column:product_name" json:"product_name"`
44
+	ProductDesc string  `gorm:"column:product_desc" json:"product_desc"`
45
+	Price       float64 `gorm:"column:price" json:"price"`
46
+	Quantity    int64   `gorm:"column:quantity" json:"quantity"`
47
+	MarketPrice float64 `gorm:"column:market_price" json:"market_price"`
48
+	Status      int64   `gorm:"column:status" json:"status"`
49
+}
50
+
51
+func (ServeOrderInfomation) TableName() string {
52
+	return "sgj_serve_order_infomation"
53
+}
54
+
55
+type ServeProduct struct {
56
+	ID            int64   `gorm:"column:id" json:"id"`
57
+	ServeName     string  `gorm:"column:serve_name" json:"serve_name"`
58
+	ServeDesc     string  `gorm:"column:serve_desc" json:"serve_desc"`
59
+	OriginalPrice float64 `gorm:"column:original_price" json:"original_price"`
60
+	Price         float64 `gorm:"column:price" json:"price"`
61
+	Status        int64   `gorm:"column:status" json:"status"`
62
+	CreatedTime   int64   `gorm:"column:created_time" json:"created_time"`
63
+	UpdatedTime   int64   `gorm:"column:updated_time" json:"updated_time"`
64
+	ServeDuration int64   `gorm:"column:serve_duration" json:"serve_duration"`
65
+	Edition int64   `gorm:"column:edition" json:"edition"`
66
+}
67
+
68
+func (ServeProduct) TableName() string {
69
+	return "sgj_serve_product"
70
+}
71
+
72
+type ServeSubscibe struct {
73
+	ID              int64     `gorm:"column:id" json:"id"`
74
+	OrgId           int64     `gorm:"column:org_id" json:"org_id"`
75
+	PeriodStart     int64     `gorm:"column:period_start" json:"period_start"`
76
+	PeriodEnd       int64     `gorm:"column:period_end" json:"period_end"`
77
+	PeriodStartTime time.Time `gorm:"column:period_start_time" json:"period_start_time"`
78
+	PeriodEndTime   time.Time `gorm:"column:period_end_time" json:"period_end_time"`
79
+	Status          int64     `gorm:"column:status" json:"status"`
80
+	CreatedTime     int64     `gorm:"column:created_time" json:"created_time"`
81
+	UpdatedTime     int64     `gorm:"column:updated_time" json:"updated_time"`
82
+	State           int64     `gorm:"column:state" json:"state" form:"statstateus"`
83
+	Org				Org       `gorm:"ForeignKey:OrgId"`
84
+
85
+	Patients        int64     `gorm:"-" json:"patients"`
86
+}
87
+
88
+func (ServeSubscibe) TableName() string {
89
+	return "sgj_serve_subscibe"
90
+}
91
+
92
+type ServeInvoice struct {
93
+	ID                      int64   `gorm:"column:id" json:"id" form:"id"`
94
+	InvoiceType             int64   `gorm:"column:invoice_type" json:"invoice_type" form:"invoice_type"`
95
+	OrgId                   int64   `gorm:"column:org_id" json:"org_id" form:"org_id"`
96
+	InvoiceTitle            string  `gorm:"column:invoice_title" json:"invoice_title" form:"invoice_title"`
97
+	InvoiceAmountGross      float64 `gorm:"column:invoice_amount_gross" json:"invoice_amount_gross" form:"invoice_amount_gross"`
98
+	Recipient               string  `gorm:"column:recipient" json:"recipient" form:"recipient"`
99
+	ContactPhone            string  `gorm:"column:contact_phone" json:"contact_phone" form:"contact_phone"`
100
+	Address                 string  `gorm:"column:address" json:"address" form:"address"`
101
+	TaxIdentificationNumber string  `gorm:"column:tax_identification_number" json:"tax_identification_number" form:"tax_identification_number"`
102
+	Remark                  string  `gorm:"column:remark" json:"remark" form:"remark"`
103
+	Status                  int64   `gorm:"column:status" json:"status" form:"status"`
104
+	CreatedTime             int64   `gorm:"column:created_time" json:"created_time" form:"created_time"`
105
+	UpdatedTime             int64   `gorm:"column:updated_time" json:"updated_time" form:"updated_time"`
106
+	Orders                  string  `gorm:"column:orders" json:"orders" form:"orders"`
107
+	InvoiceStatus int64 `gorm:"column:invoice_status" json:"invoice_status" form:"invoice_status"`
108
+}
109
+
110
+func (ServeInvoice) TableName() string {
111
+	return "sgj_serve_invoice"
112
+}
113
+
114
+
115
+type ServeOrderContract struct {
116
+	ID int64 `gorm:"column:id" json:"id" form:"id"`
117
+	OrgId int64 `gorm:"column:org_id" json:"org_id" form:"org_id"`
118
+	OrderId int64 `gorm:"column:order_id" json:"order_id" form:"order_id"`
119
+	OrderNumber string `gorm:"column:order_number" json:"order_number" form:"order_number"`
120
+	CompanyTitle string `gorm:"column:company_title" json:"company_title" form:"company_title"`
121
+	CompanyAddress string `gorm:"column:company_address" json:"company_address" form:"company_address"`
122
+	ContactPhone string `gorm:"column:contact_phone" json:"contact_phone" form:"contact_phone"`
123
+	Contact string `gorm:"column:contact" json:"contact" form:"contact"`
124
+	Status int64 `gorm:"column:status" json:"status" form:"status"`
125
+	CreatedTime int64 `gorm:"column:created_time" json:"created_time" form:"created_time"`
126
+	UpdatedTime int64 `gorm:"column:updated_time" json:"updated_time" form:"updated_time"`
127
+}
128
+func (ServeOrderContract) TableName() string {
129
+	return "sgj_serve_order_contract"
130
+}

+ 18 - 1
routers/router.go View File

@@ -2,9 +2,26 @@ package routers
2 2
 
3 3
 import (
4 4
 	"wsc-go/controllers"
5
+
5 6
 	"github.com/astaxie/beego"
7
+	"github.com/astaxie/beego/plugins/cors"
6 8
 )
7 9
 
8 10
 func init() {
9
-    beego.Router("/", &controllers.MainController{})
11
+	beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
12
+		// AllowAllOrigins:  true,
13
+		AllowOrigins:     []string{"http://mall.kuyicloud.com", "http://mall.test.sgjyun.com"},
14
+		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
15
+		AllowHeaders:     []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
16
+		ExposeHeaders:    []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
17
+		AllowCredentials: true,
18
+	}))
19
+
20
+	beego.Router("/", &controllers.MainController{})
21
+
22
+	controllers.VerifyUserLoginControllerRegistRouters()
23
+	controllers.QiniuApiRegistRouters()
24
+	controllers.OrgInfoApiRegistRouters()
25
+	controllers.FxlinkApiRegistRouters()
26
+
10 27
 }

+ 116 - 0
service/db.go View File

@@ -0,0 +1,116 @@
1
+// Pipe - A small and beautiful blogging platform written in golang.
2
+// Copyright (C) 2017-2018, b3log.org
3
+//
4
+// This program is free software: you can redistribute it and/or modify
5
+// it under the terms of the GNU General Public License as published by
6
+// the Free Software Foundation, either version 3 of the License, or
7
+// (at your option) any later version.
8
+//
9
+// This program is distributed in the hope that it will be useful,
10
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+// GNU General Public License for more details.
13
+//
14
+// You should have received a copy of the GNU General Public License
15
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
+
17
+package service
18
+
19
+import (
20
+	"fmt"
21
+
22
+	"github.com/astaxie/beego"
23
+	"github.com/jinzhu/gorm"
24
+	_ "github.com/jinzhu/gorm/dialects/mysql" // mysql
25
+)
26
+
27
+var readDb *gorm.DB
28
+var writeDb *gorm.DB
29
+var readUserDb *gorm.DB
30
+var writeUserDb *gorm.DB
31
+
32
+var err error
33
+
34
+func ConnectDB() {
35
+	readHost := beego.AppConfig.String("readmysqlhost")
36
+	readPort := beego.AppConfig.String("readmysqlport")
37
+	readUser := beego.AppConfig.String("readmysqluser")
38
+	readPass := beego.AppConfig.String("readmysqlpass")
39
+	readName := beego.AppConfig.String("readmysqlname")
40
+
41
+	writeHost := beego.AppConfig.String("writemysqlhost")
42
+	writePort := beego.AppConfig.String("writemysqlport")
43
+	writeUser := beego.AppConfig.String("writemysqluser")
44
+	writePass := beego.AppConfig.String("writemysqlpass")
45
+	writeName := beego.AppConfig.String("writemysqlname")
46
+
47
+	readUserHost := beego.AppConfig.String("readuserhost")
48
+	readUserPort := beego.AppConfig.String("readuserport")
49
+	readUserUser := beego.AppConfig.String("readuseruser")
50
+	readUserPass := beego.AppConfig.String("readuserpass")
51
+	readUserName := beego.AppConfig.String("readusername")
52
+
53
+	writeUserHost := beego.AppConfig.String("writeuserhost")
54
+	writeUserPort := beego.AppConfig.String("writeuserport")
55
+	writeUserUser := beego.AppConfig.String("writeuseruser")
56
+	writeUserPass := beego.AppConfig.String("writeuserpass")
57
+	writeUserName := beego.AppConfig.String("writeusername")
58
+
59
+	rdsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", readUser, readPass, readHost, readPort, readName)
60
+	wdsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", writeUser, writePass, writeHost, writePort, writeName)
61
+
62
+	rudsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", readUserUser, readUserPass, readUserHost, readUserPort, readUserName)
63
+	wudsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", writeUserUser, writeUserPass, writeUserHost, writeUserPort, writeUserName)
64
+
65
+	readDb, err = gorm.Open("mysql", rdsn)
66
+	if err != nil {
67
+		beego.Error(err)
68
+	}
69
+	readDb.DB().SetMaxIdleConns(10)
70
+	readDb.DB().SetMaxOpenConns(100)
71
+	readDb.LogMode(true)
72
+
73
+	writeDb, err = gorm.Open("mysql", wdsn)
74
+	if err != nil {
75
+		beego.Error(err)
76
+	}
77
+	writeDb.DB().SetMaxIdleConns(10)
78
+	writeDb.DB().SetMaxOpenConns(100)
79
+	writeDb.LogMode(true)
80
+
81
+	readUserDb, err = gorm.Open("mysql", rudsn)
82
+	if err != nil {
83
+		beego.Error(err)
84
+	}
85
+	readUserDb.DB().SetMaxIdleConns(10)
86
+	readUserDb.DB().SetMaxOpenConns(100)
87
+	readUserDb.LogMode(true)
88
+
89
+	writeUserDb, err = gorm.Open("mysql", wudsn)
90
+	if err != nil {
91
+		beego.Error(err)
92
+	}
93
+	writeUserDb.DB().SetMaxIdleConns(10)
94
+	writeUserDb.DB().SetMaxOpenConns(100)
95
+	writeUserDb.LogMode(true)
96
+
97
+}
98
+
99
+//func DisconnectDB() {
100
+//	if err := readDb.Close(); nil != err {
101
+//		beego.Error("Disconnect from database failed: " + err.Error())
102
+//	}
103
+//}
104
+
105
+func XTReadDB() *gorm.DB {
106
+	return readDb
107
+}
108
+func XTWriteDB() *gorm.DB {
109
+	return writeDb
110
+}
111
+func UserReadDB() *gorm.DB {
112
+	return readUserDb
113
+}
114
+func UserWriteDB() *gorm.DB {
115
+	return writeUserDb
116
+}

+ 10 - 0
service/district_service.go View File

@@ -0,0 +1,10 @@
1
+package service
2
+
3
+import (
4
+	"wsc-go/models"
5
+)
6
+
7
+func GetDistrictsByUpid(id int64) (dis []*models.District, err error) {
8
+	err = readUserDb.Model(&models.District{}).Where("upid=?", id).Find(&dis).Error
9
+	return
10
+}

+ 28 - 0
service/fx_token_service.go View File

@@ -0,0 +1,28 @@
1
+package service
2
+
3
+import (
4
+	"crypto/md5"
5
+	"fmt"
6
+	"time"
7
+
8
+	"github.com/astaxie/beego"
9
+)
10
+
11
+func CreateFxToken(orgId int64, adminId int) (string, int64) {
12
+
13
+	// $_GPC['fxtoken']) && isset($_GPC['fxorgid']) && isset($_GPC['timestamp']) && isset($_GPC['fxadmin']
14
+	nowTime := time.Now().Unix()
15
+	fxKey := beego.AppConfig.String("fxtokenkey")
16
+	stringA := fmt.Sprintf("org_id=%d&time=%d", orgId, nowTime)
17
+
18
+	data := []byte(stringA)
19
+	has := md5.Sum(data)
20
+	md5str := fmt.Sprintf("%x", has)
21
+	stringB := fmt.Sprintf("string=%s&key=%s", md5str, fxKey)
22
+
23
+	data = []byte(stringB)
24
+	has = md5.Sum(data)
25
+	signToken := fmt.Sprintf("%x", has)
26
+
27
+	return signToken, nowTime
28
+}

+ 31 - 0
service/orginfo_service.go View File

@@ -0,0 +1,31 @@
1
+package service
2
+
3
+import (
4
+	"time"
5
+	"wsc-go/models"
6
+)
7
+
8
+func GetOrgTypes() (ots []*models.OrgType, err error) {
9
+	err = readUserDb.Model(&models.OrgType{}).Where("status=1").Order("sort_no").Find(&ots).Error
10
+	return
11
+}
12
+
13
+func UpdateOrgInfo(org *models.Org) (err error) {
14
+	err = writeUserDb.Model(&models.Org{}).Where("id=?", org.Id).Update(org).Error
15
+	return
16
+}
17
+
18
+func GetIllnessList() (ills []*models.Illness, err error) {
19
+	err = readUserDb.Where("status=1").Find(&ills).Error
20
+	return
21
+}
22
+
23
+func CreateOrgGalleryItem(item *models.OrgGallery) (err error) {
24
+	err = writeUserDb.Create(item).Error
25
+	return
26
+}
27
+
28
+func DeleteOrgGalleryItem(id int64) (err error) {
29
+	err = writeUserDb.Model(&models.OrgGallery{}).Where("id=?", id).Update(map[string]interface{}{"Status": 0, "Mtime": time.Now().Unix()}).Error
30
+	return
31
+}

+ 21 - 0
service/redis.go View File

@@ -0,0 +1,21 @@
1
+package service
2
+
3
+import (
4
+	"fmt"
5
+
6
+	"github.com/astaxie/beego"
7
+	"github.com/go-redis/redis"
8
+)
9
+
10
+func RedisClient() *redis.Client {
11
+	address := fmt.Sprintf("%s:%s", beego.AppConfig.String("redishost"), beego.AppConfig.String("redisport"))
12
+	client := redis.NewClient(&redis.Options{
13
+		Addr:     address,
14
+		Password: beego.AppConfig.String("redispasswrod"), // no password set
15
+		DB:       0,                                       // use default DB
16
+	})
17
+
18
+	// pong, err := client.Ping().Result()
19
+	// fmt.Println(pong, err)
20
+	return client
21
+}

+ 405 - 0
service/role_service.go View File

@@ -0,0 +1,405 @@
1
+package service
2
+
3
+import (
4
+	"time"
5
+
6
+	"wsc-go/models"
7
+	"wsc-go/utils"
8
+
9
+	"github.com/jinzhu/gorm"
10
+)
11
+
12
+func GetRoles(orgID int64, appID int64, page int, count int) ([]*models.Role, int, error) {
13
+	var roles []*models.Role
14
+	var totalCount int
15
+	err := readUserDb.Model(&models.Role{}).
16
+		Where("org_id = ? AND app_id = ?", orgID, appID).
17
+		Count(&totalCount).
18
+		Order("ctime asc").Limit(count).Offset((page - 1) * count).
19
+		Find(&roles).
20
+		Error
21
+	if err != nil {
22
+		if err == gorm.ErrRecordNotFound {
23
+			return make([]*models.Role, 0), 0, nil
24
+		} else {
25
+			return nil, 0, err
26
+		}
27
+	}
28
+	return roles, totalCount, nil
29
+}
30
+
31
+func GetAppRole(orgID int64, appID int64, adminUserID int64) (*models.App_Role, error) {
32
+	var appRole models.App_Role
33
+	err := readUserDb.Model(models.App_Role{}).Where("org_id = ? and app_id = ? and admin_user_id = ?", orgID, appID, adminUserID).First(&appRole).Error
34
+	if err != nil {
35
+		if err == gorm.ErrRecordNotFound {
36
+			return nil, nil
37
+		} else {
38
+			return nil, err
39
+		}
40
+	}
41
+	return &appRole, nil
42
+}
43
+
44
+func CreateRole(adminUserID int64, orgID int64, appID int64, name string, intro string) (*models.Role, error) {
45
+	role := models.Role{
46
+		RoleName:     name,
47
+		RoleIntro:    intro,
48
+		Creator:      adminUserID,
49
+		OrgId:        orgID,
50
+		AppId:        appID,
51
+		IsSuperAdmin: false,
52
+		Status:       1,
53
+		CreateTime:   time.Now().Unix(),
54
+		ModifyTime:   time.Now().Unix(),
55
+	}
56
+	tx := writeUserDb.Begin()
57
+	if err := tx.Create(&role).Error; err != nil {
58
+		tx.Rollback()
59
+		return nil, err
60
+	}
61
+	tx.Commit()
62
+	return &role, nil
63
+}
64
+
65
+func GetRoleByRoleID(roleID int64) (*models.Role, error) {
66
+	var role models.Role
67
+	err := readUserDb.Model(&models.Role{}).Where("id = ?", roleID).First(&role).Error
68
+	if err != nil {
69
+		if err == gorm.ErrRecordNotFound {
70
+			return nil, nil
71
+		}
72
+		return nil, err
73
+	} else {
74
+		return &role, nil
75
+	}
76
+}
77
+
78
+func ModifyRole(role *models.Role) error {
79
+	tx := writeUserDb.Begin()
80
+	if err := tx.Save(role).Error; err != nil {
81
+		tx.Rollback()
82
+		return err
83
+	}
84
+	return tx.Commit().Error
85
+}
86
+
87
+// 拥有xx角色的管理员的数量
88
+func RoleAdminUserCount(orgID int64, appID int64, roleID int64) (int, error) {
89
+	var count int
90
+	err := readUserDb.Model(models.App_Role{}).
91
+		Where("org_id = ? AND app_id = ? AND role_id = ? AND status = 1", orgID, appID, roleID).
92
+		Count(&count).
93
+		Error
94
+	if err != nil {
95
+		return 0, err
96
+	} else {
97
+		return count, nil
98
+	}
99
+}
100
+
101
+type AdminUserManageViewModel struct {
102
+	AdminUserId int    `gorm:"admin_user_id" json:"user_id"`
103
+	UserName    string `gorm:"user_name" json:"user_name"`
104
+	RoleName    string `gorm:"role_name" json:"role_name"`
105
+	UserTitle   int    `gorm:"user_title" json:"user_title"`
106
+	Ip          string `gorm:"ip" json:"ip"`
107
+	Ctime       int64  `gorm:"ctime" json:"last_login_time"`
108
+	Status      int    `gorm:"status" json:"status"`
109
+
110
+	// LastLoginTimeStr string `gorm:"-" json:"last_login_time_formatted"`
111
+	TitleName string `gorm:"-" json:"title_name"`
112
+}
113
+
114
+func GetAdminUsersAndLoginInfo(orgID int64, appID int64, page int, count int) ([]*AdminUserManageViewModel, int, error) {
115
+	if count <= 0 {
116
+		return []*AdminUserManageViewModel{}, 0, nil
117
+	}
118
+	if page < 1 {
119
+		page = 1
120
+	}
121
+	var viewModels []*AdminUserManageViewModel = make([]*AdminUserManageViewModel, 0)
122
+	rows, err := readUserDb.Raw("SELECT u_a_r.admin_user_id, u_a_r.user_name, u_r.role_name, u_a_r.user_title, u_l.ip, u_l.ctime, u_a_r.status FROM sgj_user_admin_role AS u_a_r INNER JOIN sgj_user_role AS u_r ON u_a_r.org_id = u_r.org_id AND u_a_r.app_id = u_r.app_id AND u_r.id = u_a_r.role_id LEFT JOIN (SELECT * FROM (SELECT admin_user_id, org_id, app_id, ip, ctime FROM sgj_user_admin_login_log WHERE org_id = ? AND app_id = ? ORDER BY ctime DESC) AS t GROUP BY admin_user_id) AS u_l ON u_a_r.org_id = u_l.org_id AND u_a_r.app_id = u_l.app_id AND u_a_r.admin_user_id = u_l.admin_user_id WHERE u_a_r.org_id = ? AND u_a_r.app_id = ? GROUP BY u_a_r.admin_user_id LIMIT ? OFFSET ?;", orgID, appID, orgID, appID, count, (page-1)*count).Rows()
123
+	defer rows.Close()
124
+	if err != nil {
125
+		if err == gorm.ErrRecordNotFound {
126
+			return viewModels, 0, nil
127
+		} else {
128
+			return nil, 0, err
129
+		}
130
+	}
131
+	for rows.Next() {
132
+		var viewModel AdminUserManageViewModel
133
+		readUserDb.ScanRows(rows, &viewModel)
134
+		title, _ := models.UserTitle[viewModel.UserTitle]
135
+		viewModel.TitleName = title
136
+		// if viewModel.Ctime == 0 {
137
+		// 	viewModel.LastLoginTimeStr = ""
138
+		// } else {
139
+		// 	loginTime := time.Unix(viewModel.Ctime, 0)
140
+		// 	viewModel.LastLoginTimeStr = loginTime.Format("2006-01-02 15:04")
141
+		// }
142
+		viewModels = append(viewModels, &viewModel)
143
+	}
144
+	total := 0
145
+	readUserDb.Table("sgj_user_admin_role as u_a_r").Joins("join sgj_user_role as u_r on u_r.org_id = u_a_r.org_id AND u_r.app_id = u_a_r.app_id AND u_r.id = u_a_r.role_id").Where("u_a_r.org_id = ? AND u_a_r.app_id = ?", orgID, appID).Count(&total)
146
+	return viewModels, total, nil
147
+}
148
+
149
+func GetValidRoleCount(orgID int64, appID int64, superAdminUserID int64) (int, error) {
150
+	var count int
151
+	err := readUserDb.Model(models.Role{}).
152
+		Where("org_id = ? AND app_id = ? AND creator = ? AND is_super_admin = 0 AND status = 1", orgID, appID, superAdminUserID).
153
+		Count(&count).
154
+		Error
155
+	if err != nil {
156
+		return 0, err
157
+	} else {
158
+		return count, nil
159
+	}
160
+}
161
+
162
+func GetAllValidRoles(orgID int64, appID int64) ([]*models.Role, error) {
163
+	var roles []*models.Role
164
+	err := readUserDb.Model(models.Role{}).
165
+		Where("org_id = ? AND app_id = ? AND status = 1", orgID, appID).
166
+		Order("ctime asc").
167
+		Find(&roles).
168
+		Error
169
+	if err != nil {
170
+		if err == gorm.ErrRecordNotFound {
171
+			return make([]*models.Role, 0), nil
172
+		} else {
173
+			return nil, err
174
+		}
175
+	}
176
+	return roles, nil
177
+}
178
+
179
+func IsRoleExist(orgID int64, appID int64, roleID int64) (bool, error) {
180
+	var count int
181
+	err := readUserDb.Model(models.Role{}).Where("org_id = ? AND app_id = ? AND id = ? AND status = 1", orgID, appID, roleID).Count(&count).Error
182
+	if err != nil {
183
+		return false, err
184
+	} else {
185
+		return count > 0, nil
186
+	}
187
+}
188
+
189
+type AdminUserEditViewModel struct {
190
+	AdminUserId int64  `gorm:"admin_user_id" json:"user_id"`
191
+	UserName    string `gorm:"user_name" json:"user_name"`
192
+	Mobile      string `gorm:"mobile" json:"mobile"`
193
+	UserType    int    `gorm:"user_type" json:"user_type"`
194
+	UserTitle   int    `gorm:"user_title" json:"user_title"`
195
+	Intro       string `gorm:"intro" json:"intro"`
196
+	RoleId      int64  `gorm:"role_id" json:"role_id"`
197
+}
198
+
199
+func GetGeneralAdminUser(orgID int64, appID int64, user_id int64) (*AdminUserEditViewModel, error) {
200
+	rows, err := readUserDb.Raw("SELECT u_a.mobile, u_a_r.admin_user_id, u_a_r.user_name, u_a_r.user_type, u_a_r.user_title, u_a_r.intro, u_a_r.role_id FROM sgj_user_admin AS u_a, sgj_user_admin_role AS u_a_r WHERE u_a.id = u_a_r.admin_user_id AND u_a.id = ? AND u_a_r.status = 1 AND u_a_r.org_id = ? AND u_a_r.app_id = ?;", user_id, orgID, appID).Rows()
201
+	defer rows.Close()
202
+	if err != nil {
203
+		if err == gorm.ErrRecordNotFound {
204
+			return nil, nil
205
+		} else {
206
+			return nil, err
207
+		}
208
+	}
209
+	if rows.Next() {
210
+		var viewModel AdminUserEditViewModel
211
+		err := readUserDb.ScanRows(rows, &viewModel)
212
+		if err != nil {
213
+			return nil, err
214
+		} else {
215
+			return &viewModel, nil
216
+		}
217
+	}
218
+	return nil, nil
219
+}
220
+
221
+func SaveAppRole(appRole *models.App_Role) error {
222
+	tx := writeUserDb.Begin()
223
+	if err := tx.Model(&models.App_Role{}).Save(appRole).Error; err != nil {
224
+		tx.Rollback()
225
+		return err
226
+	}
227
+	return tx.Commit().Error
228
+}
229
+
230
+func IsMobileDidUsedAtApp(orgID int64, appID int64, mobile string) (bool, error) {
231
+	var count int
232
+	rows, err := readUserDb.Raw("select count(u_a.id) as count from sgj_user_admin as u_a, sgj_user_admin_role as u_a_r where u_a_r.org_id = ? and u_a_r.app_id = ? and u_a.mobile = ? and u_a.id = u_a_r.admin_user_id;", orgID, appID, mobile).Rows()
233
+	defer rows.Close()
234
+	if err != nil {
235
+		if err == gorm.ErrRecordNotFound {
236
+			return false, nil
237
+		} else {
238
+			return true, err
239
+		}
240
+	}
241
+	if rows.Next() {
242
+		rows.Scan(&count)
243
+		return count > 0, nil
244
+	}
245
+	return true, nil
246
+}
247
+
248
+func IsUserSuperAdminWithMobile(mobile string) (bool, error) {
249
+	var user models.AdminUser
250
+	err := readUserDb.Where("mobile = ?", mobile).First(&user).Error
251
+	if err != nil {
252
+		if err == gorm.ErrRecordNotFound {
253
+			return false, nil
254
+		} else {
255
+			return false, err
256
+		}
257
+	}
258
+	return user.IsSuperAdmin, nil
259
+}
260
+
261
+func CreateGeneralAdminUser(orgID int64, appID int64, mobile string, name string, userType int, userTitle int, intro string, roleID int64) (*models.AdminUser, string, error) {
262
+	now := time.Now().Unix()
263
+	tx := writeUserDb.Begin()
264
+	var adminUser models.AdminUser
265
+	err := readUserDb.Where("mobile = ? AND status = 1", mobile).First(&adminUser).Error
266
+	password := ""
267
+	if err != nil {
268
+		if err != gorm.ErrRecordNotFound {
269
+			return nil, "", err
270
+		} else {
271
+			password = utils.RandomNumberString(6)
272
+			adminUser.Mobile = mobile
273
+			adminUser.Password = utils.String2md5(password)
274
+			adminUser.IsSuperAdmin = false
275
+			adminUser.Status = 1
276
+			adminUser.CreateTime = now
277
+			adminUser.ModifyTime = now
278
+			if createErr := tx.Create(&adminUser).Error; createErr != nil {
279
+				tx.Rollback()
280
+				return nil, "", createErr
281
+			}
282
+		}
283
+	}
284
+	app_role := models.App_Role{
285
+		AdminUserId: adminUser.Id,
286
+		OrgId:       orgID,
287
+		AppId:       appID,
288
+		RoleId:      roleID,
289
+		Avatar:      "",
290
+		UserName:    name,
291
+		Intro:       intro,
292
+		UserType:    int8(userType),
293
+		UserTitle:   int8(userTitle),
294
+		Status:      1,
295
+		CreateTime:  now,
296
+		ModifyTime:  now,
297
+	}
298
+	if createApp_RoleErr := tx.Create(&app_role).Error; createApp_RoleErr != nil {
299
+		tx.Rollback()
300
+		return nil, "", createApp_RoleErr
301
+	}
302
+
303
+	tx.Commit()
304
+	return &adminUser, password, nil
305
+}
306
+
307
+type PurviewTreeViewModel struct {
308
+	ID     int64                   `json:"id"`
309
+	PID    int64                   `json:"pid"`
310
+	Name   string                  `json:"name"`
311
+	Childs []*PurviewTreeViewModel `json:"childs"`
312
+}
313
+
314
+func GetAllGeneralPurviewVMsProcessed() ([]*PurviewTreeViewModel, error) {
315
+	var originPurviews []*models.Purview
316
+	getPurviewErr := readUserDb.Model(models.Purview{}).Where("module = 3 AND status = 1 AND super_admin_exclusive = 0").Order("listorder asc").Order("id asc").Find(&originPurviews).Error
317
+	if getPurviewErr != nil {
318
+		return nil, getPurviewErr
319
+	}
320
+	// 加工这些规则:树形化
321
+	purviewVMs := make([]*PurviewTreeViewModel, 0)
322
+	pid_childs := make(map[int64][]*PurviewTreeViewModel)
323
+	for _, purview := range originPurviews {
324
+		// warning:下面这个算法只适用最多两层树形结构的菜单,对于两层以上的会丢失掉第三层及其以下的节点
325
+		// 因为取出 originPurviews 的时候已经排过序了,所以顶级节点肯定最先处理,不需要担心子节点比父节点先处理
326
+		pvm := &PurviewTreeViewModel{
327
+			ID:   purview.Id,
328
+			PID:  purview.Parentid,
329
+			Name: purview.Name,
330
+		}
331
+		if purview.Parentid == 0 {
332
+			purviewVMs = append(purviewVMs, pvm)
333
+		} else {
334
+			childs := pid_childs[purview.Parentid]
335
+			if childs == nil {
336
+				childs = make([]*PurviewTreeViewModel, 0)
337
+			}
338
+			childs = append(childs, pvm)
339
+			pid_childs[purview.Parentid] = childs
340
+		}
341
+	}
342
+
343
+	for _, vm := range purviewVMs {
344
+		vm.Childs = pid_childs[vm.ID]
345
+	}
346
+
347
+	return purviewVMs, nil
348
+}
349
+
350
+func GetRolePurviewIds(roleID int64) (string, error) {
351
+	var rolePurview models.RolePurview
352
+	err := readUserDb.Where("role_id = ?", roleID).First(&rolePurview).Error
353
+	if err != nil {
354
+		if err == gorm.ErrRecordNotFound {
355
+			return "", nil
356
+		} else {
357
+			return "", err
358
+		}
359
+	}
360
+	return rolePurview.PurviewIds, nil
361
+}
362
+
363
+func SaveRolePurviewIds(orgID int64, appID int64, roleID int64, purviewIds string) error {
364
+	var rolePurview models.RolePurview
365
+	getRPErr := readUserDb.Where("org_id = ? AND app_id = ? AND role_id = ?", orgID, appID, roleID).First(&rolePurview).Error
366
+	if getRPErr != nil {
367
+		if getRPErr == gorm.ErrRecordNotFound {
368
+			rolePurview = models.RolePurview{
369
+				RoleId:     roleID,
370
+				OrgId:      orgID,
371
+				AppId:      appID,
372
+				Status:     1,
373
+				CreateTime: time.Now().Unix(),
374
+			}
375
+		} else {
376
+			return getRPErr
377
+		}
378
+	}
379
+	rolePurview.PurviewIds = purviewIds
380
+	rolePurview.ModifyTime = time.Now().Unix()
381
+	tx := writeUserDb.Begin()
382
+	if err := tx.Save(&rolePurview).Error; err != nil {
383
+		tx.Rollback()
384
+		return err
385
+	}
386
+	return tx.Commit().Error
387
+}
388
+
389
+func ModifyAdminUserInfo(adminUserID int64, orgID int64, appID int64, name string, avatar string, newPassword string) error {
390
+	tx := writeUserDb.Begin()
391
+	editInfoErr := tx.Exec("update sgj_user_admin_role set user_name = ?, avatar = ?, mtime = ? where admin_user_id = ? and org_id = ?", name, avatar, time.Now().Unix(), adminUserID, orgID).Error
392
+	if editInfoErr != nil {
393
+		tx.Rollback()
394
+		return editInfoErr
395
+	}
396
+	if len(newPassword) > 0 {
397
+		editPwdErr := tx.Exec("update sgj_user_admin set password = ?, mtime = ? where id = ?", newPassword, time.Now().Unix(), adminUserID).Error
398
+		if editPwdErr != nil {
399
+			tx.Rollback()
400
+			return editPwdErr
401
+		}
402
+	}
403
+	tx.Commit()
404
+	return nil
405
+}

+ 185 - 0
service/sms_service.go View File

@@ -0,0 +1,185 @@
1
+package service
2
+
3
+import (
4
+	"bytes"
5
+	"encoding/json"
6
+	"io/ioutil"
7
+	"net/http"
8
+	"strconv"
9
+	"strings"
10
+	"time"
11
+
12
+	"wsc-go/utils"
13
+
14
+	"github.com/astaxie/beego"
15
+)
16
+
17
+type SMSServiceError struct {
18
+	Err string
19
+}
20
+
21
+func (e *SMSServiceError) Error() string {
22
+	return e.Err
23
+}
24
+
25
+/* public */
26
+
27
+// 发送验证码短信
28
+func SMSSendVerificationCode(mobile string) error {
29
+	if len(mobile) == 0 {
30
+		return &SMSServiceError{Err: "手机号为空"}
31
+	}
32
+	if err := checkVerificationCodeSMSLimit(mobile); err != nil {
33
+		return err
34
+	}
35
+
36
+	code_str := utils.RandomNumberString(6)
37
+	templateID, _ := beego.AppConfig.Int("sms_verification_code_templateid")
38
+	_, _, _, err := singleSendMessageUseUCPaas(templateID, []string{code_str}, mobile)
39
+	if err == nil {
40
+		redisClient := RedisClient()
41
+		defer redisClient.Close()
42
+		cur_date := time.Now().Format("2006-01-02")
43
+		redisClient.Set("xt_modify_pwd_"+mobile, code_str, time.Minute*10)
44
+		redisClient.Incr("xt_modify_pwd_" + mobile + "_" + cur_date).Result()
45
+	}
46
+	return err
47
+}
48
+
49
+// 成为机构管理员的邀请短信
50
+func SMSSendInviteMobileToJoinOrgAdmin(name string, mobile string, password string) error {
51
+	if len(mobile) == 0 {
52
+		return &SMSServiceError{Err: "手机号为空"}
53
+	}
54
+	if len(password) == 0 {
55
+		_, _, _, err := singleSendMessageUseUCPaas(332784, []string{name, mobile}, mobile)
56
+		return err
57
+	} else {
58
+		_, _, _, err := singleSendMessageUseUCPaas(332783, []string{name, mobile, password}, mobile)
59
+		return err
60
+	}
61
+}
62
+
63
+/* private */
64
+
65
+// 检查验证码短信请求限制
66
+func checkVerificationCodeSMSLimit(mobile string) error {
67
+	redisClient := RedisClient()
68
+	defer redisClient.Close()
69
+
70
+	cur_date := time.Now().Format("2006-01-02")
71
+	moblie_count, _ := redisClient.Get("xt_modify_pwd_" + mobile + "_" + cur_date).Result()
72
+	moblie_count_int, _ := strconv.Atoi(moblie_count)
73
+	if moblie_max := 5; moblie_count_int >= moblie_max {
74
+		return &SMSServiceError{Err: "当前手机号发送短信超过限制"}
75
+	}
76
+
77
+	return nil
78
+}
79
+
80
+/* 最底层的短信平台创建模板和发送短信的函数 */
81
+
82
+// 获取短信平台信息
83
+func getSMSConfig() (string, string, string) {
84
+	return beego.AppConfig.String("sms_appId"),
85
+		beego.AppConfig.String("sms_sid"),
86
+		beego.AppConfig.String("sms_token")
87
+}
88
+
89
+// 用云之讯群发模板短信
90
+// 返回值为发送了 n 条短信
91
+func batchSendMessageUseUCPaas(templateID int, params []string, mobiles []string) (int, []interface{}, error) {
92
+	sms_api := beego.AppConfig.String("sms_baseUrl") + "sendsms_batch"
93
+	mobileStr := strings.Join(mobiles, ",")
94
+	appID, sid, token := getSMSConfig()
95
+	requestParams := make(map[string]interface{})
96
+	requestParams["appid"] = appID
97
+	requestParams["sid"] = sid
98
+	requestParams["token"] = token
99
+	requestParams["templateid"] = strconv.Itoa(templateID)
100
+	requestParams["mobile"] = mobileStr
101
+	if params != nil && len(params) != 0 {
102
+		paramStr := strings.Join(params, ",")
103
+		requestParams["param"] = paramStr
104
+	}
105
+
106
+	paramsBytes, _ := json.Marshal(requestParams)
107
+	resp, requestErr := http.Post(sms_api, "application/json", bytes.NewBuffer(paramsBytes))
108
+
109
+	if requestErr != nil {
110
+		utils.ErrorLog("短信平台模板群发接口调用失败: %v", requestErr)
111
+		return 0, nil, requestErr
112
+	}
113
+	defer resp.Body.Close()
114
+	body, ioErr := ioutil.ReadAll(resp.Body)
115
+	if ioErr != nil {
116
+		utils.ErrorLog("短信平台模板群发接口返回数据读取失败: %v", ioErr)
117
+		return 0, nil, ioErr
118
+	}
119
+	var respJSON map[string]interface{}
120
+	utils.InfoLog(string(body))
121
+	if err := json.Unmarshal([]byte(string(body)), &respJSON); err != nil {
122
+		utils.ErrorLog("短信平台模板群发接口返回数据解析JSON失败: %v", err)
123
+		return 0, nil, err
124
+	}
125
+	if respJSON["code"].(string) != "000000" {
126
+		msg := respJSON["msg"].(string)
127
+		utils.ErrorLog("短信平台模板群发接口请求失败: %v", msg)
128
+		return 0, nil, &SMSServiceError{"短信平台模板群发接口请求失败"}
129
+
130
+	} else {
131
+		utils.SuccessLog("短信发送成功 report: %v", respJSON["report"])
132
+		if len(mobiles) > 1 {
133
+			count, _ := strconv.Atoi(respJSON["count_sum"].(string))
134
+			return count, respJSON["report"].([]interface{}), nil
135
+		} else {
136
+			return 1, nil, nil
137
+		}
138
+	}
139
+}
140
+
141
+// 用云之讯单发模板短信
142
+// 返回值分别是 是否成功,code,msg,error
143
+func singleSendMessageUseUCPaas(templateID int, params []string, mobile string) (bool, string, string, error) {
144
+	sms_api := beego.AppConfig.String("sms_baseUrl") + "sendsms"
145
+	appID, sid, token := getSMSConfig()
146
+	requestParams := make(map[string]interface{})
147
+	requestParams["appid"] = appID
148
+	requestParams["sid"] = sid
149
+	requestParams["token"] = token
150
+	requestParams["templateid"] = strconv.Itoa(templateID)
151
+	requestParams["mobile"] = mobile
152
+	if params != nil && len(params) != 0 {
153
+		paramStr := strings.Join(params, ",")
154
+		requestParams["param"] = paramStr
155
+	}
156
+
157
+	paramsBytes, _ := json.Marshal(requestParams)
158
+	resp, requestErr := http.Post(sms_api, "application/json", bytes.NewBuffer(paramsBytes))
159
+
160
+	if requestErr != nil {
161
+		utils.ErrorLog("短信平台模板群发接口调用失败: %v", requestErr)
162
+		return false, "", "", requestErr
163
+	}
164
+	defer resp.Body.Close()
165
+	body, ioErr := ioutil.ReadAll(resp.Body)
166
+	if ioErr != nil {
167
+		utils.ErrorLog("短信平台模板群发接口返回数据读取失败: %v", ioErr)
168
+		return false, "", "", ioErr
169
+	}
170
+	var respJSON map[string]interface{}
171
+	utils.InfoLog(string(body))
172
+	if err := json.Unmarshal([]byte(string(body)), &respJSON); err != nil {
173
+		utils.ErrorLog("短信平台模板群发接口返回数据解析JSON失败: %v", err)
174
+		return false, "", "", err
175
+	}
176
+	if respJSON["code"].(string) != "000000" {
177
+		msg := respJSON["msg"].(string)
178
+		utils.ErrorLog("短信平台模板群发接口请求失败: %v", msg)
179
+		return false, "", "", &SMSServiceError{"短信平台模板群发接口请求失败"}
180
+
181
+	} else {
182
+		utils.SuccessLog("短信发送成功")
183
+		return true, respJSON["code"].(string), respJSON["msg"].(string), nil
184
+	}
185
+}

+ 29 - 0
service/subscibe_service.go View File

@@ -0,0 +1,29 @@
1
+package service
2
+
3
+import (
4
+	"errors"
5
+	"time"
6
+	"wsc-go/models"
7
+)
8
+
9
+func GetOrgSubscibeState(subscibe *models.ServeSubscibe) (err error) {
10
+	if subscibe == nil {
11
+		err = errors.New("没有订阅信息")
12
+		return
13
+	}
14
+
15
+	//免费试用版2,永久免费版9 不过期
16
+	if subscibe.State == 9 || subscibe.State == 2 {
17
+		return
18
+	}
19
+
20
+	timeNow := time.Now().Unix()
21
+	if timeNow < subscibe.PeriodStart || timeNow > subscibe.PeriodEnd {
22
+		subscibe.State = 3
23
+	}
24
+	if subscibe.State != 1 && subscibe.State != 8 {
25
+		subscibe.State = 3
26
+	}
27
+	return
28
+
29
+}

+ 381 - 0
service/verify_login_token_service.go View File

@@ -0,0 +1,381 @@
1
+package service
2
+
3
+import (
4
+	"encoding/json"
5
+	"io/ioutil"
6
+	"net/http"
7
+	"net/url"
8
+	"strconv"
9
+	"time"
10
+
11
+	"wsc-go/models"
12
+	"wsc-go/utils"
13
+
14
+	"github.com/astaxie/beego"
15
+)
16
+
17
+type AdminUserInfo struct {
18
+	AdminUser    *models.AdminUser                    `json:"user"`
19
+	CurrentOrgId int64                                `json:"current_org_id"`
20
+	CurrentAppId int64                                `json:"current_app_id"`
21
+	OrgIds       []int64                              `json:"org_ids"`
22
+	Orgs         map[int64]*models.Org                `json:"orgs"`
23
+	OrgAppIds    map[int64][]int64                    `json:"org_app_ids"`
24
+	OrgApps      map[int64](map[int64]*models.OrgApp) `json:"org_apps"`
25
+	App2OrgIds   map[int64]int64                      `json:"app_to_org_ids"`
26
+	AppRoles     map[int64]*models.App_Role           `json:"app_roles"`
27
+	AppPurviews  map[int64][]*models.Purview          `json:"app_purviews"`
28
+	AppUrlfors   map[int64][]string                   `json:"app_urlfors"`
29
+	Subscibes    map[int64]*models.ServeSubscibe      `json:"org_subscibes"`
30
+}
31
+
32
+type verifyTokenError struct {
33
+	Msg string
34
+}
35
+
36
+func (e *verifyTokenError) Error() string {
37
+	return e.Msg
38
+}
39
+
40
+// 验证 token 成功后返回的管理员用户的所有信息,包括:基本用户信息,所属的所有机构,机构下的所有应用,应用的用户权限
41
+// map 的数据格式为
42
+/*
43
+"admin_user": { AdminUser's json },
44
+current_org_id: 1,
45
+current_app_id: 11,
46
+"org_ids": [1, 2, 3],
47
+"orgs": { (org_id: Org_Obj)
48
+	1: { Org's json },
49
+	2: { Org's json },
50
+},
51
+"org_app_ids": { (org_id: org_app_ids)
52
+	1: [11, 12, 13],
53
+	2: [21, 22, 23],
54
+},
55
+"org_apps": { (org_id: {app_id: OrgApp_Obj})
56
+	1: {
57
+		11: { OrgApp's json },
58
+		12: { OrgApp's json },
59
+	},
60
+	2: {
61
+		21: { OrgApp's json },
62
+		22: { OrgApp's json },
63
+	},
64
+},
65
+"app_to_org_ids": { (app_id: org_id)
66
+	11: 1,
67
+	12: 1,
68
+	21: 2,
69
+	22: 2,
70
+},
71
+"app_roles": { (app_id: App_Role Obj)
72
+	11: {App_Role's json},
73
+	12: {App_Role's json},
74
+	21: {App_Role's json},
75
+},
76
+"purviews": { (app_id: [processed Purviews' json])
77
+	11: [
78
+		{Purview's json .childs[
79
+			{Purview's json},
80
+			{Purview's json},
81
+		]},
82
+		{Purview's json},
83
+	],
84
+	12: [
85
+		{Purview's json},
86
+		{Purview's json},
87
+	],
88
+},
89
+"purview_urlfors": { (app_id: [url_for])
90
+	11: [
91
+		"Controller1.Action1",
92
+		"Controller1.Action2",
93
+		"Controller2.Action1",
94
+		"Controller2.Action2",
95
+	],
96
+}
97
+应当注意的是,屈服于 Golang 令人恶心的类型机制,这里将所有数值型的 key 或 value 全部转成了 string
98
+*/
99
+// 解析用户信息,并返回
100
+func VerifyToken(token string, ip string, sessionID string) (*AdminUserInfo, error, int) {
101
+	// if len(sessionID) == 0 {
102
+	// 	return nil, &verifyTokenError{"sessionID 为空"}
103
+	// }
104
+	ssoDomain := beego.AppConfig.String("sso_domain")
105
+	api := ssoDomain + "/verifytoken"
106
+	values := make(url.Values)
107
+	values.Set("token", token)
108
+	values.Set("app_type", "5")
109
+	values.Set("ip", ip)
110
+	values.Set("session_id", sessionID)
111
+	resp, requestErr := http.PostForm(api, values)
112
+
113
+	if requestErr != nil {
114
+		utils.ErrorLog("请求验证 sso token 接口失败: %v", requestErr)
115
+		return nil, requestErr, 0
116
+	}
117
+	defer resp.Body.Close()
118
+	body, ioErr := ioutil.ReadAll(resp.Body)
119
+	if ioErr != nil {
120
+		utils.ErrorLog("验证 sso token 接口返回数据读取失败: %v", ioErr)
121
+		return nil, ioErr, 0
122
+	}
123
+	var respJSON map[string]interface{}
124
+	utils.InfoLog(string(body))
125
+	if err := json.Unmarshal([]byte(string(body)), &respJSON); err != nil {
126
+		utils.ErrorLog("验证 sso token 接口返回数据解析JSON失败: %v", err)
127
+		return nil, err, 0
128
+	}
129
+
130
+	if respJSON["state"].(float64) != 1 {
131
+		msg := respJSON["msg"].(string)
132
+		utils.ErrorLog("验证 sso token 接口请求失败: %v", msg)
133
+		return nil, &verifyTokenError{"验证 sso token 接口请求失败"}, int(respJSON["code"].(float64))
134
+	} else {
135
+		utils.SuccessLog("验证 sso token 成功")
136
+		return processAdminUserInfo(respJSON["data"].(map[string]interface{})), nil, 0
137
+	}
138
+}
139
+
140
+func processAdminUserInfo(data map[string]interface{}) *AdminUserInfo {
141
+	adminUser := processAdminUser(data)
142
+	currentOrgId, currentAppId := processCurrentOrgIDAndAppID(data)
143
+	orgIds := processOrgIds(data)
144
+	orgs := processOrgs(data)
145
+	orgAppIds := processOrgAppIds(data)
146
+	orgApps := processOrgApps(data)
147
+	app2OrgIds := processApp2OrgIds(data)
148
+	appRoles := processAppRoles(data)
149
+	appPurviews := processPurviews(data)
150
+	appUrlfors := processPurviewUrlfors(data)
151
+	orgSubscibes := processOrgSubscibes(data)
152
+	sessionAdminUserInfo := &AdminUserInfo{
153
+		AdminUser:    adminUser,
154
+		CurrentOrgId: currentOrgId,
155
+		CurrentAppId: currentAppId,
156
+		OrgIds:       orgIds,
157
+		Orgs:         orgs,
158
+		OrgAppIds:    orgAppIds,
159
+		OrgApps:      orgApps,
160
+		App2OrgIds:   app2OrgIds,
161
+		AppRoles:     appRoles,
162
+		AppPurviews:  appPurviews,
163
+		AppUrlfors:   appUrlfors,
164
+		Subscibes:    orgSubscibes,
165
+	}
166
+	return sessionAdminUserInfo
167
+}
168
+
169
+// "admin_user": { AdminUser's json },
170
+func processAdminUser(data map[string]interface{}) *models.AdminUser {
171
+	userJSONStr := data["admin_user"].(string)
172
+	var adminUser models.AdminUser
173
+	if err := json.Unmarshal([]byte(userJSONStr), &adminUser); err != nil {
174
+		utils.ErrorLog("解析用户信息失败:%v", err)
175
+		return nil
176
+	} else {
177
+		return &adminUser
178
+	}
179
+}
180
+
181
+// current_org_id: 1,
182
+// current_app_id: 11,
183
+func processCurrentOrgIDAndAppID(data map[string]interface{}) (int64, int64) {
184
+	orgIDStr := data["current_org_id"].(string)
185
+	appIDStr := data["current_app_id"].(string)
186
+	orgID, _ := strconv.Atoi(orgIDStr)
187
+	appID, _ := strconv.Atoi(appIDStr)
188
+	return int64(orgID), int64(appID)
189
+}
190
+
191
+// "org_ids": [1, 2, 3],
192
+func processOrgIds(data map[string]interface{}) []int64 {
193
+	orgIdStrs := data["org_ids"].([]interface{})
194
+	orgIds := make([]int64, 0, len(orgIdStrs))
195
+	for _, idstr := range orgIdStrs {
196
+		id, _ := strconv.Atoi(idstr.(string))
197
+		orgIds = append(orgIds, int64(id))
198
+	}
199
+	return orgIds
200
+}
201
+
202
+// "orgs": { (org_id: Org_Obj)
203
+// 	1: { Org's json },
204
+// 	2: { Org's json },
205
+// },
206
+func processOrgs(data map[string]interface{}) map[int64]*models.Org {
207
+	orgJSONs := data["orgs"].(map[string]interface{})
208
+	orgs := make(map[int64]*models.Org)
209
+	for orgIdStr, orgJSON := range orgJSONs {
210
+		orgId, _ := strconv.Atoi(orgIdStr)
211
+		var org models.Org
212
+		json.Unmarshal([]byte(orgJSON.(string)), &org)
213
+		orgs[int64(orgId)] = &org
214
+	}
215
+	return orgs
216
+}
217
+
218
+// "org_app_ids": { (org_id: org_app_ids)
219
+// 	1: [11, 12, 13],
220
+// 	2: [21, 22, 23],
221
+// },
222
+func processOrgAppIds(data map[string]interface{}) map[int64][]int64 {
223
+	orgAppIdStrs := data["org_app_ids"].(map[string]interface{})
224
+	orgAppIds := make(map[int64][]int64)
225
+	for orgIdStr, appIdStrs := range orgAppIdStrs {
226
+		orgId, _ := strconv.Atoi(orgIdStr)
227
+		appIds := make([]int64, 0, len(appIdStrs.([]interface{})))
228
+		for _, appIdStr := range appIdStrs.([]interface{}) {
229
+			appId, _ := strconv.Atoi(appIdStr.(string))
230
+			appIds = append(appIds, int64(appId))
231
+		}
232
+		orgAppIds[int64(orgId)] = appIds
233
+	}
234
+	return orgAppIds
235
+}
236
+
237
+// "org_apps": { (org_id: {app_id: OrgApp_Obj})
238
+// 	1: {
239
+// 		11: { OrgApp's json },
240
+// 		12: { OrgApp's json },
241
+// 	},
242
+// 	2: {
243
+// 		21: { OrgApp's json },
244
+// 		22: { OrgApp's json },
245
+// 	},
246
+// },
247
+func processOrgApps(data map[string]interface{}) map[int64]map[int64]*models.OrgApp {
248
+	orgAppJSONs := data["org_apps"].(map[string]interface{})
249
+	orgApps := make(map[int64]map[int64]*models.OrgApp)
250
+	for orgIdStr, appJSONStrMap := range orgAppJSONs {
251
+		orgId, _ := strconv.Atoi(orgIdStr)
252
+
253
+		apps := make(map[int64]*models.OrgApp)
254
+		for appIdStr, appJSONStr := range appJSONStrMap.(map[string]interface{}) {
255
+			appId, _ := strconv.Atoi(appIdStr)
256
+
257
+			var app models.OrgApp
258
+			json.Unmarshal([]byte(appJSONStr.(string)), &app)
259
+			apps[int64(appId)] = &app
260
+		}
261
+
262
+		orgApps[int64(orgId)] = apps
263
+	}
264
+	return orgApps
265
+}
266
+
267
+// "app_to_org_ids": { (app_id: org_id)
268
+// 	11: 1,
269
+// 	12: 1,
270
+// 	21: 2,
271
+// 	22: 2,
272
+// },
273
+func processApp2OrgIds(data map[string]interface{}) map[int64]int64 {
274
+	app2OrgIdStrs := data["app_to_org_ids"].(map[string]interface{})
275
+	app2OrgIds := make(map[int64]int64)
276
+	for appIdStr, orgIdStr := range app2OrgIdStrs {
277
+		orgId, _ := strconv.Atoi(orgIdStr.(string))
278
+		appId, _ := strconv.Atoi(appIdStr)
279
+		app2OrgIds[int64(appId)] = int64(orgId)
280
+	}
281
+	return app2OrgIds
282
+}
283
+
284
+// "app_roles": { (app_id: App_Role Obj)
285
+// 	11: {App_Role's json},
286
+// 	12: {App_Role's json},
287
+// 	21: {App_Role's json},
288
+// },
289
+func processAppRoles(data map[string]interface{}) map[int64]*models.App_Role {
290
+	appRoleJSONs := data["app_roles"].(map[string]interface{})
291
+	appRoles := make(map[int64]*models.App_Role)
292
+	for appIDStr, appRoleJSON := range appRoleJSONs {
293
+		appID, _ := strconv.Atoi(appIDStr)
294
+		var appRole models.App_Role
295
+		json.Unmarshal([]byte(appRoleJSON.(string)), &appRole)
296
+		appRoles[int64(appID)] = &appRole
297
+	}
298
+	return appRoles
299
+}
300
+
301
+// "purviews": { (app_id: [processed Purviews' json])
302
+// 	11: [
303
+// 		{Purview's json .childs[
304
+// 			{Purview's json},
305
+// 			{Purview's json},
306
+// 		]},
307
+// 		{Purview's json},
308
+// 	],
309
+// 	12: [
310
+// 		{Purview's json},
311
+// 		{Purview's json},
312
+// 	],
313
+// },
314
+func processPurviews(data map[string]interface{}) map[int64][]*models.Purview {
315
+	appPurviewJSONsStrs := data["purviews"].(map[string]interface{})
316
+	appPurviews := make(map[int64][]*models.Purview)
317
+	for appIdStr, purviewJSONsStr := range appPurviewJSONsStrs {
318
+		appId, _ := strconv.Atoi(appIdStr)
319
+		var purviews []*models.Purview
320
+		json.Unmarshal([]byte(purviewJSONsStr.(string)), &purviews)
321
+		// setLinkForPurviews(purviews)
322
+		appPurviews[int64(appId)] = purviews
323
+	}
324
+	return appPurviews
325
+}
326
+
327
+// func setLinkForPurviews(purviews []*models.Purview) {
328
+// 	for _, purview := range purviews {
329
+// 		if len(purview.Urlfor) == 0 {
330
+// 			purview.Link = ""
331
+// 		} else {
332
+// 			purview.Link = beego.URLFor(purview.Urlfor)
333
+// 		}
334
+// 		if purview.Childs == nil {
335
+// 			purview.Childs = make([]*models.Purview, 0)
336
+// 		} else {
337
+// 			setLinkForPurviews(purview.Childs)
338
+// 		}
339
+// 		// utils.TraceLog("%+v", purview)
340
+// 	}
341
+// }
342
+
343
+// "purview_urlfors": { (app_id: [url_for])
344
+// 	11: [
345
+// 		"Controller1.Action1",
346
+// 		"Controller1.Action2",
347
+// 		"Controller2.Action1",
348
+// 		"Controller2.Action2",
349
+// 	],
350
+// }
351
+func processPurviewUrlfors(data map[string]interface{}) map[int64][]string {
352
+	appUrlforsStrs := data["purview_urlfors"].(map[string]interface{})
353
+	appUrlfors := make(map[int64][]string)
354
+	for appIdStr, urlforsStr := range appUrlforsStrs {
355
+		appId, _ := strconv.Atoi(appIdStr)
356
+		var urlfors []string
357
+		json.Unmarshal([]byte(urlforsStr.(string)), &urlfors)
358
+		appUrlfors[int64(appId)] = urlfors
359
+	}
360
+	return appUrlfors
361
+}
362
+
363
+// "org_subscibes": { (org_id: ServeSubscibe)
364
+//  11: {ServeSubscibe's json}
365
+// },
366
+func processOrgSubscibes(data map[string]interface{}) map[int64]*models.ServeSubscibe {
367
+	subscibeJSONs := data["org_subscibes"].(map[string]interface{})
368
+	subscibes := make(map[int64]*models.ServeSubscibe)
369
+	for orgIDStr, subscibeJSON := range subscibeJSONs {
370
+		orgID, _ := strconv.Atoi(orgIDStr)
371
+		var subscibe models.ServeSubscibe
372
+		json.Unmarshal([]byte(subscibeJSON.(string)), &subscibe)
373
+		subscibes[int64(orgID)] = &subscibe
374
+	}
375
+	return subscibes
376
+}
377
+
378
+func ModifyPassword(adminID int64, password string) error {
379
+	err := writeUserDb.Model(&models.AdminUser{}).Where("id = ? AND status = 1", adminID).Updates(map[string]interface{}{"password": password, "mtime": time.Now().Unix()}).Error
380
+	return err
381
+}

+ 13 - 0
utils/ip_helper.go View File

@@ -0,0 +1,13 @@
1
+package utils
2
+
3
+import (
4
+	"net/http"
5
+)
6
+
7
+func GetIP(r *http.Request) string {
8
+	ip := r.Header.Get("X-Forwarded-For")
9
+	if ip == "" {
10
+		ip = r.RemoteAddr
11
+	}
12
+	return ip
13
+}

+ 66 - 0
utils/log.go View File

@@ -0,0 +1,66 @@
1
+package utils
2
+
3
+import (
4
+	"fmt"
5
+	"time"
6
+)
7
+
8
+const (
9
+	color_red = uint8(iota + 91)
10
+	color_green
11
+	color_yellow
12
+	color_blue
13
+	color_magenta //洋红
14
+
15
+	// info = "[INFO]"
16
+	// trac = "[TRAC]"
17
+	// erro = "[ERRO]"
18
+	// warn = "[WARN]"
19
+	// succ = "[SUCC]"
20
+)
21
+
22
+// 根据 https://github.com/liyu4/chill 修改的
23
+// see complete color rules in document in https://en.wikipedia.org/wiki/ANSI_escape_code#cite_note-ecma48-13
24
+func TraceLog(format string, a ...interface{}) {
25
+	fmt.Println(formatLog(yellow(fmt.Sprintf(format, a...))))
26
+}
27
+
28
+func InfoLog(format string, a ...interface{}) {
29
+	fmt.Println(formatLog(blue(fmt.Sprintf(format, a...))))
30
+}
31
+
32
+func SuccessLog(format string, a ...interface{}) {
33
+	fmt.Println(formatLog(green(fmt.Sprintf(format, a...))))
34
+}
35
+
36
+func WarningLog(format string, a ...interface{}) {
37
+	fmt.Println(formatLog(magenta(fmt.Sprintf(format, a...))))
38
+}
39
+
40
+func ErrorLog(format string, a ...interface{}) {
41
+	fmt.Println(formatLog(red(fmt.Sprintf(format, a...))))
42
+}
43
+
44
+func red(s string) string {
45
+	return fmt.Sprintf("\x1b[%dm%s\x1b[0m", color_red, s)
46
+}
47
+
48
+func green(s string) string {
49
+	return fmt.Sprintf("\x1b[%dm%s\x1b[0m", color_green, s)
50
+}
51
+
52
+func yellow(s string) string {
53
+	return fmt.Sprintf("\x1b[%dm%s\x1b[0m", color_yellow, s)
54
+}
55
+
56
+func blue(s string) string {
57
+	return fmt.Sprintf("\x1b[%dm%s\x1b[0m", color_blue, s)
58
+}
59
+
60
+func magenta(s string) string {
61
+	return fmt.Sprintf("\x1b[%dm%s\x1b[0m", color_magenta, s)
62
+}
63
+
64
+func formatLog(prefix string) string {
65
+	return time.Now().Format("[2006/01/02 15:04:05]") + " " + prefix + " "
66
+}

+ 191 - 0
utils/paginator.go View File

@@ -0,0 +1,191 @@
1
+// Copyright 2013 wetalk authors
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+package utils
16
+
17
+import (
18
+	"math"
19
+	"net/http"
20
+	"net/url"
21
+	"strconv"
22
+)
23
+
24
+type Paginator struct {
25
+	Request     *http.Request
26
+	PerPageNums int
27
+	MaxPages    int
28
+
29
+	nums      int64
30
+	pageRange []int
31
+	pageNums  int
32
+	page      int
33
+}
34
+
35
+func (p *Paginator) PageNums() int {
36
+	if p.pageNums != 0 {
37
+		return p.pageNums
38
+	}
39
+	pageNums := math.Ceil(float64(p.nums) / float64(p.PerPageNums))
40
+	if p.MaxPages > 0 {
41
+		pageNums = math.Min(pageNums, float64(p.MaxPages))
42
+	}
43
+	p.pageNums = int(pageNums)
44
+	return p.pageNums
45
+}
46
+
47
+func (p *Paginator) Nums() int64 {
48
+	return p.nums
49
+}
50
+
51
+func (p *Paginator) SetNums(nums int64) {
52
+	p.nums = nums
53
+}
54
+
55
+func (p *Paginator) Page() int {
56
+	if p.page != 0 {
57
+		return p.page
58
+	}
59
+	if p.Request.Form == nil {
60
+		p.Request.ParseForm()
61
+	}
62
+	p.page, _ = strconv.Atoi(p.Request.Form.Get("page"))
63
+	if p.page > p.PageNums() {
64
+		p.page = p.PageNums()
65
+	}
66
+	if p.page <= 0 {
67
+		p.page = 1
68
+	}
69
+	return p.page
70
+}
71
+
72
+func (p *Paginator) Pages() []int {
73
+	if p.pageRange == nil && p.nums > 0 {
74
+		var pages []int
75
+		pageNums := p.PageNums()
76
+		page := p.Page()
77
+		switch {
78
+		case page >= pageNums-4 && pageNums > 9:
79
+			start := pageNums - 9 + 1
80
+			pages = make([]int, 9)
81
+			for i, _ := range pages {
82
+				pages[i] = start + i
83
+			}
84
+		case page >= 5 && pageNums > 9:
85
+			start := page - 5 + 1
86
+			pages = make([]int, int(math.Min(9, float64(page+4+1))))
87
+			for i, _ := range pages {
88
+				pages[i] = start + i
89
+			}
90
+		default:
91
+			pages = make([]int, int(math.Min(9, float64(pageNums))))
92
+			for i, _ := range pages {
93
+				pages[i] = i + 1
94
+			}
95
+		}
96
+		p.pageRange = pages
97
+	}
98
+	return p.pageRange
99
+}
100
+
101
+func (p *Paginator) PageLink(page int) string {
102
+	link, _ := url.ParseRequestURI(p.Request.RequestURI)
103
+	values := link.Query()
104
+	if page == 1 {
105
+		values.Del("page")
106
+	} else {
107
+		values.Set("page", strconv.Itoa(page))
108
+	}
109
+	link.RawQuery = values.Encode()
110
+	return link.String()
111
+}
112
+
113
+func (p *Paginator) PageParams() url.Values {
114
+	link, _ := url.ParseRequestURI(p.Request.RequestURI)
115
+	values := link.Query()
116
+	values.Del("page")
117
+	return values
118
+}
119
+
120
+func (p *Paginator) BasePageLink() string {
121
+	link, _ := url.ParseRequestURI(p.Request.RequestURI)
122
+	values := link.Query()
123
+	values.Del("page")
124
+	link.RawQuery = values.Encode()
125
+	return link.String()
126
+}
127
+
128
+func (p *Paginator) PageLinkPrev() (link string) {
129
+	if p.HasPrev() {
130
+		link = p.PageLink(p.Page() - 1)
131
+	}
132
+	return
133
+}
134
+
135
+func (p *Paginator) PageLinkNext() (link string) {
136
+	if p.HasNext() {
137
+		link = p.PageLink(p.Page() + 1)
138
+	}
139
+	return
140
+}
141
+
142
+func (p *Paginator) PageLinkFirst() (link string) {
143
+	return p.PageLink(1)
144
+}
145
+
146
+func (p *Paginator) PageLinkLast() (link string) {
147
+	return p.PageLink(p.PageNums())
148
+}
149
+
150
+func (p *Paginator) HasPrev() bool {
151
+	return p.Page() > 1
152
+}
153
+
154
+func (p *Paginator) HasNext() bool {
155
+	return p.Page() < p.PageNums()
156
+}
157
+
158
+func (p *Paginator) IsActive(page int) bool {
159
+	return p.Page() == page
160
+}
161
+
162
+func (p *Paginator) Offset() int {
163
+	return (p.Page() - 1) * p.PerPageNums
164
+}
165
+
166
+func (p *Paginator) HasPages() bool {
167
+	return p.PageNums() > 1
168
+}
169
+
170
+func (p *Paginator) Total() int {
171
+	return p.PageNums()
172
+}
173
+func (p *Paginator) TotalSubOne() int {
174
+	return p.PageNums() - 1
175
+}
176
+
177
+func NewPaginator(req *http.Request, per int, nums int64) *Paginator {
178
+	p := Paginator{}
179
+	p.Request = req
180
+	if per <= 0 {
181
+		per = 10
182
+	}
183
+	p.PerPageNums = per
184
+	p.SetNums(nums)
185
+	return &p
186
+}
187
+
188
+func FakePaginator(currentPage int, per int, nums int64) *Paginator {
189
+	fakeReq, _ := http.NewRequest("GET", "/?page="+strconv.Itoa(currentPage), nil)
190
+	return NewPaginator(fakeReq, per, nums)
191
+}

+ 75 - 0
utils/regex_helper.go View File

@@ -0,0 +1,75 @@
1
+package utils
2
+
3
+import (
4
+	"fmt"
5
+	"regexp"
6
+)
7
+
8
+// 正整数正则
9
+func PositiveIntegerRegexp() *regexp.Regexp {
10
+	reg, _ := regexp.Compile("^[1-9][0-9]*$")
11
+	return reg
12
+}
13
+
14
+// 手机号正则 不那么严谨的
15
+func CellPhoneRegexp() *regexp.Regexp {
16
+	reg, _ := regexp.Compile("^1\\d{10}$")
17
+	return reg
18
+}
19
+
20
+// 固话正则
21
+func TelPhoneRegexp() *regexp.Regexp {
22
+	// reg, _ := regexp.Compile("^0\\d{2,3}-?\\d{7,8}$")
23
+	reg, _ := regexp.Compile("^0\\d{2,3}-?\\d{7,8}$")
24
+	return reg
25
+}
26
+
27
+// 手机号或固话正则
28
+func PhoneRegexp() *regexp.Regexp {
29
+	reg, _ := regexp.Compile("^(0\\d{2,3}-?\\d{7,8}$)|(1\\d{10}$)")
30
+	return reg
31
+}
32
+
33
+// tests
34
+func PositiveIntegerRegexpTest() {
35
+	reg := PositiveIntegerRegexp()
36
+	fmt.Println("12 是否匹配:", reg.MatchString("12"))
37
+	fmt.Println("1 是否匹配:", reg.MatchString("1"))
38
+	fmt.Println("980030 是否匹配:", reg.MatchString("980030"))
39
+	fmt.Println("01 是否匹配:", reg.MatchString("01"))
40
+	fmt.Println("asd1asd 是否匹配:", reg.MatchString("asd1asd"))
41
+	fmt.Println("a12 是否匹配:", reg.MatchString("a12"))
42
+	fmt.Println("12a 是否匹配:", reg.MatchString("12a"))
43
+	fmt.Println("-12 是否匹配:", reg.MatchString("-12"))
44
+	fmt.Println("12.1 是否匹配:", reg.MatchString("12.1"))
45
+	fmt.Println("14j2a 是否匹配:", reg.MatchString("14j2a"))
46
+}
47
+
48
+func CellPhoneRegexpTest() {
49
+	reg := CellPhoneRegexp()
50
+	fmt.Println("13632250447 是否匹配:", reg.MatchString("13632250447"))
51
+	fmt.Println("12000000000 是否匹配:", reg.MatchString("12000000000"))
52
+	fmt.Println("30001212325 是否匹配:", reg.MatchString("30001212325"))
53
+	fmt.Println("1233123 是否匹配:", reg.MatchString("1233123"))
54
+	fmt.Println("123312312344 是否匹配:", reg.MatchString("123312312344"))
55
+	fmt.Println("13345678a12 是否匹配:", reg.MatchString("13345678a12"))
56
+	fmt.Println("a13345678a1 是否匹配:", reg.MatchString("a13345678a1"))
57
+	fmt.Println("1334a678a12 是否匹配:", reg.MatchString("1334a678a12"))
58
+	fmt.Println("1345678a12a 是否匹配:", reg.MatchString("1345678a12a"))
59
+	fmt.Println("aqwertyuioo 是否匹配:", reg.MatchString("aqwertyuioo"))
60
+}
61
+
62
+func TelPhoneRegexpTest() {
63
+	reg := TelPhoneRegexp()
64
+	fmt.Println("020-39006917 是否匹配:", reg.MatchString("020-39006917"))
65
+	fmt.Println("02039006917 是否匹配:", reg.MatchString("02039006917"))
66
+	fmt.Println("0754-5916612 是否匹配:", reg.MatchString("0754-5916612"))
67
+	fmt.Println("07545916612 是否匹配:", reg.MatchString("07545916612"))
68
+	fmt.Println("123-39006917 是否匹配:", reg.MatchString("123-39006917"))
69
+	fmt.Println("1754-5916612 是否匹配:", reg.MatchString("1754-5916612"))
70
+	fmt.Println("0a0-39006917 是否匹配:", reg.MatchString("0a0-39006917"))
71
+	fmt.Println("0a039006917 是否匹配:", reg.MatchString("0a039006917"))
72
+	fmt.Println("010-39s06917 是否匹配:", reg.MatchString("010-39s06917"))
73
+	fmt.Println("020-390069171 是否匹配:", reg.MatchString("020-390069171"))
74
+	fmt.Println("020-3900691 是否匹配:", reg.MatchString("020-3900691"))
75
+}

+ 115 - 0
utils/stringtool.go View File

@@ -0,0 +1,115 @@
1
+package utils
2
+
3
+import (
4
+	"bytes"
5
+	"crypto/aes"
6
+	"crypto/cipher"
7
+	"crypto/md5"
8
+	"encoding/base64"
9
+	"fmt"
10
+	"math/rand"
11
+	"strconv"
12
+	"strings"
13
+	"time"
14
+
15
+	"github.com/astaxie/beego"
16
+)
17
+
18
+// 将字符串加密成 md5
19
+func String2md5(str string) string {
20
+	data := []byte(str)
21
+	has := md5.Sum(data)
22
+	return fmt.Sprintf("%x", has) //将[]byte转成16进制
23
+}
24
+
25
+// RandomString 在数字、大写字母、小写字母范围内生成num位的随机字符串
26
+func RandomString(length int) string {
27
+	// 48 ~ 57 数字
28
+	// 65 ~ 90 A ~ Z
29
+	// 97 ~ 122 a ~ z
30
+	// 一共62个字符,在0~61进行随机,小于10时,在数字范围随机,
31
+	// 小于36在大写范围内随机,其他在小写范围随机
32
+	rand.Seed(time.Now().UnixNano())
33
+	result := make([]string, 0, length)
34
+	for i := 0; i < length; i++ {
35
+		t := rand.Intn(62)
36
+		if t < 10 {
37
+			result = append(result, strconv.Itoa(rand.Intn(10)))
38
+		} else if t < 36 {
39
+			result = append(result, string(rand.Intn(26)+65))
40
+		} else {
41
+			result = append(result, string(rand.Intn(26)+97))
42
+		}
43
+	}
44
+	return strings.Join(result, "")
45
+}
46
+
47
+func RandomNumberString(length int) string {
48
+	var str string
49
+	for i := 0; i < length; i++ {
50
+		rand.Seed(time.Now().UnixNano())
51
+		str += strconv.Itoa(rand.Intn(10))
52
+	}
53
+	return str
54
+}
55
+
56
+// AES加密
57
+func AESEncrypt(origin string) string {
58
+	aes_key := beego.AppConfig.String("aes_key")
59
+	fmt.Println(aes_key)
60
+	xpass, _ := _aesEncrypt([]byte(origin), []byte(aes_key))
61
+	fmt.Println(_aesEncrypt([]byte(origin), []byte(aes_key)))
62
+	fmt.Println(xpass)
63
+	pass64 := base64.StdEncoding.EncodeToString(xpass)
64
+	fmt.Println(pass64)
65
+	return pass64
66
+}
67
+
68
+func AESDecrypt(crypted []byte) string {
69
+	aes_key := beego.AppConfig.String("aes_key")
70
+	origData, err := _aesDecrypt(crypted, []byte(aes_key))
71
+	if err != nil {
72
+		return ""
73
+	}
74
+	return string(origData)
75
+}
76
+
77
+func _PKCS5Padding(ciphertext []byte, blockSize int) []byte {
78
+	padding := blockSize - len(ciphertext)%blockSize
79
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
80
+	return append(ciphertext, padtext...)
81
+}
82
+
83
+func _PKCS5UnPadding(origData []byte) []byte {
84
+	length := len(origData)
85
+	unpadding := int(origData[length-1])
86
+	return origData[:(length - unpadding)]
87
+}
88
+
89
+func _aesEncrypt(origData, key []byte) ([]byte, error) {
90
+	block, err := aes.NewCipher(key)
91
+	if err != nil {
92
+		return nil, err
93
+	}
94
+
95
+	blockSize := block.BlockSize()
96
+	origData = _PKCS5Padding(origData, blockSize)
97
+	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
98
+	crypted := make([]byte, len(origData))
99
+	blockMode.CryptBlocks(crypted, origData)
100
+	return crypted, nil
101
+}
102
+
103
+func _aesDecrypt(crypted, key []byte) ([]byte, error) {
104
+	block, err := aes.NewCipher(key)
105
+	if err != nil {
106
+		return nil, err
107
+	}
108
+
109
+	blockSize := block.BlockSize()
110
+	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
111
+	origData := make([]byte, len(crypted))
112
+	blockMode.CryptBlocks(origData, crypted)
113
+	origData = _PKCS5UnPadding(origData)
114
+	return origData, nil
115
+}

+ 27 - 0
utils/time_helper.go View File

@@ -0,0 +1,27 @@
1
+package utils
2
+
3
+import (
4
+	"time"
5
+)
6
+
7
+// day 当天凌晨0点
8
+func ZeroHourTimeOfDay(day time.Time) time.Time {
9
+	dayStr := day.Format("2006-01-02")
10
+	zeroHourTime, _ := ParseTimeStringToTime("2006-01-02", dayStr)
11
+	return *zeroHourTime
12
+}
13
+
14
+// day 当月一号凌晨0点
15
+func BeginningOfMonth(day time.Time) time.Time {
16
+	dayStr := day.Format("2006-01")
17
+	monthTime, _ := ParseTimeStringToTime("2006-01", dayStr)
18
+	return *monthTime
19
+}
20
+
21
+// 指定年月的月份的月初凌晨0点和月末23点59分59秒
22
+func MonthBeginningToEnd(year int, month int) (time.Time, time.Time) {
23
+	beginningOfMonth := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Local)
24
+	beginningOfNextMonth := beginningOfMonth.AddDate(0, 1, 0)
25
+	endOfMonth := beginningOfNextMonth.Add(time.Duration(-1))
26
+	return beginningOfMonth, endOfMonth
27
+}

+ 231 - 0
utils/tools.go View File

@@ -0,0 +1,231 @@
1
+package utils
2
+
3
+import (
4
+	"crypto/sha1"
5
+	"encoding/base64"
6
+	"errors"
7
+	"fmt"
8
+	"io"
9
+	"math/rand"
10
+	"regexp"
11
+	"sort"
12
+	"strconv"
13
+	"strings"
14
+	"time"
15
+
16
+	"github.com/astaxie/beego"
17
+)
18
+
19
+func TimeSub(t1, t2 time.Time) int {
20
+	t1 = time.Date(t1.Year(), t1.Month(), t1.Day(), 0, 0, 0, 0, time.Local)
21
+	t2 = time.Date(t2.Year(), t2.Month(), t2.Day(), 0, 0, 0, 0, time.Local)
22
+
23
+	return int(t1.Sub(t2).Hours() / 24)
24
+}
25
+
26
+func MarkBackUrl(backUrl, defaultUrl string) string {
27
+	if len(backUrl) == 0 {
28
+		backUrl = defaultUrl
29
+	} else {
30
+		backURLByte, err := base64.URLEncoding.DecodeString(backUrl)
31
+		if err != nil {
32
+			backUrl = backUrl
33
+		} else {
34
+			backUrl = string(backURLByte)
35
+		}
36
+	}
37
+	return backUrl
38
+}
39
+
40
+func CheckMobile(mobile string) (match bool) {
41
+
42
+	//过滤手机
43
+	match, _ = regexp.MatchString("^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$", mobile)
44
+	return
45
+}
46
+
47
+func RandCode(min, max int64) string {
48
+	if min >= max || min == 0 || max == 0 {
49
+		return strconv.FormatInt(max, 10)
50
+	}
51
+	rand.Seed(time.Now().UnixNano())
52
+	randNum := rand.Int63n(max-min) + min
53
+	return strconv.FormatInt(randNum, 10)
54
+}
55
+
56
+func TimeAgo(timeUnix int64) string {
57
+	timeUnixS := time.Unix(timeUnix, 0)
58
+	timeNow := time.Now()
59
+	timeSub := timeNow.Sub(timeUnixS)
60
+
61
+	if timeSub < time.Minute*1 {
62
+		return "刚刚"
63
+	} else if timeSub < time.Hour*1 {
64
+		return strconv.Itoa(int(timeSub.Minutes())) + "分钟前"
65
+	} else if timeSub < time.Hour*24 {
66
+		return strconv.Itoa(int(timeSub.Hours())) + "小时前"
67
+	} else if timeSub < time.Hour*24*7 {
68
+		return strconv.Itoa(int(timeSub.Hours()/24)) + "天前"
69
+	} else {
70
+		return timeUnixS.Format("2006-01-02 15:04")
71
+	}
72
+	return ""
73
+}
74
+
75
+//Signature sha1签名
76
+func Signature(params ...string) string {
77
+	sort.Strings(params)
78
+	h := sha1.New()
79
+	for _, s := range params {
80
+		io.WriteString(h, s)
81
+	}
82
+	return fmt.Sprintf("%x", h.Sum(nil))
83
+}
84
+
85
+//RandomStr 随机生成字符串
86
+func RandomStr(length int) string {
87
+	str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
88
+	bytes := []byte(str)
89
+	result := []byte{}
90
+	r := rand.New(rand.NewSource(time.Now().UnixNano()))
91
+	for i := 0; i < length; i++ {
92
+		result = append(result, bytes[r.Intn(len(bytes))])
93
+	}
94
+	return string(result)
95
+}
96
+
97
+//GetCurrTs return current timestamps
98
+func GetCurrTs() int64 {
99
+	return time.Now().Unix()
100
+}
101
+
102
+func SetThisRequestURI(uri string) string {
103
+	return fmt.Sprintf("%v%v", beego.AppConfig.String("httpdomain"), uri)
104
+}
105
+
106
+func SetThisBasr64RequestURI(uri string) string {
107
+	backUrl := fmt.Sprintf("%v%v", beego.AppConfig.String("httpdomain"), uri)
108
+	backUrl = base64.URLEncoding.EncodeToString([]byte(backUrl))
109
+
110
+	return backUrl
111
+}
112
+
113
+func TransNum2Str(read int64) (transRead string) {
114
+	if read < 0 {
115
+		transRead = "0"
116
+	} else if read < 10000 {
117
+		transRead = fmt.Sprintf("%v", read)
118
+	} else {
119
+		var c float64 = 10000
120
+		var rc float64 = float64(read)
121
+		transRead = fmt.Sprintf("%.2f万", rc/c)
122
+	}
123
+
124
+	return
125
+}
126
+
127
+func GenMobileToken(mobile string) (token string) {
128
+	st := strings.Split(mobile, "")
129
+
130
+	s := fmt.Sprintf("%s%v%v%v%v%v%v", mobile, st[0], st[1], st[3], st[7], st[6], st[9])
131
+
132
+	h := sha1.New()
133
+	h.Write([]byte(s))
134
+	bs := h.Sum(nil)
135
+
136
+	token = fmt.Sprintf("%x", bs)
137
+
138
+	return
139
+}
140
+
141
+func CheckMobileToken(mobile, token string) bool {
142
+	o := GenMobileToken(mobile)
143
+	if token == o {
144
+		return true
145
+	}
146
+
147
+	return false
148
+}
149
+
150
+type jSapiConfig struct {
151
+	AppID     string `json:"app_id"`
152
+	Timestamp int64  `json:"timestamp"`
153
+	NonceStr  string `json:"nonce_str"`
154
+	Signature string `json:"signature"`
155
+}
156
+
157
+//GetAJTConfig jsapi_ticket config
158
+func GetAJTConfig(jsapiTicket, uri string) (jSapiConfig, error) {
159
+	var config jSapiConfig
160
+	nonceStr := RandomStr(16)
161
+	timestamp := GetCurrTs()
162
+	str := fmt.Sprintf("jsapi_ticket=%s&noncestr=%s&timestamp=%d&url=%s", jsapiTicket, nonceStr, timestamp, uri)
163
+	sigStr := Signature(str)
164
+
165
+	config.AppID = beego.AppConfig.String("wxappId")
166
+	config.NonceStr = nonceStr
167
+	config.Timestamp = timestamp
168
+	config.Signature = sigStr
169
+	return config, nil
170
+}
171
+
172
+func TrimHtml(src string) string {
173
+	//将HTML标签全转换成小写
174
+	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
175
+	src = re.ReplaceAllStringFunc(src, strings.ToLower)
176
+	//去除STYLE
177
+	re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
178
+	src = re.ReplaceAllString(src, "")
179
+	//去除SCRIPT
180
+	re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
181
+	src = re.ReplaceAllString(src, "")
182
+	//去除所有尖括号内的HTML代码,并换成换行符
183
+	re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
184
+	src = re.ReplaceAllString(src, "\n")
185
+	//去除连续的换行符
186
+	re, _ = regexp.Compile("\\s{2,}")
187
+	src = re.ReplaceAllString(src, "\n")
188
+	return strings.TrimSpace(src)
189
+}
190
+
191
+func SubString(str string, begin, length int) string {
192
+	rs := []rune(str)
193
+	lth := len(rs)
194
+	if begin < 0 {
195
+		begin = 0
196
+	}
197
+	if begin >= lth {
198
+		begin = lth
199
+	}
200
+	end := begin + length
201
+
202
+	if end > lth {
203
+		end = lth
204
+	}
205
+	return string(rs[begin:end])
206
+}
207
+
208
+func ParseTimeStringToTime(layout string, timeStr string) (*time.Time, error) {
209
+	if len(layout) == 0 || len(timeStr) == 0 {
210
+		return nil, errors.New("layout 或 日期字符串 为空,无法解析")
211
+	}
212
+	loc, _ := time.LoadLocation("Local")
213
+	date, parseDateErr := time.ParseInLocation(layout, timeStr, loc)
214
+	return &date, parseDateErr
215
+}
216
+
217
+// 获取 date 所在周的周一和周日,以周一0点为一周的开始,周日24点为一周的结束
218
+func GetMondayAndSundayOfWeekDate(date *time.Time) (time.Time, time.Time) {
219
+	if date == nil {
220
+		now := time.Now()
221
+		date = &now
222
+	}
223
+	weekday := int(date.Weekday())
224
+	if weekday == 0 {
225
+		weekday = 7
226
+	}
227
+	loc, _ := time.LoadLocation("Local")
228
+	monday, _ := time.ParseInLocation("2006-01-02 15:04:05", date.AddDate(0, 0, 1-weekday).Format("2006-01-02")+" 00:00:00", loc)
229
+	sunday, _ := time.ParseInLocation("2006-01-02 15:04:05", date.AddDate(0, 0, 7-weekday).Format("2006-01-02")+" 23:59:59", loc)
230
+	return monday, sunday
231
+}