Browse Source

体积小

XMLWAN 2 years ago
parent
commit
e389a83721

+ 119 - 0
conf/app.conf View File

@@ -0,0 +1,119 @@
1
+appname = 小程序
2
+httpport = 9666
3
+runmode = dev
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
+wxtoken = gh_ac6cd0cdde3d
23
+wxoriId = gh_ac6cd0cdde3d
24
+wxappId = wxbb9223f20bc11612
25
+# wxappsecret = a78c793c377268db25dde2eb971a2ebb
26
+# wxEncodingAESKey = 1vRDzqltXYOc9iMqhsQT7AkIRRpUaGl8MZlUcP7x4UK
27
+
28
+sms_appId = dcabb3aa7afd402794046ebbbf652bce
29
+sms_sid = a26cb0ceb3a811ca82143972f4ef38a4
30
+sms_token = ea475ed8d3de6c54c2b3f9d78db76d1e
31
+sms_baseUrl = https://open.ucpaas.com/ol/sms/
32
+ip_max_send_count = 20
33
+moblie_max_send_count = 5
34
+sms_verification_code_templateid = 329532
35
+
36
+
37
+appid = "wx43ad410d9eef426e"
38
+mchid = "1509573721"
39
+key = "e4SHrkiZu0pQEwVoGBapDBTf9N1Q6MxV"
40
+appsecret="61ee2e6268497d5aa9de0b0187c39aea"
41
+
42
+
43
+sz_province = 19
44
+sz_city = 291
45
+
46
+
47
+
48
+[prod]
49
+httpdomain = http://api.szjkhd.com
50
+
51
+
52
+readmysqlhost = shengws1.mysql.rds.aliyuncs.com
53
+readmysqlport = 3306
54
+readmysqluser = syh
55
+readmysqlpass = xhPECP2nFObR8aUK
56
+readmysqlname = sgj_xt
57
+
58
+writemysqlhost = shengws1.mysql.rds.aliyuncs.com
59
+writemysqlport = 3306
60
+writemysqluser = syh
61
+writemysqlpass = xhPECP2nFObR8aUK
62
+writemysqlname = sgj_xt
63
+
64
+
65
+readuserhost = shengws1.mysql.rds.aliyuncs.com
66
+readuserport = 3306
67
+readuseruser = syh
68
+readuserpass = xhPECP2nFObR8aUK
69
+readusername = sgj_users
70
+
71
+writeuserhost = shengws1.mysql.rds.aliyuncs.com
72
+writeuserport = 3306
73
+writeuseruser = syh
74
+writeuserpass = xhPECP2nFObR8aUK
75
+writeusername = sgj_users
76
+
77
+redishost = 349e580b2a524290.redis.rds.aliyuncs.com
78
+redisport = 6379
79
+redispasswrod = TZtBW098WId3i27clkpj3q8dnUaVFP
80
+redisdb = 0
81
+
82
+
83
+
84
+
85
+
86
+[dev]
87
+httpdomain = http://api.szjkhd.com
88
+
89
+
90
+readmysqlhost = rm-wz9rg531npf61q03tro.mysql.rds.aliyuncs.com
91
+readmysqlport = 3306
92
+readmysqluser = root
93
+readmysqlpass = 1Q2W3e4r!@#$
94
+readmysqlname = sgj_xt
95
+
96
+writemysqlhost = rm-wz9rg531npf61q03tro.mysql.rds.aliyuncs.com
97
+writemysqlport = 3306
98
+writemysqluser = root
99
+writemysqlpass = 1Q2W3e4r!@#$
100
+writemysqlname = sgj_xt
101
+
102
+readuserhost = rm-wz9rg531npf61q03tro.mysql.rds.aliyuncs.com
103
+readuserport = 3306
104
+readuseruser = root
105
+readuserpass = 1Q2W3e4r!@#$
106
+readusername = sgj_users
107
+
108
+writeuserhost = rm-wz9rg531npf61q03tro.mysql.rds.aliyuncs.com
109
+writeuserport = 3306
110
+writeuseruser = root
111
+writeuserpass = 1Q2W3e4r!@#$
112
+writeusername = sgj_users
113
+
114
+redishost = 112.74.16.180
115
+redisport = 6379
116
+redispasswrod = syh@#$%123456!
117
+redisdb = 0
118
+
119
+

+ 29 - 0
controllers/admin_api_controllers/admin_api_base_controller.go View File

@@ -0,0 +1,29 @@
1
+package admin_api_controllers
2
+
3
+import (
4
+	"Xcx_New/controllers"
5
+)
6
+
7
+type AdminBaseAPIController struct {
8
+	controllers.BaseAPIController
9
+}
10
+
11
+func (this *AdminBaseAPIController) ErrorLog(format string, a ...interface{}) {
12
+	//beego.Error(fmt.Sprintf("[管理员后台] %v", fmt.Sprintf(format, a...)))
13
+}
14
+
15
+func (this *AdminBaseAPIController) WarnLog(format string, a ...interface{}) {
16
+	//beego.Warn(fmt.Sprintf("[管理员后台] %v", fmt.Sprintf(format, a...)))
17
+}
18
+
19
+func (this *AdminBaseAPIController) InfoLog(format string, a ...interface{}) {
20
+	//beego.Info(fmt.Sprintf("[管理员后台] %v", fmt.Sprintf(format, a...)))
21
+}
22
+
23
+func (this *AdminBaseAPIController) DebugLog(format string, a ...interface{}) {
24
+	//beego.Debug(fmt.Sprintf("[管理员后台] %v", fmt.Sprintf(format, a...)))
25
+}
26
+
27
+func (this *AdminBaseAPIController) TraceLog(format string, a ...interface{}) {
28
+	//beego.Trace(fmt.Sprintf("[管理员后台] %v", fmt.Sprintf(format, a...)))
29
+}

+ 9 - 0
controllers/admin_api_controllers/api_router_register.go View File

@@ -0,0 +1,9 @@
1
+package admin_api_controllers
2
+
3
+import "github.com/astaxie/beego"
4
+
5
+// 管理员后台路由,以 /admin/api 为前缀
6
+func AdminAPIControllersRegisterRouters() {
7
+	beego.Router("/data/upload/api/city", &CityDataUploadAPIController{}, "post:UploadCityData")
8
+
9
+}

+ 11 - 0
controllers/admin_api_controllers/city_data_upload_api_controller.go View File

@@ -0,0 +1,11 @@
1
+package admin_api_controllers
2
+
3
+import "Data_Upload_Api/controllers"
4
+
5
+type CityDataUploadAPIController struct {
6
+	controllers.BaseAPIController
7
+}
8
+
9
+func (this *CityDataUploadAPIController) UploadCityData() {
10
+
11
+}

+ 72 - 0
controllers/base_api_controller.go View File

