🐛 fix bug
This commit is contained in:
		| @@ -15,7 +15,8 @@ WORKDIR /go/src/miniapp | |||||||
|  |  | ||||||
| COPY --from=0 /go/src/miniapp/server ./ | COPY --from=0 /go/src/miniapp/server ./ | ||||||
| COPY --from=0 /go/src/miniapp/resource ./resource/ | COPY --from=0 /go/src/miniapp/resource ./resource/ | ||||||
| COPY --from=0 /go/src/miniapp/config.yaml ./ | COPY --from=0 /go/src/miniapp/docker/config.docker.yaml ./docker/ | ||||||
|  | COPY --from=0 /go/src/miniapp/docker ./ | ||||||
|  |  | ||||||
| EXPOSE 8888 | EXPOSE 8888 | ||||||
| ENTRYPOINT ./server -c config.yaml | ENTRYPOINT ./server -c docker/config.docker.yaml | ||||||
|   | |||||||
| @@ -1,8 +1,11 @@ | |||||||
| package app | package app | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"git.echol.cn/loser/logger/log" | 	"git.echol.cn/loser/logger/log" | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
|  | 	"github.com/medivhzhan/weapp/v3" | ||||||
|  | 	msg "github.com/medivhzhan/weapp/v3/subscribemessage" | ||||||
| 	"miniapp/api" | 	"miniapp/api" | ||||||
| 	"miniapp/model/app" | 	"miniapp/model/app" | ||||||
| 	"miniapp/model/app/request" | 	"miniapp/model/app/request" | ||||||
| @@ -86,6 +89,13 @@ func (u *UserApi) UpdateUser(ctx *gin.Context) { | |||||||
| 	if p.Phone != "" { | 	if p.Phone != "" { | ||||||
| 		loginUser.Phone = p.Phone | 		loginUser.Phone = p.Phone | ||||||
| 	} | 	} | ||||||
|  | 	if p.SurgeryTime != "" { | ||||||
|  | 		//t, _ := time.Parse("2006-01-02", p.SurgeryTime) | ||||||
|  | 		//format := t.UTC().Format("2006-01-02") | ||||||
|  | 		loginUser.SurgeryTime = p.SurgeryTime | ||||||
|  | 	} | ||||||
|  | 	loginUser.IsSurgery = p.IsSurgery | ||||||
|  | 	loginUser.HospitalId = p.HospitalId | ||||||
| 	// 修改数据 | 	// 修改数据 | ||||||
| 	if err := userService.UpdateUserInfo(&loginUser); err != nil { | 	if err := userService.UpdateUserInfo(&loginUser); err != nil { | ||||||
| 		log.Errorf("修改用户信息失败:%s", err.Error()) | 		log.Errorf("修改用户信息失败:%s", err.Error()) | ||||||
| @@ -137,3 +147,46 @@ func (u *UserApi) GetInfo(ctx *gin.Context) { | |||||||
| 	} | 	} | ||||||
| 	r.OkWithData(userInfo, ctx) | 	r.OkWithData(userInfo, ctx) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // SendMedicineRemind 发送用药提醒消息 | ||||||
|  | func (u *UserApi) SendMedicineRemind(ctx *gin.Context) { | ||||||
|  | 	var req utils.SendRequest | ||||||
|  | 	if err := ctx.ShouldBind(&req); err != nil { | ||||||
|  | 		r.FailWithMessage("参数错误: "+err.Error(), ctx) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//app-id: wxaaf66dbb5c3983b3 | ||||||
|  | 	//app-secret: 0abba24dbff43febba1e551651f693b4 | ||||||
|  | 	//template-id: PgxoZOOSDgBcmIGd_EVLDnYUmL3eu6NQTAZCsHQeuWY | ||||||
|  |  | ||||||
|  | 	sdk := weapp.NewClient("wxaaf66dbb5c3983b3", "0abba24dbff43febba1e551651f693b4") | ||||||
|  |  | ||||||
|  | 	msgData := msg.SendRequest{ | ||||||
|  | 		ToUser:           "o9Fq_6_cYKvOWnyUM3McC11hWsTI", | ||||||
|  | 		TemplateID:       "PgxoZOOSDgBcmIGd_EVLDnYUmL3eu6NQTAZCsHQeuWY", | ||||||
|  | 		Page:             "page/index/todo", | ||||||
|  | 		MiniprogramState: msg.MiniprogramStateTrial, | ||||||
|  | 		Data: msg.SendData{ | ||||||
|  | 			"thing1":        msg.SendValue{Value: "眼药水"}, | ||||||
|  | 			"time2":         msg.SendValue{Value: "20:00"}, | ||||||
|  | 			"short_thing17": msg.SendValue{Value: "一天4次"}, | ||||||
|  | 			"time15":        msg.SendValue{Value: "2024-03-20 20:00"}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	send, err := sdk.NewSubscribeMessage().Send(&msgData) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = send.GetResponseError() | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Printf("微信返回错误: %#v", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Printf("返回结果: %#v", send) | ||||||
|  |  | ||||||
|  | 	r.Ok(ctx) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,203 +0,0 @@ | |||||||
| # miniapp Global Configuration |  | ||||||
|  |  | ||||||
| # jwt configuration |  | ||||||
| jwt: |  | ||||||
|   signing-key: qmPlus |  | ||||||
|   expires-time: 7d |  | ||||||
|   buffer-time: 1d |  | ||||||
|   issuer: qmPlus |  | ||||||
| # zap logger configuration |  | ||||||
| zap: |  | ||||||
|   level: info |  | ||||||
|   format: console |  | ||||||
|   prefix: "[miniapp]" |  | ||||||
|   director: log |  | ||||||
|   show-line: true |  | ||||||
|   encode-level: LowercaseColorLevelEncoder |  | ||||||
|   stacktrace-key: stacktrace |  | ||||||
|   log-in-console: true |  | ||||||
|  |  | ||||||
| # redis configuration |  | ||||||
| redis: |  | ||||||
|   db: 0 |  | ||||||
|   addr: 177.7.0.14:6379 |  | ||||||
|   password: "" |  | ||||||
|  |  | ||||||
| # email configuration |  | ||||||
| email: |  | ||||||
|   to: xxx@qq.com |  | ||||||
|   port: 465 |  | ||||||
|   from: xxx@163.com |  | ||||||
|   host: smtp.163.com |  | ||||||
|   is-ssl: true |  | ||||||
|   secret: xxx |  | ||||||
|   nickname: test |  | ||||||
|  |  | ||||||
| # system configuration |  | ||||||
| system: |  | ||||||
|   env: public  # Change to "develop" to skip authentication for development mode |  | ||||||
|   addr: 8888 |  | ||||||
|   db-type: mysql |  | ||||||
|   oss-type: local    # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server.exe.exe/utils/upload/upload.go 中 NewOss函数配置 |  | ||||||
|   use-redis: false     # 使用redis |  | ||||||
|   use-multipoint: false |  | ||||||
|   # IP限制次数 一个小时15000次 |  | ||||||
|   iplimit-count: 15000 |  | ||||||
|   #  IP限制一个小时 |  | ||||||
|   iplimit-time: 3600 |  | ||||||
|  |  | ||||||
| # captcha configuration |  | ||||||
| captcha: |  | ||||||
|   key-long: 6 |  | ||||||
|   img-width: 240 |  | ||||||
|   img-height: 80 |  | ||||||
|   open-captcha: 0 # 0代表一直开启,大于0代表限制次数 |  | ||||||
|   open-captcha-timeout: 3600 # open-captcha大于0时才生效 |  | ||||||
|  |  | ||||||
| # mysql connect configuration |  | ||||||
| # 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master) |  | ||||||
| mysql: |  | ||||||
|   path: "" |  | ||||||
|   port: "" |  | ||||||
|   config: "" |  | ||||||
|   db-name: "" |  | ||||||
|   username: "" |  | ||||||
|   password: "" |  | ||||||
|   max-idle-conns: 10 |  | ||||||
|   max-open-conns: 100 |  | ||||||
|   log-mode: "" |  | ||||||
|   log-zap: false |  | ||||||
|  |  | ||||||
| # pgsql connect configuration |  | ||||||
| # 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master) |  | ||||||
| pgsql: |  | ||||||
|   path: "" |  | ||||||
|   port: "" |  | ||||||
|   config: "" |  | ||||||
|   db-name: "" |  | ||||||
|   username: "" |  | ||||||
|   password: "" |  | ||||||
|   max-idle-conns: 10 |  | ||||||
|   max-open-conns: 100 |  | ||||||
|   log-mode: "" |  | ||||||
|   log-zap: false |  | ||||||
|  |  | ||||||
| db-list: |  | ||||||
|   - disable: true # 是否禁用 |  | ||||||
|     type: "" # 数据库的类型,目前支持mysql、pgsql |  | ||||||
|     alias-name: "" # 数据库的名称,注意: alias-name 需要在db-list中唯一 |  | ||||||
|     path: "" |  | ||||||
|     port: "" |  | ||||||
|     config: "" |  | ||||||
|     db-name: "" |  | ||||||
|     username: "" |  | ||||||
|     password: "" |  | ||||||
|     max-idle-conns: 10 |  | ||||||
|     max-open-conns: 100 |  | ||||||
|     log-mode: "" |  | ||||||
|     log-zap: false |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # local configuration |  | ||||||
| local: |  | ||||||
|   path: uploads/file |  | ||||||
|   store-path: uploads/file |  | ||||||
|  |  | ||||||
| # autocode configuration |  | ||||||
| autocode: |  | ||||||
|   transfer-restart: true |  | ||||||
|   # root 自动适配项目根目录 |  | ||||||
|   # 请不要手动配置,他会在项目加载的时候识别出根路径 |  | ||||||
|   root: "" |  | ||||||
|   server: /server.exe.exe |  | ||||||
|   server-plug: /plugin/%s |  | ||||||
|   server-api: /api/v1/%s |  | ||||||
|   server-initialize: /initialize |  | ||||||
|   server-model: /model/%s |  | ||||||
|   server-request: /model/%s/request/ |  | ||||||
|   server-router: /router/%s |  | ||||||
|   server-service: /service/%s |  | ||||||
|   web: /web/src |  | ||||||
|   web-api: /api |  | ||||||
|   web-form: /view |  | ||||||
|   web-table: /view |  | ||||||
|  |  | ||||||
| # qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址) |  | ||||||
| qiniu: |  | ||||||
|   zone: ZoneHuaDong |  | ||||||
|   bucket: "" |  | ||||||
|   img-path: "" |  | ||||||
|   use-https: false |  | ||||||
|   access-key: "" |  | ||||||
|   secret-key: "" |  | ||||||
|   use-cdn-domains: false |  | ||||||
|  |  | ||||||
| # aliyun oss configuration |  | ||||||
| aliyun-oss: |  | ||||||
|   endpoint: yourEndpoint |  | ||||||
|   access-key-id: yourAccessKeyId |  | ||||||
|   access-key-secret: yourAccessKeySecret |  | ||||||
|   bucket-name: yourBucketName |  | ||||||
|   bucket-url: yourBucketUrl |  | ||||||
|   base-path: yourBasePath |  | ||||||
|  |  | ||||||
| # tencent cos configuration |  | ||||||
| tencent-cos: |  | ||||||
|   bucket: xxxxx-10005608 |  | ||||||
|   region: ap-shanghai |  | ||||||
|   secret-id: your-secret-id |  | ||||||
|   secret-key: your-secret-key |  | ||||||
|   base-url: https://gin.vue.admin |  | ||||||
|   path-prefix: miniapp |  | ||||||
|  |  | ||||||
| # aws s3 configuration (minio compatible) |  | ||||||
| aws-s3: |  | ||||||
|   bucket: xxxxx-10005608 |  | ||||||
|   region: ap-shanghai |  | ||||||
|   endpoint: "" |  | ||||||
|   s3-force-path-style: false |  | ||||||
|   disable-ssl: false |  | ||||||
|   secret-id: your-secret-id |  | ||||||
|   secret-key: your-secret-key |  | ||||||
|   base-url: https://gin.vue.admin |  | ||||||
|   path-prefix: miniapp |  | ||||||
|  |  | ||||||
| # huawei obs configuration |  | ||||||
| hua-wei-obs: |  | ||||||
|   path: you-path |  | ||||||
|   bucket: you-bucket |  | ||||||
|   endpoint: you-endpoint |  | ||||||
|   access-key: you-access-key |  | ||||||
|   secret-key: you-secret-key |  | ||||||
|  |  | ||||||
| # excel configuration |  | ||||||
| excel: |  | ||||||
|   dir: ./resource/excel/ |  | ||||||
|  |  | ||||||
| # timer task db clear table |  | ||||||
| Timer: |  | ||||||
|   start: true |  | ||||||
|   spec: "@daily"  # 定时任务详细配置参考 https://pkg.go.dev/github.com/robfig/cron/v3 |  | ||||||
|   detail: |  | ||||||
|     - tableName: sys_operation_records |  | ||||||
|       compareField: created_at |  | ||||||
|       interval: 2160h |  | ||||||
|     - tableName: jwt_blacklists |  | ||||||
|       compareField: created_at |  | ||||||
|       interval: 168h |  | ||||||
|  |  | ||||||
| # 跨域配置 |  | ||||||
| # 需要配合 server.exe.exe/initialize/router.go -> `Router.Use(middleware.CorsByRules())` 使用 |  | ||||||
| cors: |  | ||||||
|   mode: whitelist # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝 |  | ||||||
|   whitelist: |  | ||||||
|     - allow-origin: example1.com |  | ||||||
|       allow-headers: content-type |  | ||||||
|       allow-methods: GET, POST |  | ||||||
|       expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type |  | ||||||
|       allow-credentials: true # 布尔值 |  | ||||||
|     - allow-origin: example2.com |  | ||||||
|       allow-headers: content-type |  | ||||||
|       allow-methods: GET, POST |  | ||||||
|       expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type |  | ||||||
|       allow-credentials: true # 布尔值 |  | ||||||
| @@ -1,12 +1,12 @@ | |||||||
| package config | package config | ||||||
|  |  | ||||||
|  | // MiniApp 微信小程序配置 | ||||||
| type MiniApp struct { | type MiniApp struct { | ||||||
| 	AppId     string `mapstructure:"app-id" yaml:"app-id"` | 	AppId      string `mapstructure:"app-id" yaml:"app-id"` | ||||||
| 	AppSecret string `mapstructure:"app-secret" yaml:"app-secret"` | 	AppSecret  string `mapstructure:"app-secret" yaml:"app-secret"` | ||||||
|  | 	TemplateID string `mapstructure:"template-id" yaml:"template-id"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // 微信小程序配置 |  | ||||||
|  |  | ||||||
| // 微信支付配置 | // 微信支付配置 | ||||||
| type wechatPayConfig struct { | type wechatPayConfig struct { | ||||||
| 	MchId      string `mapstructure:"mchId" yaml:"mchId"`           // 商户号 | 	MchId      string `mapstructure:"mchId" yaml:"mchId"`           // 商户号 | ||||||
|   | |||||||
| @@ -79,12 +79,12 @@ mini-app: | |||||||
|     app-secret: 0abba24dbff43febba1e551651f693b4 |     app-secret: 0abba24dbff43febba1e551651f693b4 | ||||||
| mysql: | mysql: | ||||||
|     prefix: "" |     prefix: "" | ||||||
|     port: "3307" |     port: "3306" | ||||||
|     config: charset=utf8mb4&parseTime=True&loc=Local |     config: charset=utf8mb4&parseTime=True&loc=Local | ||||||
|     db-name: mini_app |     db-name: jmyl | ||||||
|     username: root |     username: jmyl | ||||||
|     password: Jmyl123123 |     password: Jmyl123123 | ||||||
|     path: 47.116.50.126 |     path: 101.35.50.11 | ||||||
|     engine: "" |     engine: "" | ||||||
|     log-mode: error |     log-mode: error | ||||||
|     max-idle-conns: 10 |     max-idle-conns: 10 | ||||||
| @@ -92,8 +92,8 @@ mysql: | |||||||
|     singular: false |     singular: false | ||||||
|     log-zap: false |     log-zap: false | ||||||
| redis: | redis: | ||||||
|     addr: 47.116.50.126:6378 |     addr: 101.35.50.11:6379 | ||||||
|     password: "Jmyl123123" |     password: "loser7659" | ||||||
|     db: 0 |     db: 0 | ||||||
| system: | system: | ||||||
|     env: public |     env: public | ||||||
							
								
								
									
										132
									
								
								docker/config.docker.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								docker/config.docker.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | |||||||
|  | aliyun-oss: | ||||||
|  |   endpoint: oss-cn-chengdu.aliyuncs.com | ||||||
|  |   access-key-id: LTAI5tFHes6HBWJFUjuPwHso | ||||||
|  |   access-key-secret: qXuWtEJvYEQvj9yhkmLYfRxHShheYa | ||||||
|  |   bucket-name: jmyl-app | ||||||
|  |   bucket-url: https://jmyl-app.oss-cn-chengdu.aliyuncs.com | ||||||
|  |   base-path: miniapp | ||||||
|  | autocode: | ||||||
|  |   server-model: /model/%s | ||||||
|  |   server-router: /router/%s | ||||||
|  |   server: /server.exe.exe | ||||||
|  |   server-api: /api/v1/%s | ||||||
|  |   server-plug: /plugin/%s | ||||||
|  |   server-initialize: /initialize | ||||||
|  |   root: C:\Users\Administrator\Desktop | ||||||
|  |   web-table: /view | ||||||
|  |   web: /web/src | ||||||
|  |   server-service: /service/%s | ||||||
|  |   server-request: /model/%s/request/ | ||||||
|  |   web-api: /api | ||||||
|  |   web-form: /view | ||||||
|  |   transfer-restart: true | ||||||
|  | captcha: | ||||||
|  |   key-long: 4 | ||||||
|  |   img-width: 240 | ||||||
|  |   img-height: 80 | ||||||
|  |   open-captcha: 0 | ||||||
|  |   open-captcha-timeout: 3600 | ||||||
|  | cors: | ||||||
|  |   mode: strict-whitelist | ||||||
|  |   whitelist: | ||||||
|  |     - allow-origin: example1.com | ||||||
|  |       allow-methods: POST, GET | ||||||
|  |       allow-headers: Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id | ||||||
|  |       expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type | ||||||
|  |       allow-credentials: true | ||||||
|  |     - allow-origin: example2.com | ||||||
|  |       allow-methods: GET, POST | ||||||
|  |       allow-headers: content-type | ||||||
|  |       expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type | ||||||
|  |       allow-credentials: true | ||||||
|  | db-list: | ||||||
|  |   - type: "" | ||||||
|  |     alias-name: "" | ||||||
|  |     prefix: "" | ||||||
|  |     port: "" | ||||||
|  |     config: "" | ||||||
|  |     db-name: "" | ||||||
|  |     username: "" | ||||||
|  |     password: "" | ||||||
|  |     path: "" | ||||||
|  |     engine: "" | ||||||
|  |     log-mode: "" | ||||||
|  |     max-idle-conns: 10 | ||||||
|  |     max-open-conns: 100 | ||||||
|  |     singular: false | ||||||
|  |     log-zap: false | ||||||
|  |     disable: true | ||||||
|  | email: | ||||||
|  |   to: xxx@qq.com | ||||||
|  |   from: xxx@163.com | ||||||
|  |   host: smtp.163.com | ||||||
|  |   secret: xxx | ||||||
|  |   nickname: test | ||||||
|  |   port: 465 | ||||||
|  |   is-ssl: true | ||||||
|  | excel: | ||||||
|  |   dir: ./resource/excel/ | ||||||
|  | jwt: | ||||||
|  |   signing-key: f2b1b2af-c8f1-43cf-88e4-40b0a64b5487 | ||||||
|  |   expires-time: 7d | ||||||
|  |   buffer-time: 1d | ||||||
|  |   issuer: qmPlus | ||||||
|  | local: | ||||||
|  |   path: uploads/file | ||||||
|  |   store-path: uploads/file | ||||||
|  | mini-app: | ||||||
|  |   app-id: wxaaf66dbb5c3983b3 | ||||||
|  |   app-secret: 0abba24dbff43febba1e551651f693b4 | ||||||
|  | mysql: | ||||||
|  |   prefix: "" | ||||||
|  |   port: "3307" | ||||||
|  |   config: charset=utf8mb4&parseTime=True&loc=Local | ||||||
|  |   db-name: mini_app | ||||||
|  |   username: root | ||||||
|  |   password: Jmyl123123 | ||||||
|  |   path: 47.113.103.195 | ||||||
|  |   engine: "" | ||||||
|  |   log-mode: error | ||||||
|  |   max-idle-conns: 10 | ||||||
|  |   max-open-conns: 100 | ||||||
|  |   singular: false | ||||||
|  |   log-zap: false | ||||||
|  | redis: | ||||||
|  |   addr: 127.0.0.1:6379 | ||||||
|  |   password: "Jmyl123123" | ||||||
|  |   db: 0 | ||||||
|  | system: | ||||||
|  |   env: public | ||||||
|  |   db-type: mysql | ||||||
|  |   oss-type: aliyun-oss | ||||||
|  |   router-prefix: "" | ||||||
|  |   addr: 8888 | ||||||
|  |   iplimit-count: 15000 | ||||||
|  |   iplimit-time: 3600 | ||||||
|  |   use-multipoint: false | ||||||
|  |   use-redis: true | ||||||
|  | timer: | ||||||
|  |   spec: '@daily' | ||||||
|  |   detail: | ||||||
|  |     - tableName: sys_operation_records | ||||||
|  |       compareField: created_at | ||||||
|  |       interval: 2160h | ||||||
|  |     - tableName: jwt_blacklists | ||||||
|  |       compareField: created_at | ||||||
|  |       interval: 168h | ||||||
|  |   start: true | ||||||
|  |   with_seconds: false | ||||||
|  | zap: | ||||||
|  |   level: info | ||||||
|  |   prefix: '[miniapp]' | ||||||
|  |   format: console | ||||||
|  |   director: log | ||||||
|  |   encode-level: LowercaseColorLevelEncoder | ||||||
|  |   stacktrace-key: stacktrace | ||||||
|  |   max-age: 0 | ||||||
|  |   show-line: true | ||||||
|  |   log-in-console: true | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								go.mod
									
									
									
									
									
								
							| @@ -15,13 +15,14 @@ require ( | |||||||
| 	github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 | 	github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 | ||||||
| 	github.com/gin-gonic/gin v1.9.1 | 	github.com/gin-gonic/gin v1.9.1 | ||||||
| 	github.com/glebarez/sqlite v1.8.0 | 	github.com/glebarez/sqlite v1.8.0 | ||||||
|  | 	github.com/go-co-op/gocron v1.13.0 | ||||||
| 	github.com/go-oauth2/oauth2/v4 v4.5.2 | 	github.com/go-oauth2/oauth2/v4 v4.5.2 | ||||||
| 	github.com/go-oauth2/redis/v4 v4.1.1 | 	github.com/go-oauth2/redis/v4 v4.1.1 | ||||||
| 	github.com/go-redis/redis/v8 v8.11.4 | 	github.com/go-redis/redis/v8 v8.11.4 | ||||||
| 	github.com/go-sql-driver/mysql v1.7.1 | 	github.com/go-sql-driver/mysql v1.7.1 | ||||||
| 	github.com/gofrs/uuid/v5 v5.0.0 | 	github.com/gofrs/uuid/v5 v5.0.0 | ||||||
| 	github.com/golang-jwt/jwt/v4 v4.5.0 | 	github.com/golang-jwt/jwt/v4 v4.5.0 | ||||||
| 	github.com/google/uuid v1.3.0 | 	github.com/google/uuid v1.6.0 | ||||||
| 	github.com/gookit/color v1.5.4 | 	github.com/gookit/color v1.5.4 | ||||||
| 	github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.8+incompatible | 	github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.8+incompatible | ||||||
| 	github.com/jordan-wright/email v0.0.0-20200824153738-3f5bafa1cd84 | 	github.com/jordan-wright/email v0.0.0-20200824153738-3f5bafa1cd84 | ||||||
| @@ -37,7 +38,7 @@ require ( | |||||||
| 	github.com/shirou/gopsutil/v3 v3.23.6 | 	github.com/shirou/gopsutil/v3 v3.23.6 | ||||||
| 	github.com/songzhibin97/gkit v1.2.11 | 	github.com/songzhibin97/gkit v1.2.11 | ||||||
| 	github.com/spf13/viper v1.16.0 | 	github.com/spf13/viper v1.16.0 | ||||||
| 	github.com/stretchr/testify v1.8.4 | 	github.com/stretchr/testify v1.9.0 | ||||||
| 	github.com/swaggo/files v1.0.1 | 	github.com/swaggo/files v1.0.1 | ||||||
| 	github.com/swaggo/gin-swagger v1.6.0 | 	github.com/swaggo/gin-swagger v1.6.0 | ||||||
| 	github.com/swaggo/swag v1.16.2 | 	github.com/swaggo/swag v1.16.2 | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								go.sum
									
									
									
									
									
								
							| @@ -137,6 +137,8 @@ github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0 | |||||||
| github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E= | github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E= | ||||||
| github.com/glebarez/sqlite v1.8.0 h1:02X12E2I/4C1n+v90yTqrjRa8yuo7c3KeHI3FRznCvc= | github.com/glebarez/sqlite v1.8.0 h1:02X12E2I/4C1n+v90yTqrjRa8yuo7c3KeHI3FRznCvc= | ||||||
| github.com/glebarez/sqlite v1.8.0/go.mod h1:bpET16h1za2KOOMb8+jCp6UBP/iahDpfPQqSaYLTLx8= | github.com/glebarez/sqlite v1.8.0/go.mod h1:bpET16h1za2KOOMb8+jCp6UBP/iahDpfPQqSaYLTLx8= | ||||||
|  | github.com/go-co-op/gocron v1.13.0 h1:BjkuNImPy5NuIPEifhWItFG7pYyr27cyjS6BN9w/D4c= | ||||||
|  | github.com/go-co-op/gocron v1.13.0/go.mod h1:GD5EIEly1YNW+LovFVx5dzbYVcIc8544K99D8UVRpGo= | ||||||
| github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= | ||||||
| github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | ||||||
| github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | ||||||
| @@ -264,8 +266,9 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu | |||||||
| github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= | ||||||
| github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||||
| github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||||
| github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= |  | ||||||
| github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||||
|  | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= | ||||||
|  | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||||
| github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= | ||||||
| github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= | ||||||
| github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= | github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= | ||||||
| @@ -467,8 +470,8 @@ github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= | |||||||
| github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= | github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= | ||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||||||
| github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= |  | ||||||
| github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | ||||||
|  | github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= | ||||||
| github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||||||
| github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||||
| github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | ||||||
| @@ -480,8 +483,9 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO | |||||||
| github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | ||||||
| github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | ||||||
| github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||||||
| github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= |  | ||||||
| github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||||||
|  | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | ||||||
|  | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||||
| github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= | github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= | ||||||
| github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= | github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= | ||||||
| github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= | github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= | ||||||
|   | |||||||
| @@ -1,11 +1,10 @@ | |||||||
| package initialize | package initialize | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	swaggerFiles "github.com/swaggo/files" |  | ||||||
| 	"net/http" |  | ||||||
|  |  | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
|  | 	swaggerFiles "github.com/swaggo/files" | ||||||
| 	ginSwagger "github.com/swaggo/gin-swagger" | 	ginSwagger "github.com/swaggo/gin-swagger" | ||||||
|  | 	"net/http" | ||||||
|  |  | ||||||
| 	"miniapp/global" | 	"miniapp/global" | ||||||
| 	"miniapp/middleware" | 	"miniapp/middleware" | ||||||
| @@ -31,7 +30,7 @@ func Routers() *gin.Engine { | |||||||
| 	Router.StaticFS(global.GVA_CONFIG.Local.StorePath, http.Dir(global.GVA_CONFIG.Local.StorePath)) // 为用户头像和文件提供静态地址 | 	Router.StaticFS(global.GVA_CONFIG.Local.StorePath, http.Dir(global.GVA_CONFIG.Local.StorePath)) // 为用户头像和文件提供静态地址 | ||||||
| 	// Router.Use(middleware.LoadTls())  // 如果需要使用https 请打开此中间件 然后前往 core/server.exe.exe.exe.go 将启动模式 更变为 Router.RunTLS("端口","你的cre/pem文件","你的key文件") | 	// Router.Use(middleware.LoadTls())  // 如果需要使用https 请打开此中间件 然后前往 core/server.exe.exe.exe.go 将启动模式 更变为 Router.RunTLS("端口","你的cre/pem文件","你的key文件") | ||||||
| 	// 跨域,如需跨域可以打开下面的注释 | 	// 跨域,如需跨域可以打开下面的注释 | ||||||
| 	// Router.Use(middleware.Cors()) // 直接放行全部跨域请求 | 	Router.Use(middleware.Cors()) // 直接放行全部跨域请求 | ||||||
| 	// Router.Use(middleware.CorsByRules()) // 按照配置的规则放行跨域请求 | 	// Router.Use(middleware.CorsByRules()) // 按照配置的规则放行跨域请求 | ||||||
| 	//global.GVA_LOG.Info("use middleware cors") | 	//global.GVA_LOG.Info("use middleware cors") | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.go
									
									
									
									
									
								
							| @@ -4,6 +4,7 @@ import ( | |||||||
| 	"go.uber.org/zap" | 	"go.uber.org/zap" | ||||||
| 	"miniapp/client" | 	"miniapp/client" | ||||||
| 	"miniapp/oauth2" | 	"miniapp/oauth2" | ||||||
|  | 	"miniapp/task" | ||||||
|  |  | ||||||
| 	"miniapp/core" | 	"miniapp/core" | ||||||
| 	"miniapp/global" | 	"miniapp/global" | ||||||
| @@ -41,5 +42,6 @@ func main() { | |||||||
| 	client.InitRedisClient() | 	client.InitRedisClient() | ||||||
| 	oauth2.InitOAuth2Server() // 初始化OAuth2服务 | 	oauth2.InitOAuth2Server() // 初始化OAuth2服务 | ||||||
| 	initialize.InitKp()       // 初始化关键词处理器 | 	initialize.InitKp()       // 初始化关键词处理器 | ||||||
|  | 	task.InitTask()           // 初始化定时任务 | ||||||
| 	core.RunWindowsServer() | 	core.RunWindowsServer() | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,9 +21,12 @@ type GetUserList struct { | |||||||
|  |  | ||||||
| // ChangeUserInfo 修改普通用户信息 | // ChangeUserInfo 修改普通用户信息 | ||||||
| type ChangeUserInfo struct { | type ChangeUserInfo struct { | ||||||
| 	Nickname string `json:"nickname" form:"nickname"` // 昵称 | 	Nickname    string `json:"nickname" form:"nickname"` // 昵称 | ||||||
| 	Avatar   string `json:"avatar" form:"avatar"`     // 头像 | 	Avatar      string `json:"avatar" form:"avatar"`     // 头像 | ||||||
| 	Phone    string `json:"phone" form:"phone"`       // 手机号 | 	Phone       string `json:"phone" form:"phone"`       // 手机号 | ||||||
|  | 	IsSurgery   int    `json:"isSurgery" gorm:"default:0;comment:是否已经手术 0未手术 1已手术"` | ||||||
|  | 	HospitalId  int    `json:"hospitalId" gorm:"comment:手术医院"` | ||||||
|  | 	SurgeryTime string `json:"surgery_time" gorm:"comment:手术时间"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // ChangePassword 修改密码 | // ChangePassword 修改密码 | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ type UserVO struct { | |||||||
| 	IsSurgery   int                 `json:"isSurgery" gorm:"default:0;comment:是否已经手术 0未手术 1已手术"` | 	IsSurgery   int                 `json:"isSurgery" gorm:"default:0;comment:是否已经手术 0未手术 1已手术"` | ||||||
| 	IsInfo      int                 `json:"isInfo" gorm:"default:0;comment:是否已经填写信息 0未填写 1已填写"` | 	IsInfo      int                 `json:"isInfo" gorm:"default:0;comment:是否已经填写信息 0未填写 1已填写"` | ||||||
| 	HospitalId  int                 `json:"hospital_id" gorm:"comment:手术医院"` | 	HospitalId  int                 `json:"hospital_id" gorm:"comment:手术医院"` | ||||||
| 	SurgeryTime time.Time           `json:"surgery_time" gorm:"comment:手术时间"` | 	SurgeryTime string              `json:"surgery_time" gorm:"comment:手术时间"` | ||||||
| 	Todos       []common.UserTodo   `json:"todos" gorm:"comment:用户待办事项"` | 	Todos       []common.UserTodo   `json:"todos" gorm:"comment:用户待办事项"` | ||||||
| 	Notes       []common.Notes      `json:"notes" gorm:"comment:用户须知"` | 	Notes       []common.Notes      `json:"notes" gorm:"comment:用户须知"` | ||||||
| } | } | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ type User struct { | |||||||
| 	IsSurgery     int                 `json:"isSurgery" gorm:"default:0;comment:是否已经手术 0未手术 1已手术"` | 	IsSurgery     int                 `json:"isSurgery" gorm:"default:0;comment:是否已经手术 0未手术 1已手术"` | ||||||
| 	IsInfo        int                 `json:"isInfo" gorm:"default:0;comment:是否已经填写信息 0未填写 1已填写"` | 	IsInfo        int                 `json:"isInfo" gorm:"default:0;comment:是否已经填写信息 0未填写 1已填写"` | ||||||
| 	HospitalId    int                 `json:"hospital_id" gorm:"comment:手术医院"` | 	HospitalId    int                 `json:"hospital_id" gorm:"comment:手术医院"` | ||||||
| 	SurgeryTime   time.Time           `json:"surgery_time" gorm:"comment:手术时间"` | 	SurgeryTime   string              `json:"surgery_time" gorm:"comment:手术时间"` | ||||||
| 	LastLoginAt   *time.Time          `json:"last_login_at" gorm:"comment:'最后登录时间'"` | 	LastLoginAt   *time.Time          `json:"last_login_at" gorm:"comment:'最后登录时间'"` | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,3 +4,10 @@ type GetUserNotes struct { | |||||||
| 	UserId   string `json:"userId" form:"userId" binding:"required"` | 	UserId   string `json:"userId" form:"userId" binding:"required"` | ||||||
| 	IsFinish string `json:"isFinish" form:"isFinish" binding:"required"` | 	IsFinish string `json:"isFinish" form:"isFinish" binding:"required"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type TodoTask struct { | ||||||
|  | 	OpenId     string `json:"openId" form:"openId"` | ||||||
|  | 	Context    string `json:"context" form:"context"` | ||||||
|  | 	Frequency  string `json:"frequency" form:"frequency"` | ||||||
|  | 	RemindTime string `json:"remindTime" form:"remindTime"` | ||||||
|  | } | ||||||
|   | |||||||
| @@ -5,7 +5,11 @@ import "miniapp/global" | |||||||
| type Todos struct { | type Todos struct { | ||||||
| 	// 任务列表 | 	// 任务列表 | ||||||
| 	global.GVA_MODEL | 	global.GVA_MODEL | ||||||
| 	Content string `json:"content" form:"content" gorm:"comment:任务内容;"` | 	Content      string `json:"content" form:"content" gorm:"comment:任务内容;"` | ||||||
|  | 	RemindTime   string `json:"remindTime" form:"remindTime" gorm:"comment:提醒时间;"` | ||||||
|  | 	RemindPeriod int    `json:"remindPeriod" form:"remindPeriod" gorm:"comment:0术前,1术后;"` | ||||||
|  | 	Frequency    string `json:"frequency" form:"frequency" gorm:"comment:用药频率;"` | ||||||
|  | 	RemindDay    string `json:"remindDay" form:"remindDay" gorm:"comment:提醒日期;"` | ||||||
| } | } | ||||||
|  |  | ||||||
| func (t Todos) TableName() string { | func (t Todos) TableName() string { | ||||||
|   | |||||||
| @@ -4,9 +4,13 @@ import "miniapp/global" | |||||||
|  |  | ||||||
| type UserTodo struct { | type UserTodo struct { | ||||||
| 	global.GVA_MODEL | 	global.GVA_MODEL | ||||||
| 	UserId   int    `json:"userId" form:"userId" gorm:"comment:用户id;"` | 	UserId       int    `json:"userId" form:"userId" gorm:"comment:用户id;"` | ||||||
| 	Content  string `json:"content" form:"content" gorm:"comment:任务内容;"` | 	Content      string `json:"content" form:"content" gorm:"comment:任务内容;"` | ||||||
| 	IsFinish int    `json:"isFinish" form:"isFinish" gorm:"comment:是否完成;"` | 	IsFinish     int    `json:"isFinish" form:"isFinish" gorm:"comment:是否完成;"` | ||||||
|  | 	RemindTime   string `json:"remindTime" form:"remindTime" gorm:"comment:提醒时间;"` | ||||||
|  | 	RemindPeriod int    `json:"remindPeriod" form:"remindPeriod" gorm:"comment:术前,术后;"` | ||||||
|  | 	Frequency    string `json:"frequency" form:"frequency" gorm:"comment:用药频率;"` | ||||||
|  | 	RemindDay    string `json:"remindDay" form:"remindDay" gorm:"comment:提醒日期;"` | ||||||
| } | } | ||||||
|  |  | ||||||
| func (u UserTodo) TableName() string { | func (u UserTodo) TableName() string { | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ type SysOperationRecord struct { | |||||||
| 	Path         string        `json:"path" form:"path" gorm:"column:path;comment:请求路径"`                             // 请求路径 | 	Path         string        `json:"path" form:"path" gorm:"column:path;comment:请求路径"`                             // 请求路径 | ||||||
| 	Status       int           `json:"status" form:"status" gorm:"column:status;comment:请求状态"`                       // 请求状态 | 	Status       int           `json:"status" form:"status" gorm:"column:status;comment:请求状态"`                       // 请求状态 | ||||||
| 	Latency      time.Duration `json:"latency" form:"latency" gorm:"column:latency;comment:延迟" swaggertype:"string"` // 延迟 | 	Latency      time.Duration `json:"latency" form:"latency" gorm:"column:latency;comment:延迟" swaggertype:"string"` // 延迟 | ||||||
| 	Agent        string        `json:"agent" form:"agent" gorm:"column:agent;comment:代理"`                            // 代理 | 	Agent        string        `json:"agent" form:"agent" gorm:"column:agent; type:longtext; comment:代理"`            // 代理 | ||||||
| 	ErrorMessage string        `json:"error_message" form:"error_message" gorm:"column:error_message;comment:错误信息"`  // 错误信息 | 	ErrorMessage string        `json:"error_message" form:"error_message" gorm:"column:error_message;comment:错误信息"`  // 错误信息 | ||||||
| 	Body         string        `json:"body" form:"body" gorm:"type:text;column:body;comment:请求Body"`                 // 请求Body | 	Body         string        `json:"body" form:"body" gorm:"type:text;column:body;comment:请求Body"`                 // 请求Body | ||||||
| 	Resp         string        `json:"resp" form:"resp" gorm:"type:text;column:resp;comment:响应Body"`                 // 响应Body | 	Resp         string        `json:"resp" form:"resp" gorm:"type:text;column:resp;comment:响应Body"`                 // 响应Body | ||||||
|   | |||||||
| @@ -116,6 +116,9 @@ func ExtensionFields(ti oauth2.TokenInfo) (fieldsValue map[string]any) { | |||||||
| 	fieldsValue["IsSurgery"] = userInfo.IsSurgery | 	fieldsValue["IsSurgery"] = userInfo.IsSurgery | ||||||
| 	fieldsValue["HospitalId"] = userInfo.HospitalId | 	fieldsValue["HospitalId"] = userInfo.HospitalId | ||||||
| 	fieldsValue["IsInfo"] = userInfo.IsInfo | 	fieldsValue["IsInfo"] = userInfo.IsInfo | ||||||
|  | 	fieldsValue["SurgeryTime"] = userInfo.SurgeryTime | ||||||
|  | 	fieldsValue["HospitalId"] = userInfo.HospitalId | ||||||
|  | 	fieldsValue["IsSurgery"] = userInfo.IsSurgery | ||||||
|  |  | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|   | |||||||
| @@ -25,6 +25,7 @@ func (s *LoginRouter) InitUserRouter(Router *gin.RouterGroup) { | |||||||
| 		userRouter.GET("todo", todoApi.GetUserTodos) | 		userRouter.GET("todo", todoApi.GetUserTodos) | ||||||
| 		userRouter.PUT("todo", todoApi.UpdateTodo) | 		userRouter.PUT("todo", todoApi.UpdateTodo) | ||||||
|  |  | ||||||
|  | 		userRouter.POST("msg", baseApi.SendMedicineRemind) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ import ( | |||||||
| 	"miniapp/model/app/request" | 	"miniapp/model/app/request" | ||||||
| 	"miniapp/model/app/response" | 	"miniapp/model/app/response" | ||||||
| 	"miniapp/model/common" | 	"miniapp/model/common" | ||||||
|  | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -49,7 +50,53 @@ func (UserService) CheckUnionIdIsExist(unionId, openId string) bool { | |||||||
|  |  | ||||||
| // UpdateUserInfo 更新普通用户信息 | // UpdateUserInfo 更新普通用户信息 | ||||||
| func (UserService) UpdateUserInfo(e *app.User) (err error) { | func (UserService) UpdateUserInfo(e *app.User) (err error) { | ||||||
| 	return global.GVA_DB.Updates(&e).Error | 	tUser := app.User{} | ||||||
|  | 	err = global.GVA_DB.Where("id = ?", e.ID).First(&tUser).Error | ||||||
|  |  | ||||||
|  | 	err = global.GVA_DB.Updates(&e).Error | ||||||
|  | 	if err != nil { | ||||||
|  | 		global.GVA_LOG.Error("更新用户信息失败", zap.Error(err)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if e.SurgeryTime != "" { | ||||||
|  | 		if tUser.HospitalId != e.HospitalId { | ||||||
|  |  | ||||||
|  | 			err = global.GVA_DB.Delete(&common.UserTodo{}, "user_id = ?", e.ID).Error | ||||||
|  | 			if err != nil { | ||||||
|  | 				global.GVA_LOG.Error("清除用户Todo列表失败", zap.Error(err)) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			var hospital common.Hospital | ||||||
|  | 			err = global.GVA_DB.Where("id = ?", e.HospitalId).Preload("Todos").First(&hospital).Error | ||||||
|  | 			if err != nil { | ||||||
|  | 				global.GVA_LOG.Error("获取医院信息失败", zap.Error(err)) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if len(hospital.Todos) != 0 { | ||||||
|  | 				var userTodos []common.UserTodo | ||||||
|  | 				for _, todo := range hospital.Todos { | ||||||
|  | 					for _, s := range strings.Split(todo.RemindTime, ",") { | ||||||
|  | 						userTodos = append(userTodos, common.UserTodo{ | ||||||
|  | 							Content:      todo.Content, | ||||||
|  | 							UserId:       int(e.ID), | ||||||
|  | 							IsFinish:     0, | ||||||
|  | 							RemindTime:   s, | ||||||
|  | 							RemindPeriod: todo.RemindPeriod, | ||||||
|  | 						}) | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				err = global.GVA_DB.Create(&userTodos).Error | ||||||
|  | 				if err != nil { | ||||||
|  | 					global.GVA_LOG.Error("创建用户Todo列表失败", zap.Error(err)) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| // GetAverageUserList 查询普通用户列表 | // GetAverageUserList 查询普通用户列表 | ||||||
| @@ -126,11 +173,15 @@ func (UserService) UpdateUserHospital(r *request.ChangeUserHospital) (err error) | |||||||
| 	if len(hospital.Todos) != 0 { | 	if len(hospital.Todos) != 0 { | ||||||
| 		var userTodos []common.UserTodo | 		var userTodos []common.UserTodo | ||||||
| 		for _, todo := range hospital.Todos { | 		for _, todo := range hospital.Todos { | ||||||
| 			userTodos = append(userTodos, common.UserTodo{ | 			for _, s := range strings.Split(todo.RemindTime, ",") { | ||||||
| 				Content:  todo.Content, | 				userTodos = append(userTodos, common.UserTodo{ | ||||||
| 				UserId:   r.UserId, | 					Content:      todo.Content, | ||||||
| 				IsFinish: 0, | 					UserId:       r.UserId, | ||||||
| 			}) | 					IsFinish:     0, | ||||||
|  | 					RemindTime:   s, | ||||||
|  | 					RemindPeriod: todo.RemindPeriod, | ||||||
|  | 				}) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		err = global.GVA_DB.Create(&userTodos).Error | 		err = global.GVA_DB.Create(&userTodos).Error | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| @@ -139,9 +190,9 @@ func (UserService) UpdateUserHospital(r *request.ChangeUserHospital) (err error) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	t, _ := time.Parse("2006-01-02", r.SurgeryTime) | 	//t, _ := time.Parse("2006-01-02", r.SurgeryTime) | ||||||
|  |  | ||||||
| 	err = global.GVA_DB.Table("t_user").Where("id = ?", r.UserId).Updates(app.User{IsInfo: 1, HospitalId: r.HospitalId, SurgeryTime: t}).Error | 	err = global.GVA_DB.Table("t_user").Where("id = ?", r.UserId).Updates(app.User{IsInfo: 1, HospitalId: r.HospitalId, SurgeryTime: r.SurgeryTime}).Error | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		global.GVA_LOG.Error("更新用户信息失败", zap.Error(err)) | 		global.GVA_LOG.Error("更新用户信息失败", zap.Error(err)) | ||||||
| 		return | 		return | ||||||
|   | |||||||
| @@ -23,12 +23,48 @@ func (h HospitalService) CreateHospital(hospital *common.Hospital) (err error) { | |||||||
|  |  | ||||||
| // UpdateHospital 更新医院 | // UpdateHospital 更新医院 | ||||||
| func (h HospitalService) UpdateHospital(hospital *common.Hospital) (err error) { | func (h HospitalService) UpdateHospital(hospital *common.Hospital) (err error) { | ||||||
| 	return global.GVA_DB.Updates(&hospital).Error | 	for i := range hospital.Notes { | ||||||
|  | 		if hospital.Notes[i].NotesTime == "手术前" { | ||||||
|  | 			hospital.Notes[i].NotestimeNum = 1 | ||||||
|  | 		} else if hospital.Notes[i].NotesTime == "手术中" { | ||||||
|  | 			hospital.Notes[i].NotestimeNum = 2 | ||||||
|  | 		} else { | ||||||
|  | 			hospital.Notes[i].NotestimeNum = 3 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	err = global.GVA_DB.Model(&common.Notes{}).Save(&hospital.Notes).Error | ||||||
|  | 	if err != nil { | ||||||
|  | 		global.GVA_LOG.Error("更新医院注意事项失败", zap.Error(err)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	err = global.GVA_DB.Model(&hospital).Association("Notes").Replace(&hospital.Notes) | ||||||
|  | 	if err != nil { | ||||||
|  | 		global.GVA_LOG.Error("更新医院注意事项失败", zap.Error(err)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = global.GVA_DB.Model(&common.Todos{}).Save(&hospital.Todos).Error | ||||||
|  | 	if err != nil { | ||||||
|  | 		global.GVA_LOG.Error("更新医院Todo失败", zap.Error(err)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	err = global.GVA_DB.Model(&hospital).Association("Todos").Replace(&hospital.Todos) | ||||||
|  | 	if err != nil { | ||||||
|  | 		global.GVA_LOG.Error("更新医院Todo关联失败", zap.Error(err)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return global.GVA_DB.Save(&hospital).Error | ||||||
| } | } | ||||||
|  |  | ||||||
| // DeleteHospital 删除医院 | // DeleteHospital 删除医院 | ||||||
| func (h HospitalService) DeleteHospital(hospital *common.Hospital) (err error) { | func (h HospitalService) DeleteHospital(hospital *common.Hospital) (err error) { | ||||||
| 	return global.GVA_DB.Select("Notes").Delete(&hospital).Error | 	err = global.GVA_DB.Model(&hospital).Association("Notes").Clear() | ||||||
|  | 	err = global.GVA_DB.Model(&hospital).Association("Todos").Clear() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return global.GVA_DB.Delete(&hospital).Error | ||||||
| } | } | ||||||
|  |  | ||||||
| // GetHospitalById 根据id获取医院 | // GetHospitalById 根据id获取医院 | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								task/task.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								task/task.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | package task | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/go-co-op/gocron" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var WxTask *gocron.Scheduler | ||||||
|  |  | ||||||
|  | func InitTask() { | ||||||
|  | 	WxTask = gocron.NewScheduler(time.Local) | ||||||
|  |  | ||||||
|  | 	// 每天凌晨1点执行 | ||||||
|  | 	_, _ = WxTask.Every(1).Day().At("01:00").Do(CheckUserSurgeryDate) // 检查用户是否已到手术日期 | ||||||
|  |  | ||||||
|  | 	// 开启定时任务 | ||||||
|  | 	WxTask.StartAsync() | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								task/user.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								task/user.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | package task | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"miniapp/global" | ||||||
|  | 	"miniapp/model/app" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // CheckUserSurgeryDate 检查用户是否已到手术日期 | ||||||
|  | func CheckUserSurgeryDate() { | ||||||
|  | 	var users []app.User | ||||||
|  | 	global.GVA_DB.Model(&app.User{}).Find(&users) | ||||||
|  | 	for _, user := range users { | ||||||
|  | 		parse, _ := time.Parse("2006-01-02", user.SurgeryTime) | ||||||
|  | 		if time.Now().Sub(parse).Hours()/24 == 0 { | ||||||
|  | 			global.GVA_DB.Model(&app.User{}).Where("id = ?", user.ID).Updates(app.User{IsSurgery: 1}) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										83
									
								
								task/wxMsg.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								task/wxMsg.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | |||||||
|  | package task | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/medivhzhan/weapp/v3" | ||||||
|  | 	msg "github.com/medivhzhan/weapp/v3/subscribemessage" | ||||||
|  | 	"go.uber.org/zap" | ||||||
|  | 	"miniapp/global" | ||||||
|  | 	"miniapp/model/app" | ||||||
|  | 	"miniapp/model/common" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func SendMsg(userId int) { | ||||||
|  | 	var user app.User | ||||||
|  | 	err := global.GVA_DB.Model(&user).Where("id = ?", userId).Find(&user).Error | ||||||
|  | 	if err != nil { | ||||||
|  | 		global.GVA_LOG.Error("获取用户信息失败:%s", zap.Error(err)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// 获取用户待办列表 | ||||||
|  | 	var userTodo []common.UserTodo | ||||||
|  | 	if user.IsSurgery == 0 { | ||||||
|  | 		err = global.GVA_DB.Model(&userTodo).Where("user_id = ? and is_finish = ? and remind_period = 0", userId, 0).Find(&userTodo).Error | ||||||
|  | 		if err != nil { | ||||||
|  | 			global.GVA_LOG.Error("获取用户待办列表:%s", zap.Error(err)) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		err = global.GVA_DB.Model(&userTodo).Where("user_id = ? and is_finish = ? and remind_period = 1", userId, 0).Find(&userTodo).Error | ||||||
|  | 		if err != nil { | ||||||
|  | 			global.GVA_LOG.Error("获取用户待办列表:%s", zap.Error(err)) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// 根据用户手术信息 发送提醒消息 | ||||||
|  | 	parse, _ := time.Parse("2006-01-02", user.SurgeryTime) | ||||||
|  | 	if time.Now().Sub(parse).Hours()/24 <= -3 { | ||||||
|  | 		for _, todo := range userTodo { | ||||||
|  | 			jbo, _ := WxTask.Every(1).Day().At(todo.RemindTime).Do(MiniappSendMsg, *user.WechatOpenId, todo.Content, todo.RemindPeriod, todo.RemindTime) // 检查用户待办事项 | ||||||
|  | 			s := strings.Split("一天3次", "")[2] | ||||||
|  | 			// 将s转为int类型 | ||||||
|  | 			atoi, _ := strconv.Atoi(s) | ||||||
|  | 			if jbo.RunCount() == atoi { | ||||||
|  | 				WxTask.Remove(jbo) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func MiniappSendMsg(openId string, context string, frequency string, remindTime string) { | ||||||
|  | 	sdk := weapp.NewClient(global.GVA_CONFIG.MiniApp.AppId, global.GVA_CONFIG.MiniApp.AppSecret) | ||||||
|  |  | ||||||
|  | 	msgData := msg.SendRequest{ | ||||||
|  | 		ToUser:           openId, | ||||||
|  | 		TemplateID:       "PgxoZOOSDgBcmIGd_EVLDnYUmL3eu6NQTAZCsHQeuWY", | ||||||
|  | 		Page:             "/page/index/todo", | ||||||
|  | 		MiniprogramState: msg.MiniprogramStateTrial, | ||||||
|  | 		Data: msg.SendData{ | ||||||
|  | 			"thing1":        msg.SendValue{Value: context}, | ||||||
|  | 			"time2":         msg.SendValue{Value: remindTime}, | ||||||
|  | 			"short_thing17": msg.SendValue{Value: frequency}, | ||||||
|  | 			"time15":        msg.SendValue{Value: time.DateTime}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	send, err := sdk.NewSubscribeMessage().Send(&msgData) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = send.GetResponseError() | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Printf("微信返回错误: %#v", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Printf("返回结果: %#v", send) | ||||||
|  | } | ||||||
							
								
								
									
										190
									
								
								utils/wx_msg.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								utils/wx_msg.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | |||||||
|  | package utils | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"crypto/sha1" | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/pkg/errors" | ||||||
|  | 	"miniapp/global" | ||||||
|  | 	"net/http" | ||||||
|  | 	"net/url" | ||||||
|  | 	"sort" | ||||||
|  | 	"strings" | ||||||
|  | 	"sync" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | //type wxMsg struct{} | ||||||
|  | // | ||||||
|  | //func WxMsgUtils() *wxMsg { | ||||||
|  | //	return &wxMsg{} | ||||||
|  | //} | ||||||
|  |  | ||||||
|  | type Wechat struct { | ||||||
|  | 	appID       string | ||||||
|  | 	secret      string | ||||||
|  | 	templateID  string | ||||||
|  | 	accessToken *AccessToken | ||||||
|  | 	sync.Mutex | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type OpenIDResponse struct { | ||||||
|  | 	Openid     string `json:"openid"` | ||||||
|  | 	SessionKey string `json:"session_key"` | ||||||
|  | 	Unionid    string `json:"unionid"` | ||||||
|  | 	WxErr | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type CheckTokenRequest struct { | ||||||
|  | 	Signature string `json:"signature"` | ||||||
|  | 	Timestamp string `json:"timestamp"` | ||||||
|  | 	Nonce     string `json:"nonce"` | ||||||
|  | 	Echostr   string `json:"echostr"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type WxErr struct { | ||||||
|  | 	Errcode int    `json:"errcode"` | ||||||
|  | 	Errmsg  string `json:"errmsg"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type AccessToken struct { | ||||||
|  | 	AccessToken string `json:"access_token"` | ||||||
|  | 	ExpiresIn   int64  `json:"expires_in"` | ||||||
|  | 	WxErr | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type SendRequest struct { | ||||||
|  | 	Touser          string  `json:"touser"` | ||||||
|  | 	Page            string  `json:"page"` | ||||||
|  | 	Data            Message `json:"data"` | ||||||
|  | 	EmphasisKeyword string  `json:"emphasis_keyword"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Message map[string]interface{} | ||||||
|  |  | ||||||
|  | func (w *Wechat) SendMsg(req SendRequest) (err error) { | ||||||
|  | 	token, err := w.GetAccessToken() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	api, err := TokenAPI("https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send", token) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	for key := range req.Data { | ||||||
|  | 		req.Data[key] = Message{"value": req.Data[key]} | ||||||
|  | 	} | ||||||
|  | 	body := map[string]interface{}{ | ||||||
|  | 		"touser":           "o9Fq_6_cYKvOWnyUM3McC11hWsTI", | ||||||
|  | 		"template_id":      global.GVA_CONFIG.MiniApp.TemplateID, | ||||||
|  | 		"page":             "/pages/index/todo", | ||||||
|  | 		"data":             req.Data, | ||||||
|  | 		"emphasis_keyword": req.EmphasisKeyword, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	b, err := json.Marshal(body) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	res, err := http.Post(api, "application/json", strings.NewReader(string(b))) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer res.Body.Close() | ||||||
|  |  | ||||||
|  | 	if res.StatusCode != 200 { | ||||||
|  | 		err = errors.New("WECHAT_SERVER_ERROR") | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var resp WxErr | ||||||
|  | 	if err = json.NewDecoder(res.Body).Decode(&resp); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if resp.Errcode != 0 { | ||||||
|  | 		return errors.New(resp.Errmsg) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (w *Wechat) GetAccessToken() (token string, err error) { | ||||||
|  | 	w.Lock() | ||||||
|  | 	defer w.Unlock() | ||||||
|  | 	if w.accessToken == nil || w.accessToken.ExpiresIn < time.Now().Unix() { | ||||||
|  | 		for i := 0; i < 3; i++ { | ||||||
|  | 			err = w.getAccessToken() | ||||||
|  | 			if err == nil { | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 			time.Sleep(time.Second) | ||||||
|  | 		} | ||||||
|  | 		if err != nil { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	token = w.accessToken.AccessToken | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (w *Wechat) CheckSignature(req CheckTokenRequest) (err error) { | ||||||
|  | 	if sig := w.sortSha1(req.Timestamp, req.Nonce, req.Echostr); sig != req.Signature { | ||||||
|  | 		err = errors.New("check signature failed.") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TokenAPI(api, token string) (string, error) { | ||||||
|  | 	u, err := url.Parse(api) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	query := u.Query() | ||||||
|  | 	query.Set("access_token", token) | ||||||
|  | 	u.RawQuery = query.Encode() | ||||||
|  |  | ||||||
|  | 	return u.String(), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (w *Wechat) getAccessToken() (err error) { | ||||||
|  | 	urls, err := url.Parse("https://api.weixin.qq.com/cgi-bin/token") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	query := urls.Query() | ||||||
|  | 	query.Set("appid", w.appID) | ||||||
|  | 	query.Set("secret", w.secret) | ||||||
|  | 	query.Set("grant_type", "client_credential") | ||||||
|  |  | ||||||
|  | 	urls.RawQuery = query.Encode() | ||||||
|  |  | ||||||
|  | 	res, err := http.Get(urls.String()) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	defer res.Body.Close() | ||||||
|  |  | ||||||
|  | 	if res.StatusCode != 200 { | ||||||
|  | 		return errors.New("wechat internal server error.") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var token AccessToken | ||||||
|  | 	if err = json.NewDecoder(res.Body).Decode(&token); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if token.Errcode != 0 { | ||||||
|  | 		return errors.New(token.Errmsg) | ||||||
|  | 	} | ||||||
|  | 	w.accessToken.AccessToken = token.AccessToken | ||||||
|  | 	w.accessToken.ExpiresIn = token.ExpiresIn | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (w *Wechat) sortSha1(s ...string) string { | ||||||
|  | 	sort.Strings(s) | ||||||
|  | 	h := sha1.New() | ||||||
|  | 	h.Write([]byte(strings.Join(s, ""))) | ||||||
|  | 	return fmt.Sprintf("%x", h.Sum(nil)) | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user