@@ -0,0 +1,72 @@
1
+package controllers
2
+
3
+import (
4
+	"Data_Upload_Api/enums"
5
+)
6
+
7
+type BaseAPIController struct {
8
+	BaseController
9
+}
10
+
11
+// func (this *BaseAPIController) Prepare() {
12
+// 	this.BaseController.Prepare()
13
+// 	beego.Trace("============================================================")
14
+// 	beego.Trace("session ID: %v", this.Ctx.Input.Cookie("beegosessionID"))
15
+// 	beego.Trace("session : %v", this.GetSession("info"))
16
+// 	this.SetSession("info", time.Now().Format("2006/01/02 15:04:05"))
17
+// 	beego.Trace("============================================================")
18
+// }
19
+
20
+// 输出数据格式化
21
+/*
22
+	success json:
23
+	{
24
+		"state": 1,
25
+		"code": 0,
26
+		"data": json,
27
+	}
28
+
29
+	fail json:
30
+	{
31
+		"state": 0,
32
+		"code": int,
33
+		"msg": string,
34
+	}
35
+*/
36
+func (this *BaseAPIController) ServeSuccessJSON(data map[string]interface{}) {
37
+	this.Data["json"] = enums.MakeSuccessResponseJSON(data)
38
+	this.ServeJSON()
39
+}
40
+
41
+func (this *BaseAPIController) ServeFailJSONWithSGJErrorCode(code int) {
42
+	this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(code)
43
+	this.ServeJSON()
44
+}
45
+
46
+func (this *BaseAPIController) ServeFailJSONWithSGJError(err *enums.SGJError) {
47
+	this.Data["json"] = enums.MakeFailResponseJSONWithSGJError(err)
48
+	this.ServeJSON()
49
+}
50
+
51
+func (this *BaseAPIController) ServeFailJsonSend(code int, msg string) {
52
+	this.Data["json"] = enums.MakeFailResponseJSON(msg, code)
53
+	this.ServeJSON()
54
+}
55
+
56
+type BaseAuthAPIController struct {
57
+	BaseAPIController
58
+}
59
+
60
+func (this *BaseAuthAPIController) Prepare() {
61
+	this.BaseAPIController.Prepare()
62
+
63
+}
64
+
65
+type BaseServeAPIController struct {
66
+	BaseAPIController
67
+}
68
+
69
+func (this *BaseServeAPIController) Prepare() {
70
+	this.BaseAPIController.Prepare()
71
+
72
+}

+ 29 - 0
controllers/base_controller.go View File

@@ -0,0 +1,29 @@
1
+package controllers
2
+
3
+import (
4
+	"github.com/astaxie/beego"
5
+)
6
+
7
+type BaseController struct {
8
+	beego.Controller
9
+}
10
+
11
+func (this *BaseController) ErrorLog(format string, a ...interface{}) {
12
+	//beego.Error(fmt.Sprintf(format, a...))
13
+}
14
+
15
+func (this *BaseController) WarnLog(format string, a ...interface{}) {
16
+	//beego.Warn(fmt.Sprintf(format, a...))
17
+}
18
+
19
+func (this *BaseController) InfoLog(format string, a ...interface{}) {
20
+	//beego.Info(fmt.Sprintf(format, a...))
21
+}
22
+
23
+func (this *BaseController) DebugLog(format string, a ...interface{}) {
24
+	//beego.Debug(fmt.Sprintf(format, a...))
25
+}
26
+
27
+func (this *BaseController) TraceLog(format string, a ...interface{}) {
28
+	//beego.Trace(fmt.Sprintf(format, a...))
29
+}

+ 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
+// }

+ 20 - 0
controllers/mobile_api_controller.go View File

@@ -0,0 +1,20 @@
1
+package controllers
2
+
3
+import (
4
+	"fmt"
5
+	"github.com/astaxie/beego"
6
+)
7
+
8
+type MobileController struct {
9
+	BaseAPIController
10
+}
11
+
12
+func MobileRegisterRouters() {
13
+
14
+	beego.Router("/api/mobile/login", &MobileController{}, "Get:GetMobileLogin")
15
+}
16
+
17
+func (this *MobileController) GetMobileLogin() {
18
+
19
+	fmt.Println("出发多舒服的方式大发阿凡达")
20
+}

+ 325 - 0
controllers/sync.go View File

@@ -0,0 +1,325 @@
1
+package controllers
2
+
3
+import (
4
+	"Data_Upload_Api/enums"
5
+	"Data_Upload_Api/models/sz"
6
+	"Data_Upload_Api/service"
7
+	"Data_Upload_Api/service/city"
8
+	"Data_Upload_Api/utils"
9
+	"fmt"
10
+	_ "fmt"
11
+	"github.com/astaxie/beego"
12
+	_ "github.com/jinzhu/gorm"
13
+	_ "math"
14
+	_ "strconv"
15
+	_ "strings"
16
+	_ "time"
17
+)
18
+
19
+type SyncController struct {
20
+	BaseAPIController
21
+}
22
+
23
+func SyncAPIRegisterRouters() {
24
+	beego.Router("/sync/upload/hqyy", &SyncController{}, "get:SyncToHqyy")
25
+	beego.Router("/sync/upload/lg2h", &SyncController{}, "get:SyncToLg2h")
26
+	beego.Router("/sync/upload/smzy", &SyncController{}, "get:SyncToSmzy")
27
+	beego.Router("/sync/upload/smyy", &SyncController{}, "get:SyncToTesgt")
28
+
29
+}
30
+
31
+func (c *SyncController) SyncToLg2h() {
32
+	// 第一步:到上报配置表中找到深圳需要上报的机构
33
+	// sz_province, _ := beego.AppConfig.Int64("sz_province")
34
+	// sz_city, _ := beego.AppConfig.Int64("sz_city")
35
+	// configs, _ := service.FindAllDataUploadConfigOrgInfo(sz_province, sz_city, 3)
36
+
37
+	org := &sz.DataUploadConfig{
38
+		OrgId:          9598,
39
+		ProvinceId:     19,
40
+		CityId:         291,
41
+		DepartmentName: "深圳市龙岗区第二人民医院",
42
+		HospitalId:     "455835506",
43
+		InstType:       1,
44
+		DbHost:         "183.62.158.36",
45
+		DbPort:         "61433",
46
+		DbPass:         "LG2H+9897",
47
+		DbUser:         "sa",
48
+		DbName:         "xtzk",
49
+	}
50
+
51
+	// for _, org := range configs {
52
+	// 第二步:跟进配置,创建数据库连接
53
+	if len(org.DbHost) > 0 && len(org.DbUser) > 0 && len(org.DbPort) > 0 && len(org.DbPass) > 0 && len(org.DbName) > 0 {
54
+		orgDb, err := service.CreateSqlServiceDB(org.DbHost, org.DbPort, org.DbUser, org.DbPass, org.DbName)
55
+		if err != nil {
56
+			utils.ErrorLog("创建数据库连接失败:%v", err)
57
+			c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
58
+			return
59
+		}
60
+		fmt.Println("触发了没有22222222")
61
+		// 第三步:开始同步数据
62
+		// 同步医院信息  t_hd_hospital
63
+		// city.SyncHospital(orgDb, org.OrgId, org.HospitalId, org.InstType, org.DepartmentName)
64
+		// // 同步水处理器  t_hd_wm
65
+		// city.SyncWMS(orgDb, org.OrgId, org.HospitalId)
66
+		// // // 同步员工 t_hd_staff
67
+		// city.SyncStaff(orgDb, org.OrgId, org.HospitalId)
68
+		// // // 同步病人 t_hd_patient
69
+		// city.SyncPatient(orgDb, org.OrgId, org.HospitalId)
70
+		// // // 同步排班  t_hd_shift
71
+		// city.SyncShift(orgDb, org.OrgId, org.HospitalId)
72
+		// // 同步处方 t_hd_ps
73
+		// city.SyncPs(orgDb, org.OrgId, org.HospitalId)
74
+		// // 同步处方药品 t_hd_ps
75
+		// city.SyncPsMedicine(orgDb, org.OrgId, org.HospitalId)
76
+		// // // 同步转院信息 t_hd_patient_out
77
+		// city.SyncPatientOut(orgDb, org.OrgId, org.HospitalId)
78
+		// // 同步处方信息 t_hd_doctors_advice
79
+		// city.SyncDoctorAdvice(orgDb, org.OrgId, org.HospitalId)
80
+		// // 同步透中信息 t_hd_middle
81
+		// city.SyncMiddle(orgDb, org.OrgId, org.HospitalId)
82
+		// // // 同步设备 t_hd_other_machine
83
+		// city.SyncOtherMachine(orgDb, org.OrgId, org.HospitalId)
84
+		// // // 同步维修 t_hd_maintain
85
+		// city.SyncMachineRepair(orgDb, org.OrgId, org.HospitalId)
86
+		// // // 同步设备 t_hd_dm
87
+		// city.SyncDM(orgDb, org.OrgId, org.HospitalId)
88
+		// // // 同步患者透析记录 t_hd_dialysis
89
+		// city.SyncDialysis(orgDb, org.OrgId, org.HospitalId)
90
+		// // 同步透析床位分区 t_hd_division
91
+		// city.SyncDivision(orgDb, org.OrgId, org.HospitalId)
92
+		// // 患者通路信息表(T_HD_ACCESS)
93
+		// city.SyncAccess(orgDb, org.OrgId, org.HospitalId)
94
+		// // 透析床位表(T_HD_SICKBED)
95
+		// city.SyncSickbed(orgDb, org.OrgId, org.HospitalId)
96
+		// // 患者诊断信息表(T_HD_DIAGNOSIS)
97
+		// city.SyncDiagnosis(orgDb, org.OrgId, org.HospitalId)
98
+		//  患者传染病检查记录表(T_HD_INFECTION
99
+		//city.SyncInfection(orgDb, org.OrgId, org.HospitalId)
100
+		// //  透析并发症记录表(T_HD_COMPLICATION)
101
+		// city.SyncComplication(orgDb, org.OrgId, org.HospitalId)
102
+		// //  血透患者检测结果表(T_HD_LIS_REPORT)
103
+		// city.SyncLisReport(orgDb, org.OrgId, org.HospitalId)
104
+		// //  血透患者检验结果指标表(T_HD_LIS_INDICATORS)
105
+		// city.SyncLisIndicators(orgDb, org.OrgId, org.HospitalId)
106
+
107
+		// 透析机透析液细菌培养检测记录表(t_hd_dm_dialysate_bc)
108
+		// city.SyncLisCulture(orgDb,org.OrgId,org.HospitalId)
109
+		//透析机透析液内毒素检测记录表(T_HD_DM_DIALYSATE_BC)
110
+		// city.SyncDialysate(orgDb,org.OrgId,org.HospitalId)
111
+
112
+		//物表消毒记录表(T_HD_SURFACE_DISINFECT)
113
+		// city.SyncLisBodyDetection(orgDb,org.OrgId,org.HospitalId)
114
+		// 第四步:关闭数据库连接
115
+
116
+		//透析用水游离氯检测表(T_HD_WATER_FC)
117
+		// city.SyncLisWaterFc(orgDb,org.OrgId,org.HospitalId)
118
+
119
+		//透析用水有毒化学物检测表(T_HD_WATER_NC)
120
+		// city.SynLisWaterNc(orgDb,org.OrgId,org.HospitalId)
121
+
122
+		//透析用水PH值检测表(T_HD_WATER_PH)
123
+		// city.SynLisWaterPh(orgDb,org.OrgId,org.HospitalId)
124
+
125
+		//透析用水水硬度检测表(T_HD_WATER_WH)
126
+		// city.SynListHadWater(orgDb,org.OrgId,org.HospitalId)
127
+
128
+		//导管感染记录表(T_HD_CI)
129
+		// city.SynListHdCi(orgDb,org.OrgId,org.HospitalId)
130
+
131
+		//导管感染转归记录表(T_HD_CI_OUTCOME)
132
+		// city.SynLisHdCiOutCome(orgDb,org.OrgId,org.HospitalId)
133
+
134
+		//透析室空气消毒记录表(T_HD_AIR_DISINFECT)
135
+		// city.SyncLisAirDetection(orgDb,org.OrgId,org.HospitalId)
136
+
137
+		//透析用水细菌培养检测表(T_HD_WATER_BC)
138
+		// city.SyncLisWaterBc(orgDb,org.OrgId,org.HospitalId)
139
+
140
+		//透析用水内毒素检测表(T_HD_WATER_EN)
141
+		// city.SyncLisWaterEn(orgDb,org.OrgId,org.HospitalId)
142
+		// 第四步:关闭数据库连接
143
+		service.CloseDB(orgDb)
144
+	}
145
+	// }
146
+	c.ServeSuccessJSON(map[string]interface{}{
147
+		"resultList": "12345",
148
+	})
149
+	return
150
+}
151
+
152
+func (c *SyncController) SyncToHqyy() {
153
+	// 第一步:到上报配置表中找到深圳需要上报的机构
154
+	// sz_province, _ := beego.AppConfig.Int64("sz_province")
155
+	// sz_city, _ := beego.AppConfig.Int64("sz_city")
156
+	// configs, _ := service.FindAllDataUploadConfigOrgInfo(sz_province, sz_city, 3)
157
+
158
+	org := &sz.DataUploadConfig{
159
+		OrgId:          9442,
160
+		ProvinceId:     19,
161
+		CityId:         291,
162
+		DepartmentName: "暨南大学附属深圳华侨医院",
163
+		HospitalId:     "73307826X",
164
+		InstType:       1,
165
+		DbHost:         "183.11.232.26",
166
+		DbPort:         "3306",
167
+		DbPass:         "1Q2W3e4r!@#$",
168
+		DbUser:         "sa",
169
+		DbName:         "xtzk",
170
+	}
171
+
172
+	// for _, org := range configs {
173
+	// 第二步:跟进配置,创建数据库连接
174
+	if len(org.DbHost) > 0 && len(org.DbUser) > 0 && len(org.DbPort) > 0 && len(org.DbPass) > 0 && len(org.DbName) > 0 {
175
+		orgDb, err := service.CreateSqlServiceDB(org.DbHost, org.DbPort, org.DbUser, org.DbPass, org.DbName)
176
+		if err != nil {
177
+			utils.ErrorLog("创建数据库连接失败:%v", err)
178
+			c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
179
+			return
180
+		}
181
+		// 第三步:开始同步数据
182
+		// 同步医院信息  t_hd_hospital
183
+		city.SyncHospital(orgDb, org.OrgId, org.HospitalId, org.InstType, org.DepartmentName)
184
+		// 同步水处理器  t_hd_wm
185
+		city.SyncWMS(orgDb, org.OrgId, org.HospitalId)
186
+		// // 同步员工 t_hd_staff
187
+		city.SyncStaff(orgDb, org.OrgId, org.HospitalId)
188
+		// // 同步病人 t_hd_patient
189
+		city.SyncPatient(orgDb, org.OrgId, org.HospitalId)
190
+		// // 同步排班  t_hd_shift
191
+		city.SyncShift(orgDb, org.OrgId, org.HospitalId)
192
+		// 同步处方 t_hd_ps
193
+		city.SyncPs(orgDb, org.OrgId, org.HospitalId)
194
+		// 同步处方药品 t_hd_ps
195
+		city.SyncPsMedicine(orgDb, org.OrgId, org.HospitalId)
196
+		// // 同步转院信息 t_hd_patient_out
197
+		city.SyncPatientOut(orgDb, org.OrgId, org.HospitalId)
198
+		// 同步处方信息 t_hd_doctors_advice
199
+		city.SyncDoctorAdvice(orgDb, org.OrgId, org.HospitalId)
200
+		// 同步透中信息 t_hd_middle
201
+		city.SyncMiddle(orgDb, org.OrgId, org.HospitalId)
202
+		// // 同步设备 t_hd_other_machine
203
+		city.SyncOtherMachine(orgDb, org.OrgId, org.HospitalId)
204
+		// // 同步维修 t_hd_maintain
205
+		city.SyncMachineRepair(orgDb, org.OrgId, org.HospitalId)
206
+		// // 同步设备 t_hd_dm
207
+		city.SyncDM(orgDb, org.OrgId, org.HospitalId)
208
+		// // 同步患者透析记录 t_hd_dialysis
209
+		city.SyncDialysis(orgDb, org.OrgId, org.HospitalId)
210
+		// 同步透析床位分区 t_hd_division
211
+		city.SyncDivision(orgDb, org.OrgId, org.HospitalId)
212
+		// 患者通路信息表(T_HD_ACCESS)
213
+		city.SyncAccess(orgDb, org.OrgId, org.HospitalId)
214
+		// 透析床位表(T_HD_SICKBED)
215
+		city.SyncSickbed(orgDb, org.OrgId, org.HospitalId)
216
+		// 患者诊断信息表(T_HD_DIAGNOSIS)
217
+		city.SyncDiagnosis(orgDb, org.OrgId, org.HospitalId)
218
+		//  患者传染病检查记录表(T_HD_INFECTION
219
+		city.SyncInfection(orgDb, org.OrgId, org.HospitalId)
220
+		//  透析并发症记录表(T_HD_COMPLICATION)
221
+		city.SyncComplication(orgDb, org.OrgId, org.HospitalId)
222
+		//  血透患者检测结果表(T_HD_LIS_REPORT)
223
+		city.SyncLisReport(orgDb, org.OrgId, org.HospitalId)
224
+		//  血透患者检验结果指标表(T_HD_LIS_INDICATORS)
225
+		city.SyncLisIndicators(orgDb, org.OrgId, org.HospitalId)
226
+
227
+		// 第四步:关闭数据库连接
228
+		service.CloseDB(orgDb)
229
+	}
230
+	// }
231
+	c.ServeSuccessJSON(map[string]interface{}{
232
+		"resultList": "12345",
233
+	})
234
+	return
235
+}
236
+
237
+func (c *SyncController) SyncToSmzy() {
238
+	// 第一步:到上报配置表中找到深圳需要上报的机构
239
+	// sz_province, _ := beego.AppConfig.Int64("sz_province")
240
+	// sz_city, _ := beego.AppConfig.Int64("sz_city")
241
+	// configs, _ := service.FindAllDataUploadConfigOrgInfo(sz_province, sz_city, 3)
242
+
243
+	org := &sz.DataUploadConfig{
244
+		OrgId:          9504,
245
+		ProvinceId:     19,
246
+		CityId:         291,
247
+		DepartmentName: "深圳生命之源血液透析中心",
248
+		HospitalId:     "MA5EU4PC0",
249
+		InstType:       1,
250
+		DbHost:         "localhost",
251
+		DbPort:         "1433",
252
+		DbPass:         "1Q2W3e4r!@#$",
253
+		DbUser:         "sa",
254
+		DbName:         "xtzk",
255
+	}
256
+
257
+	// for _, org := range configs {
258
+	// 第二步:跟进配置,创建数据库连接
259
+	if len(org.DbHost) > 0 && len(org.DbUser) > 0 && len(org.DbPort) > 0 && len(org.DbPass) > 0 && len(org.DbName) > 0 {
260
+		orgDb, err := service.CreateSqlServiceDB(org.DbHost, org.DbPort, org.DbUser, org.DbPass, org.DbName)
261
+		if err != nil {
262
+			utils.ErrorLog("创建数据库连接失败:%v", err)
263
+			c.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
264
+			return
265
+		}
266
+		// 第三步:开始同步数据
267
+		// 同步医院信息  t_hd_hospital
268
+		city.SyncHospital(orgDb, org.OrgId, org.HospitalId, org.InstType, org.DepartmentName)
269
+		// 同步水处理器  t_hd_wm
270
+		city.SyncWMS(orgDb, org.OrgId, org.HospitalId)
271
+		// // 同步员工 t_hd_staff
272
+		city.SyncStaff(orgDb, org.OrgId, org.HospitalId)
273
+		// // 同步病人 t_hd_patient
274
+		city.SyncPatient(orgDb, org.OrgId, org.HospitalId)
275
+		// // 同步排班  t_hd_shift
276
+		city.SyncShift(orgDb, org.OrgId, org.HospitalId)
277
+		// 同步处方 t_hd_ps
278
+		city.SyncPs(orgDb, org.OrgId, org.HospitalId)
279
+		// 同步处方药品 t_hd_ps
280
+		city.SyncPsMedicine(orgDb, org.OrgId, org.HospitalId)
281
+		// // 同步转院信息 t_hd_patient_out
282
+		city.SyncPatientOut(orgDb, org.OrgId, org.HospitalId)
283
+		// 同步处方信息 t_hd_doctors_advice
284
+		city.SyncDoctorAdvice(orgDb, org.OrgId, org.HospitalId)
285
+		// 同步透中信息 t_hd_middle
286
+		city.SyncMiddle(orgDb, org.OrgId, org.HospitalId)
287
+		// // 同步设备 t_hd_other_machine
288
+		city.SyncOtherMachine(orgDb, org.OrgId, org.HospitalId)
289
+		// // 同步维修 t_hd_maintain
290
+		city.SyncMachineRepair(orgDb, org.OrgId, org.HospitalId)
291
+		// // 同步设备 t_hd_dm
292
+		city.SyncDM(orgDb, org.OrgId, org.HospitalId)
293
+		// // 同步患者透析记录 t_hd_dialysis
294
+		city.SyncDialysis(orgDb, org.OrgId, org.HospitalId)
295
+		// 同步透析床位分区 t_hd_division
296
+		city.SyncDivision(orgDb, org.OrgId, org.HospitalId)
297
+		// 患者通路信息表(T_HD_ACCESS)
298
+		city.SyncAccess(orgDb, org.OrgId, org.HospitalId)
299
+		// 透析床位表(T_HD_SICKBED)
300
+		city.SyncSickbed(orgDb, org.OrgId, org.HospitalId)
301
+		// 患者诊断信息表(T_HD_DIAGNOSIS)
302
+		city.SyncDiagnosis(orgDb, org.OrgId, org.HospitalId)
303
+		//  患者传染病检查记录表(T_HD_INFECTION
304
+		city.SyncInfection(orgDb, org.OrgId, org.HospitalId)
305
+		//  透析并发症记录表(T_HD_COMPLICATION)
306
+		city.SyncComplication(orgDb, org.OrgId, org.HospitalId)
307
+		//  血透患者检测结果表(T_HD_LIS_REPORT)
308
+		city.SyncLisReport(orgDb, org.OrgId, org.HospitalId)
309
+		//  血透患者检验结果指标表(T_HD_LIS_INDICATORS)
310
+		city.SyncLisIndicators(orgDb, org.OrgId, org.HospitalId)
311
+
312
+		// 第四步:关闭数据库连接
313
+		service.CloseDB(orgDb)
314
+	}
315
+	// }
316
+	c.ServeSuccessJSON(map[string]interface{}{
317
+		"resultList": "12345",
318
+	})
319
+	return
320
+}
321
+
322
+func (c *SyncController) SyncToTesgt() {
323
+	fmt.Println("c出发飞阿道夫阿道夫阿方阿方")
324
+	//city.GetInspectionData(10028)
325
+}

File diff suppressed because it is too large
+ 2 - 0
db/xt_drug_dic


+ 21 - 0
db/xt_drugway_dic View File

@@ -0,0 +1,21 @@
1
+INSERT INTO xt_drugway_dic (code, name, status, created_time, updated_time) VALUES 
2
+("DGCX","导管冲洗",1,1536290447,1536290447),
3
+("PO","口服",1,1536290447,1536290447),
4
+("LNZS","瘤内注射",1,1536290447,1536290447),
5
+("IVPUMP","微泵注射",1,1536290447,1536290447),
6
+("WBZS","微泵注射",1,1536290447,1536290447),
7
+("SXHF","舌下含服",1,1536290447,1536290447),
8
+("JMFG","静脉封管",1,1536290447,1536290447),
9
+("DGNWBZS","导管内微泵注射",1,1536290447,1536290447),
10
+("GLCX","管路冲洗",1,1536290447,1536290447),
11
+("PS","皮试 ",1,1536290447,1536290447),
12
+("JMCX","静脉采血",1,1536290447,1536290447),
13
+("YLGCX","引流管冲洗",1,1536290447,1536290447),
14
+("ID","皮内注射",1,1536290447,1536290447),
15
+("IH","皮下注射",1,1536290447,1536290447),
16
+("IM","肌肉注射",1,1536290447,1536290447),
17
+("IV","静脉注射",1,1536290447,1536290447),
18
+("IVGTT","静脉输液(普通)",1,1536290447,1536290447),
19
+("IVGTT","静脉输液(特殊)",1,1536290447,1536290447),
20
+("JBMZ","局部麻醉",1,1536290447,1536290447),
21
+("DGRS","导管溶栓",1,1536290447,1536290447);

+ 35 - 0
db/xt_ef_dic View File

@@ -0,0 +1,35 @@
1
+INSERT INTO xt_execution_frequency_dic (code,name,status,created_time,updated_time) VALUES
2
+("AM","上午",1,1536290447,1536290447),
3
+("QW","每周一次",1,1536290447,1536290447),
4
+("SAS","需要时",1,1536290447,1536290447),
5
+("SQ30FZ","术前30分钟",1,1536290447,1536290447),
6
+("ST","立即",1,1536290447,1536290447),
7
+("TID","每日三次",1,1536290447,1536290447),
8
+("QID","每日四次",1,1536290447,1536290447),
9
+("QIW","每周四次",1,1536290447,1536290447),
10
+("TIW","每周三次",1,1536290447,1536290447),
11
+("TXHLJ","透析后立即",1,1536290447,1536290447),
12
+("XJQ","下机前",1,1536290447,1536290447),
13
+("ONCE","临时一次",1,1536290447,1536290447),
14
+("LZYC","两周一次",1,1536290447,1536290447),
15
+("LZSC","两周三次",1,1536290447,1536290447),
16
+("AA","各",1,1536290447,1536290447),
17
+("SZYC","四周一次",1,1536290447,1536290447),
18
+("QOD","隔日一次",1,1536290447,1536290447),
19
+("QN","每晚一次",1,1536290447,1536290447),
20
+("BID","每日二次",1,1536290447,1536290447),
21
+("BIW","每周二次",1,1536290447,1536290447),
22
+("CF","长方",1,1536290447,1536290447),
23
+("CITO!","急速地",1,1536290447,1536290447),
24
+("CXSY","持续使用",1,1536290447,1536290447),
25
+("F","份",1,1536290447,1536290447),
26
+("HS","临睡前",1,1536290447,1536290447),
27
+("LSKY","临时开药",1,1536290447,1536290447),
28
+("MCYC","每晨一次",1,1536290447,1536290447),
29
+("MFZYC","每分钟一次",1,1536290447,1536290447),
30
+("QD","每日一次",1,1536290447,1536290447),
31
+("QEH","每小时",1,1536290447,1536290447),
32
+("QH","每1小时一次",1,1536290447,1536290447),
33
+("QM","每晨一次",1,1536290447,1536290447),
34
+("QN","每晚",1,1536290447,1536290447),
35
+("SJQ","上机前",1,1536290447,1536290447);

BIN
db/xtdb.docx View File


+ 374 - 0
enums/error_code.go View File

@@ -0,0 +1,374 @@
1
+package enums
2
+
3
+import "Data_Upload_Api/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
+	ErrorCodePrescriptionPermissionDeniedModify = 200020
160
+
161
+	ErrorCodeAdvicePermissionDeniedModify = 200021
162
+	ErrorCodePrescriptionException        = 200022
163
+
164
+	ErrorCodeNameException = 200023
165
+)
166
+
167
+var ErrCodeMsgs = map[int]string{
168
+	// 登录注册错误
169
+	ErrorCodeLoginTimeout:                   "登录超时",
170
+	ErrorCodeNotLogin:                       "未登录",
171
+	ErrorCodePermissionDenied:               "权限不足",
172
+	ErrorCodeMobileRegistered:               "手机号已被注册",
173
+	ErrorCodePasswordEmpty:                  "密码为空",
174
+	ErrorCodeVerificationCodeWrong:          "验证码错误",
175
+	ErrorCodeRegisterFail:                   "注册失败",
176
+	ErrorCodeInvalidToken:                   "令牌无效",
177
+	ErrorCodeAccountOrPasswordWrong:         "账号或密码错误",
178
+	ErrorCodeMissingOrg:                     "未创建机构",
179
+	ErrorCodeMissingOrgApp:                  "未创建任何应用",
180
+	ErrorCodeAccountOrVerCodeWrong:          "账号或验证码错误",
181
+	ErrorCodeMobileNotExit:                  "手机号不存在",
182
+	ErrorCodeUserNotExist:                   "用户不存在",
183
+	ErrorCodeUserWasForbidden:               "该用户被禁用",
184
+	ErrorCodeNeverCreateTypeApp:             "未创建此种应用",
185
+	ErrorCodeContactSuperAdminCreateTypeApp: "请联系超级管理员开通此种应用",
186
+
187
+	// 数据验证错误
188
+	ErrorCodeMobileFormat:     "手机号格式错误",
189
+	ErrorCodeTelphoneFormat:   "电话格式错误",
190
+	ErrorCodeParamWrong:       "参数错误",
191
+	ErrorCodeParamFormatWrong: "参数格式错误",
192
+
193
+	// 数据库操作错误
194
+	ErrorCodeDBCreate:         "数据库创建出错",
195
+	ErrorCodeDBUpdate:         "数据库更新出错",
196
+	ErrorCodeDBDelete:         "数据库删除出错",
197
+	ErrorCodeDBSelectNoResult: "查询无结果",
198
+	ErrorCodeDataException:    "数据异常",
199
+
200
+	// 业务逻辑操作错误
201
+	ErrorCodeRoleNotExist:           "角色不存在",
202
+	ErrorCodeAdminUserNotExist:      "管理员不存在",
203
+	ErrorCodeMobileDidUsedInApp:     "该手机号已在该应用中被注册为管理员",
204
+	ErrorCodeMissingUserName:        "缺少用户名",
205
+	ErrorCodeOldPasswordWrong:       "原密码不正确",
206
+	ErrorCodeCannotRemoveRole:       "存在该角色的管理员,不能删除该角色",
207
+	ErrorCodeRoleMobileIsSuperAdmin: "该手机号已注册为超级管理员",
208
+
209
+	ErrorCodeGetQiniuUpToken: "获取七牛uptoken失败",
210
+	ErrorCodeCreatePatient:   "创建患者失败",
211
+	ErrorCodeDialysisNoExist: "患者透析号重复!",
212
+	ErrorCodeIdCardNoExist:   "身份证号重复!",
213
+	ErrorCodePatientNoExist:  "患者信息不存在!",
214
+	ErrorCodeUpdatePatient:   "修改患者信息失败",
215
+
216
+	ErrorCodeDialysisSolutionExist:          "该处方已经存在",
217
+	ErrorCodeDialysisSolutionCreate:         "创建处方失败",
218
+	ErrorCodeDialysisSolutionUpdate:         "修改处方失败",
219
+	ErrorCodeDialysisSolutionNotExist:       "该处方不存在",
220
+	ErrorCodeParentDialysisSolutionNotExist: "上级处方不存在",
221
+	ErrorCodeAlReadyHadChildSolution:        "所选处方已经存在子方案",
222
+	ErrorCodeCanntCreateChildChildSolution:  "子方案不能添加子方案",
223
+	ErrorCodeDialysisSolutionUsed:           "处方已被使用,不能删除",
224
+	ErrorCodeCreateDryWeightFail:            "添加干体重失败",
225
+	ErrorCodeCreateDoctorAdviceFail:         "添加医嘱失败",
226
+	ErrorCodeUpdateDoctorAdviceFail:         "修改医嘱信息失败",
227
+	ErrorCodeDoctorAdviceNotExist:           "医嘱不存在",
228
+	ErrorCodeLongTimeAdviceNotCanntEdit:     "长期医嘱不能修改!",
229
+	ErrorCodeAdviceStoped:                   "所选医嘱已停止",
230
+	ErrorCodeParentAdviceNotExist:           "上级医嘱不存在",
231
+	ErrorCodeDeleteAdviceFail:               "删除医嘱失败",
232
+	ErrorCodeStopAdviceFail:                 "停止医嘱失败",
233
+	ErrorCodeDialysisSolutionDelete:         "删除方案失败",
234
+	ErrorCodeDeviceNumberNotTheZone:         "所选机号不在选择分区中",
235
+	ErrorCodeCreateScheduleFail:             "添加排班失败",
236
+	ErrorCodeCantSetScheduleAgainOneDay:     "同一天不可有两次排班",
237
+	ErrorCodeCantSetScheduleBeforeNow:       "不能给今天之前的日期排班",
238
+	ErrorCodeScheduleNotExist:               "排班不存在",
239
+	ErrorCodePointScheduleExist:             "所先位置排班已经存在",
240
+	ErrorCodeDeleteScheduleFail:             "取消排班失败",
241
+	ErrorCodeChangeScheduleFail:             "修改排班失败",
242
+	ErrorCodePatientPhoneUsed:               "手机号已经存在",
243
+	ErrorCodeAdviceExced:                    "医嘱已经执行",
244
+	ErrorCodeAdviceCheckBeforeExce:          "核对医嘱不能在执行医嘱之前",
245
+	ErrorCodeAdviceExceBeforeStart:          "执行医嘱不能在开始之前",
246
+	ErrorCodeAdviceChecked:                  "医嘱已经核对",
247
+	ErrorCodeExceAndCheckNotOneUser:         "核对与执行不能是同一人",
248
+	ErrorCodeCanotEditOtherAdvice:           "不能修改非本人添加的医嘱",
249
+	ErrorCodeEditLapsetoFail:                "转归失败",
250
+	ErrorCodeDelScheduleFailByDialysis:      "已经上机透析,不能取消排班",
251
+	ErrorCodeNotSelectLapsetoType:           "请选择转归状态",
252
+	ErrorCodeNotSelectLapsetoTime:           "请选择转归时间",
253
+
254
+	ErrorCodeInspectionDateExit:    "当天已经存在检验检查记录",
255
+	ErrorCodeInspectionAddFail:     "添加记录失败",
256
+	ErrorCodeInspectionDateNotExit: "当天不存在检验检查记录",
257
+	ErrorCodeInspectionEditFail:    "修改记录失败",
258
+	ErrorCodeInspectionDeleteFail:  "删除记录失败",
259
+
260
+	ErrorCodeDeviceZoneNotExist:                      "设备分区不存在",
261
+	ErrorCodeDeviceZoneNameRepeat:                    "该分区名已存在",
262
+	ErrorCodeDeviceGroupNotExist:                     "设备分组不存在",
263
+	ErrorCodeDeviceGroupNameRepeat:                   "该分组名已存在",
264
+	ErrorCodeDeviceNumberNotExist:                    "机号不存在",
265
+	ErrorCodeDeviceNumberRepeat:                      "该机号已存在",
266
+	ErrorCodeDeviceNotExist:                          "该设备不存在",
267
+	ErrorCodeDeviceZoneCannotDisable:                 "该分区存在床位号,不能删除",
268
+	ErrorCodeDeviceNumberCannotDisableCuzDevice:      "该床位存在设备,不能删除",
269
+	ErrorCodeDeviceNumberCannotDisableCuzSchedule:    "该床位尚有排班安排,不能删除",
270
+	ErrorCodeDeviceNumberCannotDisableCuzSchTemplate: "排班模板在该床位尚有排班安排,不能删除",
271
+
272
+	ErrorCodeNotSubscibe:       "没有订阅服务或服务已过期,请先购买服务!",
273
+	ErrorCodeServeNotExist:     "服务订单不存在!",
274
+	ErrorCodeInvoiceExist:      "已经申请了发票!",
275
+	ErrorCodeApplyInvoiceFail:  "申请发票失败!",
276
+	ErrorCodeHetongHad:         "合同已经存在!",
277
+	ErrorCodeCreateHetongFail:  "合同创建失败",
278
+	ErrorCodePatientReachLimit: "患者数已达到当前服务版本病人数,需要升级到更高的版本",
279
+
280
+	ErrorCodeMonitorCreate:                  "创建监测失败",
281
+	ErrorCodeMonitorNotExist:                "监测记录不存在",
282
+	ErrorCodeMonitorUpdate:                  "修改监测失败",
283
+	ErrorCodeDialysisPermissionDeniedModify: "您没有权限修改其他医护的数据!",
284
+
285
+	ErrorDialysisOrderNoStart:     "尚未上机,无法执行下机操作",
286
+	ErrorDialysisOrderNoEND:       "已处于下机状态",
287
+	ErrorDialysisOrderRepeatStart: "已上机",
288
+	//ErrorCodeScheduleTemplateNotExist: "排班模板不存在",
289
+
290
+	ErrorCodeSystemError:              "系统异常",
291
+	ErrorCodeProductError:             "该服务商品已丢失",
292
+	ErrorCodeScheduleTemplateNotExist: "排班模板不存在",
293
+
294
+	ErrorCodeCreateStockInFail: "入库失败",
295
+	//ErrorCodeSystemError:  "系统异常",
296
+	//ErrorCodeProductError: "该服务商品已丢失",
297
+	ErrorCodeFieldExist:   "配置字段已存在",
298
+	ErrorCodeCreateConfig: "创建配置失败",
299
+	ErrorCodeUpdateConfig: "修改配置失败",
300
+
301
+	ErrorCommitFail:               "提交失败",
302
+	ErrorCodeDoubleCheckWrong:     "核对已完成, 无法再次提交",
303
+	ErrorCodeDoubleCheckUserWrong: "你已完成核对,不能重复核对",
304
+	ErrorCodeGoodNoStockInError:   "该商品尚未入库",
305
+
306
+	ErrorCodeCancelStockFail:    "出库退库失败",
307
+	ErrorCodeDeleteGoodTypeFail: "该类型存在商品信息,无法删除",
308
+	ErrorCodeDeleteGoodInfoFail: "该商品已经入库无法删除",
309
+
310
+	ErrorCodeDeleteFail: "删除失败",
311
+
312
+	ErrorCodeKeyFail:                 "关键字不能为空",
313
+	ErrorCodeDeleteStockInRecordFail: "该记录已经有出库或退货操作,无法删除",
314
+	ErrorCodeNameWrong:               "该模版名字已存在",
315
+	ErrorCodeParamEmptyWrong:         "模版名称不能为空",
316
+	ErrorCodeParamAdviceEmptyWrong:   "医嘱名称不能为空",
317
+
318
+	ErrorCodeDeleteDealerWrong:       "该经销商所属商品已入库无法删除",
319
+	ErrorCodeDeleteManufacturerWrong: "该厂商所属商品已入库无法删除",
320
+	ErrorCodeGoodTypeNameExistError:  "该商品类型名字已存在",
321
+	ErrorCodeGoodInfoNameExistError:  "该规格名称名字已存在",
322
+
323
+	ErrorCodePrescriptionPermissionDeniedModify: "您没有权限修改透析处方数据",
324
+	ErrorCodeAdvicePermissionDeniedModify:       "您没有权限添加医嘱",
325
+	ErrorCodePrescriptionException:              "上机失败,请先开处方",
326
+
327
+	ErrorCodeNameException: "账号已经存在",
328
+}
329
+
330
+type SGJError struct {
331
+	Code int
332
+}
333
+
334
+func (e *SGJError) Error() string {
335
+	value, ok := ErrCodeMsgs[e.Code]
336
+	if ok {
337
+		return value
338
+	} else {
339
+		return "未知错误"
340
+	}
341
+}
342
+
343
+func MakeSuccessResponseJSON(data map[string]interface{}) map[string]interface{} {
344
+	json := make(map[string]interface{})
345
+	if data != nil {
346
+		json["data"] = data
347
+	} else {
348
+		json["data"] = make(map[string]interface{})
349
+	}
350
+	json["state"] = 1
351
+	json["code"] = 0
352
+	return json
353
+}
354
+
355
+func MakeFailResponseJSON(errMsg string, errCode int) map[string]interface{} {
356
+	json := make(map[string]interface{})
357
+	json["msg"] = errMsg
358
+	json["code"] = errCode
359
+	json["state"] = 0
360
+	return json
361
+}
362
+
363
+func MakeFailResponseJSONWithSGJError(err *SGJError) map[string]interface{} {
364
+	if err == nil {
365
+		utils.WarningLog("MakeFailResponseJSONWithSGJError 参数err 不能为空")
366
+		return nil
367
+	}
368
+	return MakeFailResponseJSON(err.Error(), err.Code)
369
+}
370
+
371
+func MakeFailResponseJSONWithSGJErrorCode(code int) map[string]interface{} {
372
+	err := &SGJError{Code: code}
373
+	return MakeFailResponseJSON(err.Error(), err.Code)
374
+}

+ 20 - 0
main.go View File

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

File diff suppressed because it is too large
+ 1267 - 0
models/src_data.go


File diff suppressed because it is too large
+ 1012 - 0
models/sz/target_data.go


+ 22 - 0
routers/router.go View File

@@ -0,0 +1,22 @@
1
+package routers
2
+
3
+import (
4
+	"Xcx_New/controllers"
5
+	"fmt"
6
+	"github.com/astaxie/beego"
7
+	"github.com/astaxie/beego/plugins/cors"
8
+)
9
+
10
+func init() {
11
+	beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
12
+		// AllowAllOrigins:  true,
13
+		AllowOrigins:     []string{"http://api.szjkhd.com", "http://admin.xt.test.szjkhd.com", "http://admin.xt.szjkhd.com", "http://localhost:9527"},
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
+	fmt.Println(" chufffdsdfsdfsdfasdf adf afd s fadsf ")
20
+	//controllers.SyncAPIRegisterRouters()
21
+	controllers.MobileRegisterRouters()
22
+}

File diff suppressed because it is too large
+ 2658 - 0
service/city/auto_create_week_schedules_service.go


File diff suppressed because it is too large
+ 1410 - 0
service/city_data_uoload_service.go


+ 150 - 0
service/db.go View File

@@ -0,0 +1,150 @@
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
+	"github.com/astaxie/beego"
22
+	"github.com/jinzhu/gorm"
23
+	_ "github.com/jinzhu/gorm/dialects/mssql"
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 CreateDB(Host string, Port string, User string, Pass string, Name string) (rsdDb *gorm.DB, err error) {
35
+	rdb := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", User, Pass, Host, Port, Name)
36
+	rsdDb, err = gorm.Open("mysql", rdb)
37
+	if err != nil {
38
+		//beego.Error(err)
39
+	}
40
+	rsdDb.DB().SetMaxIdleConns(5)
41
+	rsdDb.DB().SetMaxOpenConns(20)
42
+	rsdDb.LogMode(true)
43
+	return
44
+}
45
+
46
+func CreateSqlServiceDB(Host string, Port string, User string, Pass string, Name string) (mssqlDb *gorm.DB, err error) {
47
+	//rdb := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", User, Pass, Host, Port, Name)
48
+	mssqlstring := fmt.Sprintf("server=%s;port=%s;database=%s;user id=%s;password=%s", Host, Port, Name, User, Pass)
49
+	fmt.Println(mssqlstring)
50
+	mssqlDb, err = gorm.Open("mssql", mssqlstring)
51
+	if err != nil {
52
+		panic(err)
53
+	}
54
+	mssqlDb.DB().SetMaxIdleConns(5)
55
+	mssqlDb.DB().SetMaxOpenConns(20)
56
+	mssqlDb.LogMode(true)
57
+	return
58
+}
59
+
60
+func CloseDB(DB *gorm.DB) {
61
+	DB.Close()
62
+}
63
+
64
+func ConnectDB() {
65
+	readHost := beego.AppConfig.String("readmysqlhost")
66
+	readPort := beego.AppConfig.String("readmysqlport")
67
+	readUser := beego.AppConfig.String("readmysqluser")
68
+	readPass := beego.AppConfig.String("readmysqlpass")
69
+	readName := beego.AppConfig.String("readmysqlname")
70
+
71
+	writeHost := beego.AppConfig.String("writemysqlhost")
72
+	writePort := beego.AppConfig.String("writemysqlport")
73
+	writeUser := beego.AppConfig.String("writemysqluser")
74
+	writePass := beego.AppConfig.String("writemysqlpass")
75
+	writeName := beego.AppConfig.String("writemysqlname")
76
+
77
+	readUserHost := beego.AppConfig.String("readuserhost")
78
+	readUserPort := beego.AppConfig.String("readuserport")
79
+	readUserUser := beego.AppConfig.String("readuseruser")
80
+	readUserPass := beego.AppConfig.String("readuserpass")
81
+	readUserName := beego.AppConfig.String("readusername")
82
+
83
+	writeUserHost := beego.AppConfig.String("writeuserhost")
84
+	writeUserPort := beego.AppConfig.String("writeuserport")
85
+	writeUserUser := beego.AppConfig.String("writeuseruser")
86
+	writeUserPass := beego.AppConfig.String("writeuserpass")
87
+	writeUserName := beego.AppConfig.String("writeusername")
88
+
89
+	rdsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", readUser, readPass, readHost, readPort, readName)
90
+	wdsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", writeUser, writePass, writeHost, writePort, writeName)
91
+
92
+	rudsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", readUserUser, readUserPass, readUserHost, readUserPort, readUserName)
93
+	wudsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", writeUserUser, writeUserPass, writeUserHost, writeUserPort, writeUserName)
94
+
95
+	readDb, err = gorm.Open("mysql", rdsn)
96
+
97
+	//defer readDb.Close()
98
+	if err != nil {
99
+		//beego.Error(err)
100
+	}
101
+	readDb.DB().SetMaxIdleConns(5)
102
+	readDb.DB().SetMaxOpenConns(20)
103
+	readDb.LogMode(true)
104
+
105
+	writeDb, err = gorm.Open("mysql", wdsn)
106
+	if err != nil {
107
+		//beego.Error(err)
108
+	}
109
+
110
+	//defer writeDb.Close()
111
+
112
+	writeDb.DB().SetMaxIdleConns(5)
113
+	writeDb.DB().SetMaxOpenConns(20)
114
+	writeDb.LogMode(true)
115
+
116
+	readUserDb, err = gorm.Open("mysql", rudsn)
117
+	if err != nil {
118
+		//beego.Error(err)
119
+	}
120
+
121
+	//defer readUserDb.Close()
122
+
123
+	readUserDb.DB().SetMaxIdleConns(5)
124
+	readUserDb.DB().SetMaxOpenConns(20)
125
+	readUserDb.LogMode(true)
126
+
127
+	writeUserDb, err = gorm.Open("mysql", wudsn)
128
+	if err != nil {
129
+		//beego.Error(err)
130
+	}
131
+	//defer writeUserDb.Close()
132
+
133
+	writeUserDb.DB().SetMaxIdleConns(5)
134
+	writeUserDb.DB().SetMaxOpenConns(20)
135
+	writeUserDb.LogMode(true)
136
+
137
+}
138
+
139
+func XTReadDB() *gorm.DB {
140
+	return readDb
141
+}
142
+func XTWriteDB() *gorm.DB {
143
+	return writeDb
144
+}
145
+func UserReadDB() *gorm.DB {
146
+	return readUserDb
147
+}
148
+func UserWriteDB() *gorm.DB {
149
+	return writeUserDb
150
+}

BIN
static/1.jpg View File


BIN
static/2.jpg View File


BIN
static/5.jpg View File


+ 1 - 0
static/js/reload.min.js View File

@@ -0,0 +1 @@
1
+function b(a){var c=new WebSocket(a);c.onclose=function(){setTimeout(function(){b(a)},2E3)};c.onmessage=function(){location.reload()}}try{if(window.WebSocket)try{b("ws://localhost:12450/reload")}catch(a){console.error(a)}else console.log("Your browser does not support WebSockets.")}catch(a){console.error("Exception during connecting to Reload:",a)};

+ 37 - 0
tests/default_test.go View File

@@ -0,0 +1,37 @@
1
+package test
2
+
3
+import (
4
+	_ "XT/routers"
5
+	"net/http"
6
+	"net/http/httptest"
7
+	"path/filepath"
8
+	"runtime"
9
+	"testing"
10
+
11
+	"github.com/astaxie/beego"
12
+	. "github.com/smartystreets/goconvey/convey"
13
+)
14
+
15
+func init() {
16
+	_, file, _, _ := runtime.Caller(1)
17
+	apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator))))
18
+	beego.TestBeegoInit(apppath)
19
+}
20
+
21
+// TestBeego is a sample to run an endpoint test
22
+func TestBeego(t *testing.T) {
23
+	r, _ := http.NewRequest("GET", "/", nil)
24
+	w := httptest.NewRecorder()
25
+	beego.BeeApp.Handlers.ServeHTTP(w, r)
26
+
27
+	beego.Trace("testing", "TestBeego", "Code[%d]\n%s", w.Code, w.Body.String())
28
+
29
+	Convey("Subject: Test Station Endpoint\n", t, func() {
30
+		Convey("Status Code Should Be 200", func() {
31
+			So(w.Code, ShouldEqual, 200)
32
+		})
33
+		Convey("The Result Should Not Be Empty", func() {
34
+			So(w.Body.Len(), ShouldBeGreaterThan, 0)
35
+		})
36
+	})
37
+}

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

File diff suppressed because it is too large
+ 95 - 0
views/index.tpl