From 812db10a6aea48edb3c849a466c92508ec20374c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=87=E6=AD=A6?= <875892894@qq.com> Date: Thu, 1 Aug 2024 12:48:04 +0800 Subject: [PATCH] init --- .gitignore | 18 + Dockerfile | 8 + Makefile | 67 + README.md | 3 +- api/global/dict.go | 40 + api/global/global.go | 151 + api/influencer/banner.go | 33 + api/influencer/chain.go | 36 + api/influencer/mission.go | 354 +++ api/influencer/order.go | 162 + api/influencer/tb_goods.go | 29 + api/influencer/tools.go | 76 + api/influencer/user.go | 356 +++ api/influencer/wallet.go | 347 +++ api/sys/sys_brochure.go | 42 + api/sys/sys_user.go | 50 + api/sys/version.go | 30 + config-prod.yaml | 122 + config.yaml | 122 + config/auto_code.go | 1 + config/captcha.go | 7 + config/casbin.go | 5 + config/config.go | 23 + config/dysmsapi.go | 11 + config/email.go | 11 + config/excel.go | 2 + config/gorm.go | 21 + config/gorm_settings.go | 10 + config/jpush.go | 8 + config/jwt.go | 7 + config/minio.go | 2 + config/oss.go | 31 + config/paypal.go | 11 + config/redis.go | 7 + config/system.go | 9 + config/timer.go | 13 + config/tools.go | 5 + config/zap.go | 13 + core/server.go | 38 + core/server_other.go | 17 + core/server_win.go | 19 + core/viper.go | 56 + core/zap.go | 103 + docs/docs.go | 4378 +++++++++++++++++++++++++++ docs/swagger.json | 4354 ++++++++++++++++++++++++++ docs/swagger.yaml | 2897 ++++++++++++++++++ dto/customer.pb.go | 820 +++++ dto/customer.proto | 60 + global/global.go | 25 + global/model.go | 56 + go.mod | 118 + go.sum | 781 +++++ initialize/api/email.pb.go | 253 ++ initialize/api/email.proto | 32 + initialize/api/email_grpc.pb.go | 111 + initialize/api/greeter.pb.go | 1429 +++++++++ initialize/api/greeter.proto | 126 + initialize/api/greeter_grpc.pb.go | 432 +++ initialize/api/sms.pb.go | 329 ++ initialize/api/sms.proto | 47 + initialize/api/sms_grpc.pb.go | 150 + initialize/gorm.go | 110 + initialize/grpc.go | 89 + initialize/internal/gorm.go | 52 + initialize/internal/logger.go | 33 + initialize/international.go | 24 + initialize/redis.go | 44 + initialize/router.go | 53 + initialize/timer.go | 23 + initialize/validator.go | 22 + main.go | 36 + middleware/Ijwt.go | 132 + middleware/cors.go | 26 + middleware/error.go | 61 + middleware/jwt.go | 203 ++ middleware/loadtls.go | 26 + middleware/need_init.go | 23 + middleware/params.go | 50 + model/account.go | 29 + model/address.go | 22 + model/application.go | 21 + model/banner.go | 22 + model/base.go | 9 + model/bill.go | 51 + model/bill_fund.go | 22 + model/collectiom_goods.go | 13 + model/collection_mission.go | 13 + model/dict.go | 49 + model/dt_statistic_order.go | 26 + model/goods_visit.go | 14 + model/internationalization.go | 13 + model/mission.go | 98 + model/mission_claim.go | 49 + model/mission_claim_address.go | 12 + model/mission_claim_order.go | 43 + model/mission_claim_order_goods.go | 17 + model/mission_claim_video.go | 37 + model/mission_claim_works.go | 17 + model/mission_recommend.go | 27 + model/notify.go | 16 + model/order.go | 69 + model/order_address.go | 12 + model/order_deliver.go | 27 + model/order_goods.go | 26 + model/order_goods_specs.go | 30 + model/order_post_sale.go | 42 + model/paypalWebhook.go | 21 + model/platform_auth.go | 22 + model/provider.go | 60 + model/request/account.go | 21 + model/request/address.go | 7 + model/request/bill.go | 16 + model/request/chain.go | 5 + model/request/collection_mission.go | 9 + model/request/common.go | 56 + model/request/dict.go | 5 + model/request/jwt.go | 19 + model/request/mission.go | 67 + model/request/notify.go | 6 + model/request/order.go | 42 + model/request/othor.go | 11 + model/request/sys_brochure.go | 5 + model/request/tb_goods.go | 15 + model/request/user.go | 57 + model/request/wallet.go | 24 + model/response/banner.go | 16 + model/response/chain.go | 10 + model/response/common.go | 19 + model/response/mission.go | 116 + model/response/paypalOrder.go | 843 ++++++ model/response/response.go | 86 + model/response/tripartite.go | 26 + model/response/user.go | 25 + model/seller_store.go | 26 + model/sys_brochure.go | 16 + model/sys_jwt_blacklist.go | 8 + model/sys_mission_reward.go | 28 + model/tag_relation.go | 26 + model/tags.go | 26 + model/tb_attribute.go | 41 + model/tb_attribute_value.go | 25 + model/tb_category.go | 15 + model/tb_goods.go | 103 + model/tb_goods_specs.go | 42 + model/track.go | 28 + model/track_webhook.go | 12 + model/us_citys.go | 12 + model/us_states.go | 18 + model/user.go | 64 + model/version.go | 32 + model/wallet.go | 18 + model/webhook.go | 12 + model/withdrawal.go | 32 + openapi.yaml | 10 + packfile/notUsePackFile.go | 3 + packfile/usePackFile.go | 45 + resource/gorm_settings.yaml | 25 + resource/rbac_model.conf | 14 + router/global/dict.go | 13 + router/global/global.go | 19 + router/influencer/base.go | 25 + router/influencer/goods.go | 13 + router/influencer/mission.go | 36 + router/influencer/order.go | 18 + router/influencer/user.go | 19 + router/influencer/wallet.go | 28 + service/address.go | 181 ++ service/banner.go | 41 + service/bill.go | 157 + service/chain.go | 28 + service/collectiom_goods.go | 85 + service/collection_mission.go | 305 ++ service/dict.go | 56 + service/jwt_black_list.go | 53 + service/mission.go | 778 +++++ service/notify.go | 24 + service/order.go | 459 +++ service/redis_tools.go | 355 +++ service/seller_store.go | 24 + service/sys_brochure.go | 11 + service/sys_mission_reward.go | 133 + service/tags.go | 49 + service/tb_category.go | 48 + service/tb_goods.go | 146 + service/user.go | 868 ++++++ service/version.go | 58 + service/wallet.go | 281 ++ service/withdrawal.go | 27 + tests/Makefile | 69 + tests/api/recommender.proto | 30 + tests/grpc.go | 1 + tests/grpc_test.go | 1 + tests/openapi.yaml | 10 + utils/array.go | 19 + utils/breakpoint_continue.go | 102 + utils/constant.go | 6 + utils/cors.go | 17 + utils/db_automation.go | 28 + utils/directory.go | 46 + utils/email.go | 78 + utils/file_operations.go | 63 + utils/float.go | 28 + utils/fmt_plus.go | 36 + utils/injectionCode.go | 142 + utils/international.go | 32 + utils/jpush/model.go | 23 + utils/jpush/push.go | 202 ++ utils/md5.go | 17 + utils/qiniu/model.go | 83 + utils/qiniu/video.go | 84 + utils/redis.go | 321 ++ utils/redis_store.go | 44 + utils/reload.go | 18 + utils/rotatelogs_unix.go | 30 + utils/rotatelogs_windows.go | 26 + utils/sendSms.go | 109 + utils/server.go | 113 + utils/string.go | 69 + utils/time.go | 13 + utils/timer/timed_task.go | 109 + utils/upload/aliyun_oss.go | 75 + utils/upload/local.go | 79 + utils/upload/minio.go | 123 + utils/upload/tencent_cos.go | 60 + utils/validator.go | 368 +++ utils/verify.go | 27 + utils/zipfiles.go | 71 + webhook.json | 546 ++++ 228 files changed, 30651 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 api/global/dict.go create mode 100644 api/global/global.go create mode 100644 api/influencer/banner.go create mode 100644 api/influencer/chain.go create mode 100644 api/influencer/mission.go create mode 100644 api/influencer/order.go create mode 100644 api/influencer/tb_goods.go create mode 100644 api/influencer/tools.go create mode 100644 api/influencer/user.go create mode 100644 api/influencer/wallet.go create mode 100644 api/sys/sys_brochure.go create mode 100644 api/sys/sys_user.go create mode 100644 api/sys/version.go create mode 100644 config-prod.yaml create mode 100644 config.yaml create mode 100644 config/auto_code.go create mode 100644 config/captcha.go create mode 100644 config/casbin.go create mode 100644 config/config.go create mode 100644 config/dysmsapi.go create mode 100644 config/email.go create mode 100644 config/excel.go create mode 100644 config/gorm.go create mode 100644 config/gorm_settings.go create mode 100644 config/jpush.go create mode 100644 config/jwt.go create mode 100644 config/minio.go create mode 100644 config/oss.go create mode 100644 config/paypal.go create mode 100644 config/redis.go create mode 100644 config/system.go create mode 100644 config/timer.go create mode 100644 config/tools.go create mode 100644 config/zap.go create mode 100644 core/server.go create mode 100644 core/server_other.go create mode 100644 core/server_win.go create mode 100644 core/viper.go create mode 100644 core/zap.go create mode 100644 docs/docs.go create mode 100644 docs/swagger.json create mode 100644 docs/swagger.yaml create mode 100644 dto/customer.pb.go create mode 100644 dto/customer.proto create mode 100644 global/global.go create mode 100644 global/model.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 initialize/api/email.pb.go create mode 100644 initialize/api/email.proto create mode 100644 initialize/api/email_grpc.pb.go create mode 100644 initialize/api/greeter.pb.go create mode 100644 initialize/api/greeter.proto create mode 100644 initialize/api/greeter_grpc.pb.go create mode 100644 initialize/api/sms.pb.go create mode 100644 initialize/api/sms.proto create mode 100644 initialize/api/sms_grpc.pb.go create mode 100644 initialize/gorm.go create mode 100644 initialize/grpc.go create mode 100644 initialize/internal/gorm.go create mode 100644 initialize/internal/logger.go create mode 100644 initialize/international.go create mode 100644 initialize/redis.go create mode 100644 initialize/router.go create mode 100644 initialize/timer.go create mode 100644 initialize/validator.go create mode 100644 main.go create mode 100644 middleware/Ijwt.go create mode 100644 middleware/cors.go create mode 100644 middleware/error.go create mode 100644 middleware/jwt.go create mode 100644 middleware/loadtls.go create mode 100644 middleware/need_init.go create mode 100644 middleware/params.go create mode 100644 model/account.go create mode 100644 model/address.go create mode 100755 model/application.go create mode 100644 model/banner.go create mode 100644 model/base.go create mode 100644 model/bill.go create mode 100644 model/bill_fund.go create mode 100644 model/collectiom_goods.go create mode 100644 model/collection_mission.go create mode 100644 model/dict.go create mode 100644 model/dt_statistic_order.go create mode 100644 model/goods_visit.go create mode 100644 model/internationalization.go create mode 100644 model/mission.go create mode 100644 model/mission_claim.go create mode 100644 model/mission_claim_address.go create mode 100644 model/mission_claim_order.go create mode 100644 model/mission_claim_order_goods.go create mode 100644 model/mission_claim_video.go create mode 100644 model/mission_claim_works.go create mode 100644 model/mission_recommend.go create mode 100644 model/notify.go create mode 100644 model/order.go create mode 100644 model/order_address.go create mode 100644 model/order_deliver.go create mode 100644 model/order_goods.go create mode 100644 model/order_goods_specs.go create mode 100644 model/order_post_sale.go create mode 100644 model/paypalWebhook.go create mode 100644 model/platform_auth.go create mode 100755 model/provider.go create mode 100644 model/request/account.go create mode 100644 model/request/address.go create mode 100644 model/request/bill.go create mode 100644 model/request/chain.go create mode 100644 model/request/collection_mission.go create mode 100644 model/request/common.go create mode 100644 model/request/dict.go create mode 100644 model/request/jwt.go create mode 100644 model/request/mission.go create mode 100644 model/request/notify.go create mode 100644 model/request/order.go create mode 100644 model/request/othor.go create mode 100644 model/request/sys_brochure.go create mode 100644 model/request/tb_goods.go create mode 100644 model/request/user.go create mode 100644 model/request/wallet.go create mode 100644 model/response/banner.go create mode 100644 model/response/chain.go create mode 100644 model/response/common.go create mode 100644 model/response/mission.go create mode 100644 model/response/paypalOrder.go create mode 100644 model/response/response.go create mode 100644 model/response/tripartite.go create mode 100755 model/response/user.go create mode 100644 model/seller_store.go create mode 100644 model/sys_brochure.go create mode 100755 model/sys_jwt_blacklist.go create mode 100644 model/sys_mission_reward.go create mode 100644 model/tag_relation.go create mode 100644 model/tags.go create mode 100644 model/tb_attribute.go create mode 100644 model/tb_attribute_value.go create mode 100644 model/tb_category.go create mode 100644 model/tb_goods.go create mode 100644 model/tb_goods_specs.go create mode 100644 model/track.go create mode 100644 model/track_webhook.go create mode 100644 model/us_citys.go create mode 100644 model/us_states.go create mode 100755 model/user.go create mode 100644 model/version.go create mode 100644 model/wallet.go create mode 100644 model/webhook.go create mode 100644 model/withdrawal.go create mode 100644 openapi.yaml create mode 100644 packfile/notUsePackFile.go create mode 100644 packfile/usePackFile.go create mode 100644 resource/gorm_settings.yaml create mode 100644 resource/rbac_model.conf create mode 100644 router/global/dict.go create mode 100644 router/global/global.go create mode 100644 router/influencer/base.go create mode 100644 router/influencer/goods.go create mode 100644 router/influencer/mission.go create mode 100644 router/influencer/order.go create mode 100644 router/influencer/user.go create mode 100644 router/influencer/wallet.go create mode 100644 service/address.go create mode 100644 service/banner.go create mode 100644 service/bill.go create mode 100644 service/chain.go create mode 100644 service/collectiom_goods.go create mode 100644 service/collection_mission.go create mode 100644 service/dict.go create mode 100755 service/jwt_black_list.go create mode 100644 service/mission.go create mode 100644 service/notify.go create mode 100644 service/order.go create mode 100644 service/redis_tools.go create mode 100644 service/seller_store.go create mode 100644 service/sys_brochure.go create mode 100644 service/sys_mission_reward.go create mode 100644 service/tags.go create mode 100644 service/tb_category.go create mode 100644 service/tb_goods.go create mode 100644 service/user.go create mode 100644 service/version.go create mode 100644 service/wallet.go create mode 100644 service/withdrawal.go create mode 100644 tests/Makefile create mode 100644 tests/api/recommender.proto create mode 100644 tests/grpc.go create mode 100644 tests/grpc_test.go create mode 100644 tests/openapi.yaml create mode 100644 utils/array.go create mode 100644 utils/breakpoint_continue.go create mode 100644 utils/constant.go create mode 100644 utils/cors.go create mode 100644 utils/db_automation.go create mode 100644 utils/directory.go create mode 100644 utils/email.go create mode 100644 utils/file_operations.go create mode 100644 utils/float.go create mode 100644 utils/fmt_plus.go create mode 100644 utils/injectionCode.go create mode 100644 utils/international.go create mode 100644 utils/jpush/model.go create mode 100644 utils/jpush/push.go create mode 100644 utils/md5.go create mode 100644 utils/qiniu/model.go create mode 100644 utils/qiniu/video.go create mode 100644 utils/redis.go create mode 100644 utils/redis_store.go create mode 100644 utils/reload.go create mode 100644 utils/rotatelogs_unix.go create mode 100644 utils/rotatelogs_windows.go create mode 100644 utils/sendSms.go create mode 100644 utils/server.go create mode 100644 utils/string.go create mode 100644 utils/time.go create mode 100644 utils/timer/timed_task.go create mode 100644 utils/upload/aliyun_oss.go create mode 100644 utils/upload/local.go create mode 100644 utils/upload/minio.go create mode 100644 utils/upload/tencent_cos.go create mode 100644 utils/validator.go create mode 100644 utils/verify.go create mode 100644 utils/zipfiles.go create mode 100644 webhook.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1e2f0b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.log + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out +.idea/ + +*.history +*_debug* +*.vscode +cache/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4232a79 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM registry.cn-shanghai.aliyuncs.com/lj-go/alpine +LABEL MAINTAINER="NFT" + +WORKDIR /go/src/nft +COPY . /go/src/nft +RUN ls +EXPOSE 8001 +ENTRYPOINT ./server.app \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b25a8c2 --- /dev/null +++ b/Makefile @@ -0,0 +1,67 @@ +GOHOSTOS:=$(shell go env GOHOSTOS) +GOPATH:=$(shell go env GOPATH) +VERSION=$(shell git describe --tags --always) + +ifeq ($(GOHOSTOS), windows) + #the `find.exe` is different from `find` in bash/shell. + #to see https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/find. + #changed to use git-bash.exe to run find cli or other cli friendly, caused of every developer has a Git. + #Git_Bash= $(subst cmd\,bin\bash.exe,$(dir $(shell where git))) + Git_Bash=$(subst \,/,$(subst cmd\,bin\bash.exe,$(dir $(shell where git)))) + INTERNAL_PROTO_FILES=$(shell $(Git_Bash) -c "find internal -name *.proto") + API_PROTO_FILES=$(shell $(Git_Bash) -c "find dto -name *.proto") +else + INTERNAL_PROTO_FILES=$(shell find internal -name *.proto) + API_PROTO_FILES=$(shell find dto -name *.proto) + SD_PROTO_FILES=$(shell find pkg/stable_diffusion -name *.proto) +endif + +.PHONY: init +# init env +init: + go install google.golang.org/protobuf/cmd/protoc-gen-go@latest + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest + go install github.com/go-kratos/kratos/cmd/kratos/v2@latest + go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest + go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest + go install github.com/google/wire/cmd/wire@latest + +.PHONY: config +# generate internal proto +config: + protoc --proto_path=./internal \ + --proto_path=./third_party \ + --go_out=paths=source_relative:./internal \ + $(INTERNAL_PROTO_FILES) + +.PHONY: api +# generate api proto +api: + protoc --proto_path=./dto \ + --go_out=paths=source_relative:./dto \ + --go-http_out=paths=source_relative:./dto \ + --go-grpc_out=paths=source_relative:./dto \ + --openapi_out=fq_schema_naming=true,default_response=false:. \ + $(API_PROTO_FILES) + ls ./dto/*.pb.go | xargs -n1 -IX bash -c 'sed s/,omitempty// X > X.tmp && mv X{.tmp,}' + + + +# show help +help: + @echo '' + @echo 'Usage:' + @echo ' make [target]' + @echo '' + @echo 'Targets:' + @awk '/^[a-zA-Z\-\_0-9]+:/ { \ + helpMessage = match(lastLine, /^# (.*)/); \ + if (helpMessage) { \ + helpCommand = substr($$1, 0, index($$1, ":")); \ + helpMessage = substr(lastLine, RSTART + 2, RLENGTH); \ + printf "\033[36m%-22s\033[0m %s\n", helpCommand,helpMessage; \ + } \ + } \ + { lastLine = $$0 }' $(MAKEFILE_LIST) + +.DEFAULT_GOAL := help diff --git a/README.md b/README.md index 704cc64..b74af18 100644 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ -# app-api - +# app-api \ No newline at end of file diff --git a/api/global/dict.go b/api/global/dict.go new file mode 100644 index 0000000..d08c755 --- /dev/null +++ b/api/global/dict.go @@ -0,0 +1,40 @@ +package global + +import ( + "pure/model/request" + "pure/model/response" + "pure/service" + "pure/utils" + + "github.com/gin-gonic/gin" +) + +// GetSysDictDataList +// @Tags dict +// @Summary 获取数据字典取值列表【v1.0】 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data query request.SearchDictDataParams true "data" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}" +// @Router /dict/getDictDataList [get] +func GetSysDictDataList(c *gin.Context) { + var ( + err error + list interface{} + params request.SearchDictDataParams + ) + _ = c.ShouldBindQuery(¶ms) + if err = utils.Verify(params, utils.DictDataVerity); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, list = service.GetSysDictDataList(params.TypeCode); err != nil { + ////global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithDetailed(response.SelectListResult{ + List: list, + }, "获取成功", c) + } +} diff --git a/api/global/global.go b/api/global/global.go new file mode 100644 index 0000000..ec237ec --- /dev/null +++ b/api/global/global.go @@ -0,0 +1,151 @@ +package global + +import ( + "github.com/gin-gonic/gin" + + "pure/api/sys" + "pure/global" + "pure/model" + "pure/model/request" + "pure/model/response" + "pure/service" + "pure/utils" +) + +// @Summary 获取用户收货地址列表【v1.0】 +// @Security Bearer +// @Description +// @Tags 公用-收货地址 +// @Success 200 {object} []model.Address "{"code": 0, "data": [...]}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /global/address [get] +func GetAddressList(c *gin.Context) { + var ( + err error + userID string + req request.ReqAddress + data any + ) + c.ShouldBind(&req) + userID = sys.GetUserUuid(c) + err, data = service.GetUserAddressList(userID, &req) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(data, c) +} + +// @Summary 添加收货地址【v1.0】 +// @Security Bearer +// @Description +// @Tags 公用-收货地址 +// @Param data body model.Address false "data..." +// @Success 200 {string} string "{"code": 0, "data": [...]}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /global/address [post] +func AddAddress(c *gin.Context) { + var ( + err error + userID string + data model.Address + ) + c.ShouldBindJSON(&data) + userID = sys.GetUserUuid(c) + err = service.AddUserAddressList(userID, &data) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithMessage("添加成功", c) +} + +// @Summary 修改收货地址【v1.0】 +// @Security Bearer +// @Description +// @Tags 公用-收货地址 +// @Param data body model.Address false "data..." +// @Success 200 {string} string "{"code": 0, "data": [...]}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /global/address [put] +func UpdateAddress(c *gin.Context) { + var ( + err error + userID string + data model.Address + ) + c.ShouldBindJSON(&data) + userID = sys.GetUserUuid(c) + err = service.UpdateAddress(userID, &data) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithMessage("修改成功", c) +} + +// @Summary 删除收货地址【v1.0】 +// @Security Bearer +// @Description +// @Tags 公用-收货地址 +// @Param data body global.BASE_ID false "data..." +// @Success 200 {string} string "{"code": 0, "data": [...]}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /global/address [delete] +func DeleteAddress(c *gin.Context) { + var ( + err error + userID string + data global.BASE_ID + ) + c.ShouldBindJSON(&data) + userID = sys.GetUserUuid(c) + err = service.DeleteAddress(userID, &data) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithMessage("删除成功", c) +} + +// @Summary 美国地区选择器【v1.0】 +// @Security Bearer +// @Description +// @Tags 公用-收货地址 +// @Success 200 {object} []model.UsSelect "{"code": 0, "data": [...]}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /global/usSelect [get] +func GetUsSelect(c *gin.Context) { + var ( + err error + data any + ) + err, data = service.GetUsSelect() + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(data, c) +} + +// @Summary 查询物流信息 +// @Security Bearer +// @Description +// @Tags track +// @Param data query request.IdReq false "params" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /global/track [get] +func GetTrack(c *gin.Context) { + var info request.IdReq + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info, utils.IdVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + data, err := service.GetTrack(int64(info.ID)) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(data, c) +} diff --git a/api/influencer/banner.go b/api/influencer/banner.go new file mode 100644 index 0000000..0be5b0c --- /dev/null +++ b/api/influencer/banner.go @@ -0,0 +1,33 @@ +package influencer + +import ( + "github.com/gin-gonic/gin" + "pure/model/response" + "pure/service" +) + +// GetBannerList +// @Tags banner +// @Summary 分页获取banner列表【v1.1.0新增】 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Success 200 {array} response.BannerListResponse "{"success":true,"data":{},"msg":"获取成功"}" +// @Router /influencer/banner/list [get] +func GetBannerList(c *gin.Context) { + var ( + err error + list interface{} + total int64 + ) + + if err, list, total = service.GetBannerList(); err != nil { + ////global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithDetailed(response.PageResult{ + List: list, + Total: total, + }, "获取成功", c) + } +} diff --git a/api/influencer/chain.go b/api/influencer/chain.go new file mode 100644 index 0000000..3414350 --- /dev/null +++ b/api/influencer/chain.go @@ -0,0 +1,36 @@ +package influencer + +import ( + "github.com/gin-gonic/gin" + "pure/model/request" + "pure/model/response" + "pure/service" + "pure/utils" +) + +// GetChainInfo +// @Summary 获取区块链数据 +// @Description +// @Tags Chain +// @Param data query request.ChainParams false "data..." +// @Success 200 {object} []response.ChainResp "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/base/chain [get] +func GetChainInfo(c *gin.Context) { + var ( + err error + params request.ChainParams + result []response.ChainResp + ) + _ = c.ShouldBindQuery(¶ms) + if err = utils.Verify(params, utils.ChainVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + err, result = service.GetChainInfo(params.Hash) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(result, c) +} diff --git a/api/influencer/mission.go b/api/influencer/mission.go new file mode 100644 index 0000000..7fc426c --- /dev/null +++ b/api/influencer/mission.go @@ -0,0 +1,354 @@ +package influencer + +import ( + "pure/api/sys" + "pure/global" + "pure/model/request" + "pure/model/response" + "pure/service" + "pure/utils" + + "github.com/gin-gonic/gin" + "go.uber.org/zap" +) + +// GetMissionDetail +// @Summary 获取任务详情【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data query request.IdReq false "params" +// @Success 200 {object} model.MissionDetail "{"code": 200, "data": {}}" +// @Router /influencer/mission/detail [get] +func GetMissionDetail(c *gin.Context) { + var info request.IdReq + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info, utils.IdVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, data := service.GetMissionDetail(sys.GetUserUuid(c), info.ID); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithData(data, c) + } +} + +// GetMissionList +// @Summary 获取任务列表【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data query request.SearchMission false "params" +// @Success 200 {array} model.MissionDetail "{"code": 200, "data": {}}" +// @Router /influencer/mission/list [get] +func GetMissionList(c *gin.Context) { + var info request.SearchMission + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info.PageInfo, utils.PageInfoVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, list, total := service.GetMissionList(sys.GetUserUuid(c), info); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithDetailed(response.PageResult{ + List: list, + Total: total, + Page: info.Page, + PageSize: info.PageSize, + }, "获取成功", c) + } +} + +// GetMissionClaim +// @Summary 获取我的任务详情【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data query request.IdReq false "params" +// @Success 200 {object} model.MissionClaimDetail "{"code": 200, "data": {}}" +// @Router /influencer/mission/claim [get] +func GetMissionClaim(c *gin.Context) { + var info request.IdReq + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info, utils.IdVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, data := service.GetMissionClaim(sys.GetUserUuid(c), info.ID); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithData(data, c) + } +} + +// GetMissionClaimList +// @Summary 获取我的任务列表【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data query request.SearchMissionClaim false "params" +// @Success 200 {array} model.MissionClaimDetail "{"code": 200, "data": {}}" +// @Router /influencer/mission/claim-list [get] +func GetMissionClaimList(c *gin.Context) { + var info request.SearchMissionClaim + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info.PageInfo, utils.PageInfoVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, list, total := service.MergeMissionClaimList(sys.GetUserUuid(c), info); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithDetailed(response.PageResult{ + List: list, + Total: total, + Page: info.Page, + PageSize: info.PageSize, + }, "获取成功", c) + } +} + +// ClaimMission +// @Summary 领取任务【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data body request.ClaimMission false "params" +// @Success 200 {string} string "{"code": 200, "data": {}}" +// @Router /influencer/mission/claim [post] +func ClaimMission(c *gin.Context) { + var info request.ClaimMission + _ = c.ShouldBindJSON(&info) + if err := utils.Verify(info, utils.MissionClaimVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, id := service.ClaimMission(sys.GetUserUuid(c), info); err != nil { + global.MG_LOG.Error("领取失败!"+err.Error(), zap.Any("err", err)) + response.FailWithMessage("领取失败!"+err.Error(), c) + } else { + response.OkWithDetailed(id, "领取成功", c) + } +} + +// CollectMission +// @Summary 收藏/取消收藏任务【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data body request.MissionId false "params" +// @Success 200 {string} string "{"code": 200, "data": {}}" +// @Router /influencer/mission/collect [post] +func CollectMission(c *gin.Context) { + var info request.MissionId + _ = c.ShouldBindJSON(&info) + if err := utils.Verify(info, utils.MissionIdVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, id := service.ChangeCollectionMission(sys.GetUserUuid(c), info); err != nil { + global.MG_LOG.Error("操作失败!"+err.Error(), zap.Any("err", err)) + response.FailWithMessage("操作失败!"+err.Error(), c) + } else { + response.OkWithDetailed(id, "操作成功", c) + } +} + +// GetCollectionMissionList +// @Summary 获取收藏任务列表【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data query request.SearchCollectionMission false "params" +// @Success 200 {array} model.MissionDetail "{"code": 200, "data": {}}" +// @Router /influencer/mission/collect-list [get] +func GetCollectionMissionList(c *gin.Context) { + var info request.SearchCollectionMission + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info.PageInfo, utils.PageInfoVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, list, total := service.GetCollectionMissionList(sys.GetUserUuid(c), info); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithDetailed(response.PageResult{ + List: list, + Total: total, + Page: info.Page, + PageSize: info.PageSize, + }, "获取成功", c) + } +} + +// SubmitClaimMissionWorks +// @Summary 领取任务的提交作品【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data body request.ClaimMissionWorksList false "params" +// @Success 200 {string} string "{"code": 200, "data": {}}" +// @Router /influencer/mission/submit-works [post] +func SubmitClaimMissionWorks(c *gin.Context) { + var info request.ClaimMissionWorksList + _ = c.ShouldBindJSON(&info) + if err := utils.Verify(info, utils.MissionClaimIdVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err := service.SubmitClaimMissionWorks(sys.GetUserUuid(c), info); err != nil { + global.MG_LOG.Error("提交失败!"+err.Error(), zap.Any("err", err)) + response.FailWithMessage("提交失败!"+err.Error(), c) + } else { + response.OkWithMessage("提交成功", c) + } +} + +// GetMissionDetail +// @Summary 获取任务累计奖金 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data query request.MissionCode false "params" +// @Success 200 {object} model.MissionBonus "{"code": 200, "data": {}}" +// @Router /influencer/mission/bonus [get] +func GetMissionBonus(c *gin.Context) { + var info request.MissionCode + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info, utils.MissionCodeVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + data := service.GetMissionBonus(info.Code) + response.OkWithData(data, c) +} + +// SubmitClaimMissionVideo +// @Summary 固定费用任务上传视频【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data body request.ClaimMissionVideo false "params" +// @Success 200 {string} string "{"code": 200, "data": {}}" +// @Router /influencer/mission/submit-video [post] +func SubmitClaimMissionVideo(c *gin.Context) { + var info request.ClaimMissionVideo + _ = c.ShouldBindJSON(&info) + if err := utils.Verify(info, utils.MissionClaimIdVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err := service.SubmitClaimMissionVideo(sys.GetUserUuid(c), info); err != nil { + global.MG_LOG.Error("提交失败!"+err.Error(), zap.Any("err", err)) + response.FailWithMessage("提交失败!"+err.Error(), c) + } else { + response.OkWithMessage("提交成功", c) + } +} + +// GetRecommendMissionList +// @Summary 获取首页任务列表【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data query request.SearchRecommendMission false "params" +// @Success 200 {array} response.MissionRecommendResponse "{"code": 200, "data": {}}" +// @Router /influencer/mission/recommend-list [get] +func GetRecommendMissionList(c *gin.Context) { + var info request.SearchRecommendMission + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info.PageInfo, utils.PageInfoVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, list, total := service.GetRecommendMissionList(info); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithDetailed(response.PageResult{ + List: list, + Total: total, + Page: info.Page, + PageSize: info.PageSize, + }, "获取成功", c) + } +} + +// GetRecommendMissionDetail +// @Summary 获取首页任务详情【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data query request.IdReq false "params" +// @Success 200 {object} response.MissionRecommendResponse "{"code": 200, "data": {}}" +// @Router /influencer/mission/recommend-detail [get] +func GetRecommendMissionDetail(c *gin.Context) { + var info request.IdReq + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info, utils.IdVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, data := service.GetRecommendMissionDetail(info); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithDetailed(data, "获取成功", c) + } +} + +// GetSysRewardList +// @Summary 获取平台奖励列表【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data query request.SearchSysReward false "params" +// @Success 200 {array} model.SysMissionReward "{"code": 200, "data": {}}" +// @Router /influencer/mission/sys-reward-list [get] +func GetSysRewardList(c *gin.Context) { + var info request.SearchSysReward + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info.PageInfo, utils.PageInfoVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + uuid := sys.GetUserUuid(c) + if err, list, total := service.GetSysMissionRewardList(info, uuid); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithDetailed(response.PageResult{ + List: list, + Total: total, + Page: info.Page, + PageSize: info.PageSize, + }, "获取成功", c) + } +} + +// GetSysRewardSummary +// @Summary 获取平台奖励汇总【v1.0】 +// @Description +// @Tags mission +// @Security ApiKeyAuth +// @Param data query request.SearchSysRewardSummary false "params" +// @Success 200 {object} response.SysMissionBonus "{"code": 200, "data": {}}" +// @Router /influencer/mission/sys-reward-summary [get] +func GetSysRewardSummary(c *gin.Context) { + var info request.SearchSysRewardSummary + _ = c.ShouldBindQuery(&info) + uuid := sys.GetUserUuid(c) + if err, data := service.GetSysRewardSummary(uuid, info); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithDetailed(data, "获取成功", c) + } +} diff --git a/api/influencer/order.go b/api/influencer/order.go new file mode 100644 index 0000000..05c66a1 --- /dev/null +++ b/api/influencer/order.go @@ -0,0 +1,162 @@ +package influencer + +import ( + "pure/api/sys" + "pure/dto" + "pure/model" + "pure/model/request" + "pure/model/response" + "pure/service" + "pure/utils" + + "github.com/gin-gonic/gin" +) + +// @Summary 获取订单数据 +// @Security Bearer +// @Description +// @Tags order +// @Param data query request.SceneParams false "data..." +// @Success 200 {object} dto.OrderData "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/order/data [get] +func GetOrderData(c *gin.Context) { + var ( + err error + params request.SceneParams + result dto.OrderData + ) + _ = c.ShouldBindQuery(¶ms) + userId := sys.GetUserUuid(c) + result, err = service.GetOrderData(userId, ¶ms) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithDataMessage(result, "获取成功", c) +} + +// @Summary 获取订单详情 +// @Security Bearer +// @Description +// @Tags order +// @Param data query request.GetOrderParams false "data..." +// @Success 200 {object} model.OrderDetail "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/order/detail [get] +func GetOrderDetail(c *gin.Context) { + var ( + err error + params request.GetOrderParams + result model.OrderDetail + ) + _ = c.ShouldBindQuery(¶ms) + if err = utils.Verify(params, utils.OrderIdVerity); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + userId := sys.GetUserUuid(c) + err, result = service.GetOrderDetail(userId, ¶ms) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } else { + response.OkWithDataMessage(result, "获取成功", c) + return + } +} + +// @Summary 获取订单列表 +// @Security Bearer +// @Description +// @Tags order +// @Param data query request.SearchOrderList false "data..." +// @Success 200 {object} []model.OrderList "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/order/list [get] +func GetUserOrderList(c *gin.Context) { + var ( + err error + params request.SearchOrderList + list interface{} + total int64 + ) + _ = c.ShouldBindQuery(¶ms) + userID := sys.GetUserUuid(c) + if err, list, total = service.GetOrderList(userID, ¶ms); err != nil { + response.FailWithMessage(err.Error(), c) + return + } else { + response.OkWithDetailed(response.PageResult{ + List: list, + Total: total, + Page: params.Page, + PageSize: params.PageSize, + }, "获取成功", c) + } +} + +func GetOrderTotalList(c *gin.Context) { + var ( + err error + list interface{} + data request.SearchOrderList + ) + _ = c.ShouldBindQuery(&data) + err, list = service.GetOrderTotalList(&data) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithDetailed(list, "获取成功", c) +} + +// @Summary 获取订单商品快照 +// @Security Bearer +// @Description +// @Tags order +// @Param data query request.GetOrderParams false "data..." +// @Success 200 {object} model.OrderGoodsDetail "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/order/goods/snapshot [get] +func GetOrderGoodsInfo(c *gin.Context) { + var ( + err error + params request.GetOrderParams + result model.OrderGoodsDetail + ) + _ = c.ShouldBindQuery(¶ms) + userId := sys.GetUserUuid(c) + err, result = service.GetOrderGoods(userId, ¶ms) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } else { + response.OkWithDataMessage(result, "获取成功", c) + return + } +} + +// @Summary 获取任务下订单统计数据 +// @Security Bearer +// @Description +// @Tags mission +// @Param data query request.MissionCode false "data..." +// @Success 200 {object} dto.MissionOrderStatistic "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/mission/order-data [get] +func GetMissionOrderStatistic(c *gin.Context) { + var ( + err error + params request.MissionCode + result dto.MissionOrderStatistic + ) + _ = c.ShouldBindQuery(¶ms) + userId := sys.GetUserUuid(c) + result, err = service.GetMissionOrderStatistic(userId, params.Code) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithDataMessage(result, "获取成功", c) +} diff --git a/api/influencer/tb_goods.go b/api/influencer/tb_goods.go new file mode 100644 index 0000000..98aa285 --- /dev/null +++ b/api/influencer/tb_goods.go @@ -0,0 +1,29 @@ +package influencer + +import ( + "github.com/gin-gonic/gin" + "go.uber.org/zap" + "pure/global" + "pure/model/request" + "pure/model/response" + "pure/service" +) + +// GetTbGoodsDetail +// @Summary 获取商品详情 +// @Description +// @Tags goods +// @Security ApiKeyAuth +// @Param data query request.Goods false "params" +// @Success 200 {object} model.TbGoodsDetail "{"code": 200, "data": {}}" +//@Router /influencer/goods/detail [get] +func GetTbGoodsDetail(c *gin.Context) { + var info request.Goods + _ = c.ShouldBindQuery(&info) + if err, data := service.GetTbGoods(info); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithData(data, c) + } +} diff --git a/api/influencer/tools.go b/api/influencer/tools.go new file mode 100644 index 0000000..0b8e0e3 --- /dev/null +++ b/api/influencer/tools.go @@ -0,0 +1,76 @@ +package influencer + +import ( + "pure/model/request" + "pure/model/response" + "pure/service" + "pure/utils" + "regexp" + "time" + + "github.com/gin-gonic/gin" +) + +// SendMessage +// @Tags tools +// @Summary 发送短信验证码[v1.0.0] +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.SendMessage true "phone,type" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}" +// @Router /base/sendMessage [post] +func SendMessage(c *gin.Context) { + var ( + err error + params request.SendMessage + ) + _ = c.ShouldBindJSON(¶ms) + if err = utils.Verify(params, utils.SendMessageVerity); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + //校验手机号格式 + if ok, _ := regexp.MatchString(utils.RegPhoneNumber, params.Phone); !ok { + response.FailWithMessage("手机号码格式不合法", c) + return + } + if err = utils.SendSms(params.Phone, params.CountryCode, params.Type); err != nil { + response.FailWithMessage("发送失败,"+err.Error(), c) + return + } + response.OkWithMessage("发送成功", c) +} + +// SendMessage +// @Tags tools +// @Summary 发送邮件验证码[v1.0.0] +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Param data body request.SendEmail true "phone,type" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}" +// @Router /base/sendEmail [post] +func SendEmail(c *gin.Context) { + var ( + err error + params request.SendEmail + code string + ) + _ = c.ShouldBindJSON(¶ms) + if err = utils.Verify(params, utils.SendEmailVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + //校验邮箱格式 + if ok, _ := regexp.MatchString(utils.RegEmailNumber, params.Email); !ok { + response.FailWithMessage("邮箱格式不合法", c) + return + } + if code, err = utils.SendEmail(params.Email, "1"); err != nil { + response.FailWithMessage("发送失败,"+err.Error(), c) + return + } + _ = service.RedisSet("email_code:"+params.Email, code, 5*time.Minute) + response.OkWithMessage("发送成功", c) +} diff --git a/api/influencer/user.go b/api/influencer/user.go new file mode 100644 index 0000000..f83806a --- /dev/null +++ b/api/influencer/user.go @@ -0,0 +1,356 @@ +package influencer + +import ( + "fmt" + "regexp" + "time" + + "pure/api/sys" + "pure/global" + "pure/middleware" + "pure/model" + "pure/model/request" + "pure/model/response" + "pure/service" + + "pure/utils" + + "github.com/dgrijalva/jwt-go" + "github.com/gin-gonic/gin" + "github.com/go-redis/redis" + "go.uber.org/zap" +) + +// Login +// @Summary 登录[v1.0.0] +// @Security Bearer +// @Description +// @Tags auth +// @Param data body request.UserLogin true "email,password..." +// @Success 200 {string} string "{"code": 0, "data": [...]}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/base/login [post] +func LoginInfluencer(c *gin.Context) { + var ( + err error + l request.UserLogin + user *model.User + ) + _ = c.ShouldBindJSON(&l) + if err := utils.Verify(l, utils.LoginVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if l.Type == "1" { + if err := utils.Verify(l, utils.LoginPhoneVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + //校验手机号格式 + if ok, _ := regexp.MatchString(utils.RegPhoneNumber, l.Phone); !ok { + response.FailWithMessage("手机号码格式不合法", c) + return + } + if l.CountryCode == "" { + l.CountryCode = "86" + } + } else if l.Type == "2" { + if err := utils.Verify(l, utils.LoginEmailVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + //校验邮箱格式 + if ok, _ := regexp.MatchString(utils.RegEmailNumber, l.Email); !ok { + response.FailWithMessage("邮箱格式不合法", c) + return + } + } else { + response.FailWithMessage("登录类型不合法", c) + return + } + if err, user = service.UserLogin(&l); err != nil { + global.MG_LOG.Error("Login failed! The user name does not exist or the password is wrong!", zap.Any("err", err)) + fmt.Println(err) + response.FailWithMessage("The user name does not exist or the password is wrong", c) + return + } + // if user.IDForbidden { + // response.OkWithDetailed(map[string]interface{}{"id_forbidden": user.IDForbidden, "forbidden_time": user.ForbiddenTime.Unix(), "forbidden_reason": user.ForbiddenReason}, "The user forbidden", c) + // return + // } + tokenNext(c, *user) +} + +// Register +// @Summary 注册[v1.0.0] +// @Security Bearer +// @Description +// @Tags auth +// @Param data body request.UserRegister true "email,password..." +// @Success 200 {string} string "{"code": 0, "data": "注册成功"}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/base/register [post] +func Register(c *gin.Context) { + var ( + err error + l request.UserRegister + user *model.User + ) + _ = c.ShouldBindJSON(&l) + if err := utils.Verify(l, utils.RegisterVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + //校验邮箱格式 + if ok, _ := regexp.MatchString(utils.RegEmailNumber, l.Email); !ok { + response.FailWithMessage("邮箱格式不合法", c) + return + } + if l.CountryCode == "" { + l.CountryCode = "86" + } + if err, user = service.UserRegister(&l); err != nil { + global.MG_LOG.Error("Register failed!", zap.Any("err", err)) + response.FailWithMessage(err.Error(), c) + return + } + tokenNext(c, *user) +} + +// 登录以后签发jwt +func tokenNext(c *gin.Context, user model.User) { + j := &middleware.JWT{SigningKey: []byte(global.MG_CONFIG.JWT.SigningKey)} // 唯一签名 + claims := request.UserClaims{ + UUID: user.UUID.String(), + NickName: user.NickName, + Email: user.Email, + Appid: user.Appid, + Type: user.Type, + IDForbidden: user.IDForbidden, + BufferTime: global.MG_CONFIG.JWT.BufferTime, // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失 + StandardClaims: jwt.StandardClaims{ + NotBefore: time.Now().Unix() - 1000, // 签名生效时间 + ExpiresAt: time.Now().Unix() + global.MG_CONFIG.JWT.ExpiresTime, // 过期时间 7天 配置文件 + Issuer: "qmPlus", // 签名的发行者 + }, + } + token, err := j.CreateToken(claims) + if err != nil { + global.MG_LOG.Error("get token field!", zap.Any("err", err)) + response.FailWithMessage("get token field", c) + return + } + if global.MG_CONFIG.System.UseMultipoint { + err, jwtStr := service.GetRedisJWT(user.Username) + if err == redis.Nil { + if err := service.SetRedisJWT(token, user.Username); err != nil { + global.MG_LOG.Error("set token failed!", zap.Any("err", err)) + response.FailWithMessage("set token failed", c) + return + } + } else if err != nil { + global.MG_LOG.Error("get token failed!", zap.Any("err", err)) + response.FailWithMessage("get token failed", c) + return + } else { + if err := service.JsonInBlacklist(model.JwtBlacklist{Jwt: jwtStr}); err != nil { + global.MG_LOG.Error("jwt作废失败!", zap.Any("err", err)) + response.FailWithMessage("jwt作废失败", c) + return + } + if err := service.SetRedisJWT(token, user.Username); err != nil { + global.MG_LOG.Error("设置登录状态失败!", zap.Any("err", err)) + response.FailWithMessage("设置登录状态失败", c) + return + } + } + } + // if !global.MG_CONFIG.System.UseMultipoint { + response.OkWithDetailed(response.LoginResponse{ + User: user, + Token: token, + ExpiresAt: claims.StandardClaims.ExpiresAt * 1000, + }, "success", c) +} + +// @Summary 获取用户基本信息[v1.0.0] +// @Security Bearer +// @Description +// @Tags 网红端-用户 +// @Success 200 {object} model.UserSimple "{"code": 0, "data": [...]}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/user/detail [get] +func GetUserDetail(c *gin.Context) { + var ( + err error + userID string + data interface{} + ) + userID = sys.GetUserUuid(c) + err, data = service.GetUserDetail(userID) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(data, c) +} + +// @Summary 修改用户基本信息 +// @Security Bearer +// @Description +// @Tags 网红端-用户 +// @Param data body request.UserDetail false "data..." +// @Success 200 {string} string "{"code": 0, "data": [...]}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/user/detail [put] +func UpdateUserDetail(c *gin.Context) { + var ( + err error + userID string + data request.UserDetail + ) + err = c.ShouldBindJSON(&data) + if err != nil { + fmt.Println(err) + } + userID = sys.GetUserUuid(c) + err = service.UpdateUserDetail(userID, &data) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithMessage("修改成功", c) +} + +// BandPhone +// @Summary 网红绑定手机[v1.0.0] +// @Security Bearer +// @Description +// @Tags 网红端-用户 +// @Param data body request.UserBandPhone true "email,password..." +// @Success 200 {string} string "{"code": 0, "data": "绑定成功"}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/user/bandPhone [post] +func BandPhone(c *gin.Context) { + var ( + err error + l request.UserBandPhone + userID string + ) + _ = c.ShouldBindJSON(&l) + if err := utils.Verify(l, utils.BandPhoneVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + userID = sys.GetUserUuid(c) + if err = service.UserBandPhone(&l, sys.GetUserAppid(c), userID); err != nil { + global.MG_LOG.Error("BandPhone failed!", zap.Any("err", err)) + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithMessage("绑定成功", c) +} + +// PlatformAuth +// @Summary 平台认证[v1.0.0] +// @Security Bearer +// @Description +// @Tags 网红端-用户 +// @Param data body request.UserPlatformAuth true "email,password..." +// @Success 200 {string} string "{"code": 0, "data": "绑定成功"}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/user/platformAuth [post] +func PlatformAuth(c *gin.Context) { + var ( + err error + l request.UserPlatformAuth + userID string + ) + err = c.ShouldBindJSON(&l) + if err != nil { + fmt.Println(err) + } + if err := utils.Verify(l, utils.PlatformAuthVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + userID = sys.GetUserUuid(c) + if err = service.UserPlatformAuth(&l, userID); err != nil { + global.MG_LOG.Error("PlatformAuth failed!", zap.Any("err", err)) + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithMessage("提交成功", c) +} + +// PlatformAuth +// @Summary 授权登录[v1.0.0] +// @Security Bearer +// @Description +// @Tags auth +// @Param data body request.UserAuthorized true "email,password..." +// @Success 200 {string} string "{"code": 0, "data": "绑定成功"}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /base/authorized [post] +func Authorized(c *gin.Context) { + var ( + err error + l request.UserAuthorized + user model.User + ) + _ = c.ShouldBindJSON(&l) + if user, err = service.UserAuthorized(&l); err != nil { + global.MG_LOG.Error("Authorized failed!", zap.Any("err", err)) + response.FailWithMessage(err.Error(), c) + return + } + tokenNext(c, user) +} + +// @Summary 获取用户统计信息[v1.0.0] +// @Security Bearer +// @Description +// @Tags 网红端-用户 +// @Success 200 {object} response.UserStatistics "{"code": 0, "data": [...]}" +// @Router /influencer/user/statistics [get] +func GetUserStatistics(c *gin.Context) { + var ( + err error + userID string + data interface{} + ) + userID = sys.GetUserUuid(c) + err, data = service.GetUserStatistics(userID) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(data, c) +} + +// @Summary 注销账户[v1.0.1] +// @Security Bearer +// @Description +// @Tags 网红端-用户 +// @Success 200 {string} string "{"code": 0, "data": "注销成功"}" +// @Router /influencer/user/logoff [post] +func UserLogOff(c *gin.Context) { + var ( + err error + userID string + ) + userID = sys.GetUserUuid(c) + err = service.UserLogOff(userID) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + //token加入黑名单 + token := c.Request.Header.Get("x-token") + if err := service.JsonInBlacklist(model.JwtBlacklist{Jwt: token}); err != nil { + global.MG_LOG.Error("jwt作废失败!", zap.Any("err", err)) + response.FailWithMessage("jwt作废失败", c) + return + } + response.OkWithMessage("注销成功", c) +} diff --git a/api/influencer/wallet.go b/api/influencer/wallet.go new file mode 100644 index 0000000..515f12d --- /dev/null +++ b/api/influencer/wallet.go @@ -0,0 +1,347 @@ +package influencer + +import ( + "pure/api/sys" + "pure/dto" + "pure/model" + "pure/model/request" + "pure/model/response" + "pure/service" + "pure/utils" + + "github.com/gin-gonic/gin" +) + +// @Summary 钱包基本信息 +// @Security Bearer +// @Description +// @Tags 网红端-用户钱包 +// @Success 200 {object} model.Wallet "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/detail [get] +func GetUserWalletDetail(c *gin.Context) { + var ( + err error + userID string + data interface{} + ) + userID = sys.GetUserUuid(c) + err, data = service.GetUserWalletDetail(userID) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(data, c) +} + +// @Summary 获取账户列表 +// @Security Bearer +// @Description +// @Tags 网红端-用户钱包 +// @Success 200 {object} []model.Account "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/accountList [get] +func GetUserAccountList(c *gin.Context) { + var ( + err error + userID string + result []model.Account + ) + userID = sys.GetUserUuid(c) + result, err = service.GetAccountList(userID) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(result, c) +} + +// @Summary 添加账户 +// @Security Bearer +// @Description +// @Tags 网红端-用户钱包 +// @Param data body request.AddAccount false "data..." +// @Success 200 {string} string "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/account [post] +func AddUserAccount(c *gin.Context) { + var ( + err error + userID string + params request.AddAccount + ) + _ = c.ShouldBindJSON(¶ms) + userID = sys.GetUserUuid(c) + if err = service.AddAccount(userID, ¶ms); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithMessage("绑定成功", c) +} + +// @Summary 设置账户默认开关 +// @Security Bearer +// @Description +// @Tags 网红端-用户钱包 +// @Param data body request.IdReq false "data..." +// @Success 200 {string} string "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/account/default [put] +func UpdateAccountIsDefault(c *gin.Context) { + var ( + err error + params request.IdReq + ) + _ = c.ShouldBindJSON(¶ms) + if err = utils.Verify(params, utils.IdVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + userId := sys.GetUserUuid(c) + err = service.UpdateAccountIsDefault(userId, ¶ms) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithMessage("设置成功", c) +} + +// @Summary 解绑账户 +// @Security Bearer +// @Description +// @Tags 网红端-用户钱包 +// @Param data body request.DeleteAccount false "data..." +// @Success 200 {string} string "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/account [delete] +func DeleteUserAccount(c *gin.Context) { + var ( + err error + userID string + params request.DeleteAccount + ) + _ = c.ShouldBindJSON(¶ms) + if err = utils.Verify(params, utils.IdVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + userID = sys.GetUserUuid(c) + err = service.DeleteAccount(userID, ¶ms) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithMessage("解绑成功", c) +} + +func GetUserCommissionList(c *gin.Context) { + var ( + err error + userID string + list interface{} + total int64 + data request.SearchCommission + ) + c.ShouldBindQuery(&data) + userID = sys.GetUserUuid(c) + err, list, total = service.GetUserCommissionList(userID, &data) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithDetailed(response.PageResult{ + List: list, + Total: total, + Page: data.Page, + PageSize: data.PageSize, + }, "获取成功", c) +} + +func GetUserWithdrawalList(c *gin.Context) { + var ( + err error + userID string + list interface{} + total int64 + data request.SearchWithdrawal + ) + c.ShouldBindQuery(&data) + userID = sys.GetUserUuid(c) + err, list, total = service.GetUserWithdrawalList(userID, &data) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithDetailed(response.PageResult{ + List: list, + Total: total, + Page: data.Page, + PageSize: data.PageSize, + }, "获取成功", c) +} + +// @Summary 提现 +// @Security Bearer +// @Description +// @Tags 网红端-用户钱包 +// @Param data body request.WithdrawalParams false "data..." +// @Success 200 {object} model.WithdrawalView "{"code": 0, "data": [...]}" +// @Success 200 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/withdrawal [post] +func UserWithdrawal(c *gin.Context) { + var ( + err error + params request.WithdrawalParams + resp model.WithdrawalView + ) + _ = c.ShouldBindJSON(¶ms) + if err = utils.Verify(params, utils.WithdrawalVerity); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + userId := sys.GetUserUuid(c) + err, resp = service.Withdrawal(userId, ¶ms) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithDataMessage(resp, "提现成功", c) +} + +// @Summary 获取对账中心数据 +// @Security Bearer +// @Description +// @Tags 对账中心 +// @Param data query request.GetBillDataParams false "data..." +// @Success 200 {object} dto.BillData "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/bill/data [get] +func GetUserBillData(c *gin.Context) { + var ( + err error + params request.GetBillDataParams + result dto.BillData + ) + _ = c.ShouldBindQuery(¶ms) + userId := sys.GetUserUuid(c) + result, err = service.GetBillData(userId, ¶ms) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithDataMessage(result, "获取成功", c) +} + +// @Summary 获取资金流水记录 +// @Security Bearer +// @Description +// @Tags 对账中心 +// @Param data query request.SearchBillParams false "data..." +// @Success 200 {object} []model.Bill "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/bill-list [get] +func GetBillList(c *gin.Context) { + var ( + err error + params request.SearchBillParams + result []model.Bill + ) + _ = c.ShouldBindQuery(¶ms) + if err = utils.Verify(params, utils.BillListVerity); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + userId := sys.GetUserUuid(c) + if result, err = service.GetBillList(userId, ¶ms); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithDetailed(response.PageResult{ + List: result, + Page: params.Page, + PageSize: params.PageSize, + }, "获取成功", c) +} + +// @Summary 获取账单通知列表 +// @Security Bearer +// @Description +// @Tags 对账中心 +// @Success 200 {object} []model.BillNotify "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/bill-notify [get] +func GetBillNotifyList(c *gin.Context) { + var ( + err error + params request.SearchNotify + result []model.Notify + ) + userId := sys.GetUserUuid(c) + params.Page = 1 + params.PageSize = 5 + params.RelationType = "1" + if result, _, err = service.GetNotifyList(userId, ¶ms); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithDataMessage(result, "获取成功", c) +} + +// @Summary 获取提现详情 +// @Security Bearer +// @Description +// @Tags 对账中心 +// @Param data query request.FlowNoParam false "data..." +// @Success 200 {object} model.Withdrawal "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/withdrawal [get] +func GetWithdrawal(c *gin.Context) { + var ( + err error + params request.FlowNoParam + result model.Withdrawal + ) + _ = c.ShouldBindQuery(¶ms) + if err = utils.Verify(params, utils.FlowNoVerity); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + userId := sys.GetUserUuid(c) + err, result = service.GetWithdrawal(userId, ¶ms) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithData(result, c) +} + +// @Summary 获取提现记录 +// @Security Bearer +// @Description +// @Tags 对账中心 +// @Param data query request.PageInfo false "data..." +// @Success 200 {object} []model.Withdrawal "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/wallet/withdrawal-list [get] +func GetWithdrawalList(c *gin.Context) { + var ( + err error + params request.PageInfo + result []model.Withdrawal + ) + _ = c.ShouldBindQuery(¶ms) + if err = utils.Verify(params, utils.PageInfoVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + userId := sys.GetUserUuid(c) + if err, result = service.GetWithdrawalList(userId, ¶ms); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithDetailed(response.PageResult{ + List: result, + Page: params.Page, + PageSize: params.PageSize, + }, "获取成功", c) +} diff --git a/api/sys/sys_brochure.go b/api/sys/sys_brochure.go new file mode 100644 index 0000000..67771fd --- /dev/null +++ b/api/sys/sys_brochure.go @@ -0,0 +1,42 @@ +package sys + +import ( + "github.com/gin-gonic/gin" + "go.uber.org/zap" + "pure/global" + "pure/model/request" + "pure/model/response" + "pure/service" + "pure/utils" +) + +// GetSysBrochure +// @Summary 隐私协议单页 +// @Tags tools +// @Param data query request.SysBrochureType false "params" +// @Success 200 {string} string "{"success":true,"data":{},"msg":""}" +// @Router /customer/base/brochure [get] +func GetSysBrochure(c *gin.Context) { + var info request.SysBrochureType + _ = c.ShouldBindQuery(&info) + if err := utils.Verify(info, utils.TypeVerify); err != nil { + response.FailWithMessage(err.Error(), c) + return + } + if err, data := service.GetSysBrochure(info.Type); err != nil { + global.MG_LOG.Error("获取失败!", zap.Any("err", err)) + response.FailWithMessage("获取失败", c) + } else { + response.OkWithDetailed(data.Content, "获取成功", c) + } +} + +// GetSysBrochure2 +// @Summary 隐私协议单页 +// @Tags tools +// @Param data query request.SysBrochureType false "params" +// @Success 200 {string} string "{"success":true,"data":{},"msg":""}" +// @Router /influencer/base/brochure [get] +func GetSysBrochure2(c *gin.Context) { + +} diff --git a/api/sys/sys_user.go b/api/sys/sys_user.go new file mode 100644 index 0000000..4ce80fe --- /dev/null +++ b/api/sys/sys_user.go @@ -0,0 +1,50 @@ +package sys + +import ( + "pure/global" + "pure/model/request" + + "github.com/gin-gonic/gin" +) + +// 从Gin的Context中获取从jwt解析出来的用户UUID +func GetUserUuid(c *gin.Context) string { + if claims, exists := c.Get("claims"); !exists { + global.MG_LOG.Error("从Gin的Context中获取从jwt解析出来的用户UUID失败, 请检查路由是否使用jwt中间件!") + return "" + } else { + waitUse := claims.(*request.UserClaims) + return waitUse.UUID + } +} + +// 从Gin的Context中获取从jwt解析出来的用户账号 +func GetUserName(c *gin.Context) string { + if claims, exists := c.Get("claims"); !exists { + global.MG_LOG.Error("从Gin的Context中获取从jwt解析出来的用户UUID失败, 请检查路由是否使用jwt中间件!") + return "" + } else { + waitUse := claims.(*request.UserClaims) + return waitUse.Username + } +} + +func GetUserAppid(c *gin.Context) string { + if claims, exists := c.Get("claims"); !exists { + global.MG_LOG.Error("从Gin的Context中获取从jwt解析出来的用户UUID失败, 请检查路由是否使用jwt中间件!") + return "" + } else { + waitUse := claims.(*request.UserClaims) + return waitUse.Appid + } +} + +func getUserInfo(c *gin.Context) *request.UserClaims { + if claims, exists := c.Get("claims"); !exists { + global.MG_LOG.Error("从Gin的Context中获取从jwt解析出来的用户UUID失败, 请检查路由是否使用jwt中间件!") + return nil + } else { + waitUse := claims.(*request.UserClaims) + return waitUse + } +} diff --git a/api/sys/version.go b/api/sys/version.go new file mode 100644 index 0000000..f5baf77 --- /dev/null +++ b/api/sys/version.go @@ -0,0 +1,30 @@ +package sys + +import ( + "github.com/gin-gonic/gin" + "pure/model" + "pure/model/response" + "pure/service" +) + +// @Summary 获取版本信息 +// @Security Bearer +// @Description +// @Tags version +// @Success 200 {string} string "{"code": 0, "data": [...]}" +// @Success 201 {string} string "{"code": 1, "message": ""}" +// @Router /influencer/base/version [get] +func GetVersion(c *gin.Context) { + var ( + err error + result model.VersionV + ) + platform := c.GetString("platform") + version := c.GetString("version") + result, err = service.CheckVersion(platform, version) + if err != nil { + response.FailWithMessage(err.Error(), c) + } else { + response.OkWithData(result, c) + } +} diff --git a/config-prod.yaml b/config-prod.yaml new file mode 100644 index 0000000..a470538 --- /dev/null +++ b/config-prod.yaml @@ -0,0 +1,122 @@ + +autocode: + transfer-restart: true + root: /Users/holi/Downloads/go-workspace/nft-admin + server: /server + server-api: /api/sys + server-initialize: /initialize + server-model: /model + server-request: /model/request/ + server-router: /router + server-service: /service + web: /web/src + web-api: /api + web-form: /view + web-table: /view + web-flow: /view +captcha: + key-long: 6 + img-width: 240 + img-height: 80 +casbin: + model-path: ./resource/rbac_model.conf +email: + to: xxx@qq.com + port: 465 + from: xxx@163.com + host: smtp.163.com + is-ssl: true + secret: xxx + nickname: test +excel: + dir: ./resource/excel/ +jwt: + signing-key: wqrefsad + expires-time: 604800 + buffer-time: 86400 +local: + path: uploads/file +mysql: + path: 172.16.0.26:3306 + config: charset=utf8mb4&parseTime=True&loc=Local + db-name: bkb-prod + username: bkbrd + password: yJGQ3hlV#*4nTJrn + max-idle-conns: 10 + max-open-conns: 100 + log-mode: info + log-zap: "" +minio: + endpoint: file.mangguonews.com + access-key-id: minio + secret-access-key: minio123 + use-ssl: false +redis: + db: 2 +# addr: 172.16.0.239:6379 +# password: bkbrd:!Fgcye*HGs*Z&q0p + addr: redis-6715eafa-8e3f-4014-9659-ac647bd1ef46.cn-north-4.dcs.myhuaweicloud.com:6379 + password: rMof*kkr!mfO7MHW + +system: + env: prod + addr: 8001 + db-type: mysql + oss-type: local + use-multipoint: false + +timer: + start: true + spec: '@daily' + detail: + - tableName: sys_operation_records + compareField: created_at + interval: 2160h +zap: + level: warn + format: console + prefix: '[NFT-ADMIN]' + director: log + link-name: nft.log + showLine: true + encode-level: LowercaseColorLevelEncoder + stacktrace-key: stacktrace + log-in-console: true + +jpush: + appkey: d7e557b47f34c5214e70b02f + secret: 036c179ba0f7c43c1e199c91 + all-user-sign: fm_all_users + android-intent: intent:#Intent;component=com.mg.news.dev/com.mango.hnxwlb.ui930.Main930Activity;S.extras=%v;end + +# qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址) +qiniu: + zone: 'ZoneHuabei' + bucket: ff-file-test + img-path: http://qny-ff-file-test.mangguonews.com + use-https: false + access-key: Maeg1k1PuMo2wJSidAJ-6sSPZquxEbGQuRJvl_Vr + secret-key: gEwHt01k5Pnsk75ad8w4OFZr2kYC6YmoWNITIB1_ + use-cdn-domains: true + +paypal: + env: SandBox + client-id: Af7cbDvcc0qBEZDWgGU3ATZFJePJnFl-UH6foaGzmOu6w_8l1ewZRv88CO39HA0X_ATSR-TP_ZvM_t55 + secret: EFsM94NOvKscr6J-U18rtVp0AIZXlrqWwjXP-vqnNXQ8s2c9TpLQo2hFuf0gYUJg4pjPonqCD4T7nrdW + return-url: + cancel-url: + order-back: 15 + order-confirm: 1 + +tools: +# customer-url: http://120.55.164.69:30204 + customer-url: https://h5-dev.bkbackground.com + +dysmsapi: + accessSecret: ZAnicsJ4biuCbgpNnqQbYU34FhTmn3& + accessKeyID: LTAI5tLzNwMrdZUhdKpm9wor + signName: 一个地球 + templateCode1: SMS_257761932 + templateCode2: SMS_257742075 + templateCode3: SMS_257742078 + templateCode4: SMS_257767780 \ No newline at end of file diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..9ec157f --- /dev/null +++ b/config.yaml @@ -0,0 +1,122 @@ + +autocode: + transfer-restart: true + root: /Users/holi/Downloads/go-workspace/nft-admin + server: /server + server-api: /api/sys + server-initialize: /initialize + server-model: /model + server-request: /model/request/ + server-router: /router + server-service: /service + web: /web/src + web-api: /api + web-form: /view + web-table: /view + web-flow: /view +captcha: + key-long: 6 + img-width: 240 + img-height: 80 +casbin: + model-path: ./resource/rbac_model.conf +email: + to: xxx@qq.com + port: 465 + from: xxx@163.com + host: smtp.163.com + is-ssl: true + secret: xxx + nickname: test +excel: + dir: ./resource/excel/ +jwt: + signing-key: wqrefsad + expires-time: 604800 + buffer-time: 86400 +local: + path: uploads/file +mysql: + path: 172.16.0.26:3306 + config: charset=utf8mb4&parseTime=True&loc=Local + db-name: bkb + username: bkbrd + password: yJGQ3hlV#*4nTJrn + max-idle-conns: 10 + max-open-conns: 100 + log-mode: info + log-zap: "" +minio: + endpoint: file.mangguonews.com + access-key-id: minio + secret-access-key: minio123 + use-ssl: false +redis: + db: 1 +# addr: 172.16.0.239:6379 +# password: bkbrd:!Fgcye*HGs*Z&q0p + addr: redis-6715eafa-8e3f-4014-9659-ac647bd1ef46.cn-north-4.dcs.myhuaweicloud.com:6379 + password: rMof*kkr!mfO7MHW + +system: + env: develop + addr: 8001 + db-type: mysql + oss-type: local + use-multipoint: false + +timer: + start: true + spec: '@daily' + detail: + - tableName: sys_operation_records + compareField: created_at + interval: 2160h +zap: + level: warn + format: console + prefix: '[NFT-ADMIN]' + director: log + link-name: nft.log + showLine: true + encode-level: LowercaseColorLevelEncoder + stacktrace-key: stacktrace + log-in-console: true + +jpush: + appkey: d7e557b47f34c5214e70b02f + secret: 036c179ba0f7c43c1e199c91 + all-user-sign: fm_all_users + android-intent: intent:#Intent;component=com.mg.news.dev/com.mango.hnxwlb.ui930.Main930Activity;S.extras=%v;end + +# qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址) +qiniu: + zone: 'ZoneHuabei' + bucket: ff-file-test + img-path: http://qny-ff-file-test.mangguonews.com + use-https: false + access-key: Maeg1k1PuMo2wJSidAJ-6sSPZquxEbGQuRJvl_Vr + secret-key: gEwHt01k5Pnsk75ad8w4OFZr2kYC6YmoWNITIB1_ + use-cdn-domains: true + +paypal: + env: SandBox + client-id: Af7cbDvcc0qBEZDWgGU3ATZFJePJnFl-UH6foaGzmOu6w_8l1ewZRv88CO39HA0X_ATSR-TP_ZvM_t55 + secret: EFsM94NOvKscr6J-U18rtVp0AIZXlrqWwjXP-vqnNXQ8s2c9TpLQo2hFuf0gYUJg4pjPonqCD4T7nrdW + return-url: + cancel-url: + order-back: 15 + order-confirm: 1 + +tools: +# customer-url: http://120.55.164.69:30204 + customer-url: https://h5-dev.bkbackground.com + +dysmsapi: + accessSecret: ZAnicsJ4biuCbgpNnqQbYU34FhTmn3& + accessKeyID: LTAI5tLzNwMrdZUhdKpm9wor + signName: 一个地球 + templateCode1: SMS_257761932 + templateCode2: SMS_257742075 + templateCode3: SMS_257742078 + templateCode4: SMS_257767780 \ No newline at end of file diff --git a/config/auto_code.go b/config/auto_code.go new file mode 100644 index 0000000..d912156 --- /dev/null +++ b/config/auto_code.go @@ -0,0 +1 @@ +package config diff --git a/config/captcha.go b/config/captcha.go new file mode 100644 index 0000000..af329bf --- /dev/null +++ b/config/captcha.go @@ -0,0 +1,7 @@ +package config + +type Captcha struct { + KeyLong int `mapstructure:"key-long" json:"keyLong" yaml:"key-long"` // 验证码长度 + ImgWidth int `mapstructure:"img-width" json:"imgWidth" yaml:"img-width"` // 验证码宽度 + ImgHeight int `mapstructure:"img-height" json:"imgHeight" yaml:"img-height"` // 验证码高度 +} diff --git a/config/casbin.go b/config/casbin.go new file mode 100644 index 0000000..1b32f2b --- /dev/null +++ b/config/casbin.go @@ -0,0 +1,5 @@ +package config + +type Casbin struct { + ModelPath string `mapstructure:"model-path" json:"modelPath" yaml:"model-path"` // 存放casbin模型的相对路径 +} diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..5e977bf --- /dev/null +++ b/config/config.go @@ -0,0 +1,23 @@ +package config + +type Server struct { + JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"` + Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"` + Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"` + Email Email `mapstructure:"email" json:"email" yaml:"email"` + Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"` + System System `mapstructure:"system" json:"system" yaml:"system"` + // gorm + Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"` + GormSettings GormSettings `mapstructure:"gorm-settings" json:"gormSettings" yaml:"gorm-settings"` + // oss + Local Local `mapstructure:"local" json:"local" yaml:"local"` + Qiniu Qiniu `mapstructure:"qiniu" json:"qiniu" yaml:"qiniu"` + AliyunOSS AliyunOSS `mapstructure:"aliyun-oss" json:"aliyunOSS" yaml:"aliyun-oss"` + TencentCOS TencentCOS `mapstructure:"tencent-cos" json:"tencentCOS" yaml:"tencent-cos"` + Timer Timer `mapstructure:"timer" json:"timer" yaml:"timer"` + JPush JPush `mapstructure:"jpush" json:"jpush" yaml:"jpush"` + Paypal Paypal `mapstructure:"paypal" json:"paypal" yaml:"paypal"` + Tools Tools `mapstructure:"tools" json:"tools" yaml:"tools"` + Dysmsapi Dysmsapi `mapstructure:"dysmsapi" json:"dysmsapi" yaml:"dysmsapi"` +} diff --git a/config/dysmsapi.go b/config/dysmsapi.go new file mode 100644 index 0000000..e27449a --- /dev/null +++ b/config/dysmsapi.go @@ -0,0 +1,11 @@ +package config + +type Dysmsapi struct { + AccessSecret string `mapstructure:"accessSecret" json:"accessSecret" yaml:"accessSecret"` //买家端h5域名地址 + AccessKeyID string `mapstructure:"accessKeyID" json:"accessKeyID" yaml:"accessKeyID"` //买家端h5域名地址 + SignName string `mapstructure:"signName" json:"signName" yaml:"signName"` //买家端h5域名地址 + TemplateCode1 string `mapstructure:"templateCode1" json:"templateCode1" yaml:"templateCode1"` //买家端h5域名地址 + TemplateCode2 string `mapstructure:"templateCode2" json:"templateCode2" yaml:"templateCode2"` //买家端h5域名地址 + TemplateCode3 string `mapstructure:"templateCode3" json:"templateCode3" yaml:"templateCode3"` //买家端h5域名地址 + TemplateCode4 string `mapstructure:"templateCode4" json:"templateCode4" yaml:"templateCode4"` //买家端h5域名地址 +} diff --git a/config/email.go b/config/email.go new file mode 100644 index 0000000..7a8676d --- /dev/null +++ b/config/email.go @@ -0,0 +1,11 @@ +package config + +type Email struct { + To string `mapstructure:"to" json:"to" yaml:"to"` // 收件人:多个以英文逗号分隔 + Port int `mapstructure:"port" json:"port" yaml:"port"` // 端口 + From string `mapstructure:"from" json:"from" yaml:"from"` // 收件人 + Host string `mapstructure:"host" json:"host" yaml:"host"` // 服务器地址 + IsSSL bool `mapstructure:"is-ssl" json:"isSSL" yaml:"is-ssl"` // 是否SSL + Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 + Nickname string `mapstructure:"nickname" json:"nickname" yaml:"nickname"` // 昵称 +} diff --git a/config/excel.go b/config/excel.go new file mode 100644 index 0000000..f3921b0 --- /dev/null +++ b/config/excel.go @@ -0,0 +1,2 @@ +package config + diff --git a/config/gorm.go b/config/gorm.go new file mode 100644 index 0000000..9466414 --- /dev/null +++ b/config/gorm.go @@ -0,0 +1,21 @@ +package config + +type Mysql struct { + Path string `mapstructure:"path" json:"path" yaml:"path"` // 服务器地址:端口 + Config string `mapstructure:"config" json:"config" yaml:"config"` // 高级配置 + Dbname string `mapstructure:"db-name" json:"dbname" yaml:"db-name"` // 数据库名 + Username string `mapstructure:"username" json:"username" yaml:"username"` // 数据库用户名 + Password string `mapstructure:"password" json:"password" yaml:"password"` // 数据库密码 + MaxIdleConns int `mapstructure:"max-idle-conns" json:"maxIdleConns" yaml:"max-idle-conns"` // 空闲中的最大连接数 + MaxOpenConns int `mapstructure:"max-open-conns" json:"maxOpenConns" yaml:"max-open-conns"` // 打开到数据库的最大连接数 + LogMode string `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"` // 是否开启Gorm全局日志 + LogZap bool `mapstructure:"log-zap" json:"logZap" yaml:"log-zap"` // 是否通过zap写入日志文件 +} + +func (m *Mysql) Dsn() string { + return m.Username + ":" + m.Password + "@tcp(" + m.Path + ")/" + m.Dbname + "?" + m.Config +} + +func (m *Mysql) GetLogMode() string { + return m.LogMode +} diff --git a/config/gorm_settings.go b/config/gorm_settings.go new file mode 100644 index 0000000..c01a311 --- /dev/null +++ b/config/gorm_settings.go @@ -0,0 +1,10 @@ +package config + +type GormSettings struct { + Settings []Settings `mapstructure:"settings" json:"settings" yaml:"settings"` +} + +type Settings struct { + DsnName string `mapstructure:"dsn-name" json:"dsnName" yaml:"dsn-name"` + BindTables []interface{} `mapstructure:"bind-tables" json:"bindTables" yaml:"bind-tables"` +} diff --git a/config/jpush.go b/config/jpush.go new file mode 100644 index 0000000..54c4366 --- /dev/null +++ b/config/jpush.go @@ -0,0 +1,8 @@ +package config + +type JPush struct { + Appkey string `mapstructure:"appkey" json:"appkey" yaml:"appkey"` //appkey + Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` //密钥 + AllUserSign string `mapstructure:"all-user-sign" json:"allUserSign" yaml:"all-user-sign"` //所有用户标签 + AndroidIntent string `mapstructure:"android-intent" json:"androidIntent" yaml:"android-intent"` //安卓厂商通道包名 +} diff --git a/config/jwt.go b/config/jwt.go new file mode 100644 index 0000000..08b81f9 --- /dev/null +++ b/config/jwt.go @@ -0,0 +1,7 @@ +package config + +type JWT struct { + SigningKey string `mapstructure:"signing-key" json:"SigningKey" yaml:"signing-key"` // jwt签名 + ExpiresTime int64 `mapstructure:"expires-time" json:"expiresTime" yaml:"expires-time"` // 过期时间 + BufferTime int64 `mapstructure:"buffer-time" json:"bufferTime" yaml:"buffer-time"` // 缓冲时间 +} diff --git a/config/minio.go b/config/minio.go new file mode 100644 index 0000000..f3921b0 --- /dev/null +++ b/config/minio.go @@ -0,0 +1,2 @@ +package config + diff --git a/config/oss.go b/config/oss.go new file mode 100644 index 0000000..a78420a --- /dev/null +++ b/config/oss.go @@ -0,0 +1,31 @@ +package config + +type Local struct { + Path string `mapstructure:"path" json:"path" yaml:"path"` // 本地文件路径 +} + +type Qiniu struct { + Zone string `mapstructure:"zone" json:"zone" yaml:"zone"` // 存储区域 + Bucket string `mapstructure:"bucket" json:"bucket" yaml:"bucket"` // 空间名称 + ImgPath string `mapstructure:"img-path" json:"imgPath" yaml:"img-path"` // CDN加速域名 + UseHTTPS bool `mapstructure:"use-https" json:"useHttps" yaml:"use-https"` // 是否使用https + AccessKey string `mapstructure:"access-key" json:"accessKey" yaml:"access-key"` // 秘钥AK + SecretKey string `mapstructure:"secret-key" json:"secretKey" yaml:"secret-key"` // 秘钥SK + UseCdnDomains bool `mapstructure:"use-cdn-domains" json:"useCdnDomains" yaml:"use-cdn-domains"` // 上传是否使用CDN上传加速 +} + +type AliyunOSS struct { + Endpoint string `mapstructure:"endpoint" json:"endpoint" yaml:"endpoint"` + AccessKeyId string `mapstructure:"access-key-id" json:"accessKeyId" yaml:"access-key-id"` + AccessKeySecret string `mapstructure:"access-key-secret" json:"accessKeySecret" yaml:"access-key-secret"` + BucketName string `mapstructure:"bucket-name" json:"bucketName" yaml:"bucket-name"` + BucketUrl string `mapstructure:"bucket-url" json:"bucketUrl" yaml:"bucket-url"` +} +type TencentCOS struct { + Bucket string `mapstructure:"bucket" json:"bucket" yaml:"bucket"` + Region string `mapstructure:"region" json:"region" yaml:"region"` + SecretID string `mapstructure:"secret-id" json:"secretID" yaml:"secret-id"` + SecretKey string `mapstructure:"secret-key" json:"secretKey" yaml:"secret-key"` + BaseURL string `mapstructure:"base-url" json:"baseURL" yaml:"base-url"` + PathPrefix string `mapstructure:"path-prefix" json:"pathPrefix" yaml:"path-prefix"` +} diff --git a/config/paypal.go b/config/paypal.go new file mode 100644 index 0000000..1f4d95e --- /dev/null +++ b/config/paypal.go @@ -0,0 +1,11 @@ +package config + +type Paypal struct { + Env string `mapstructure:"env" json:"env" yaml:"env"` //端点 + ClientID string `mapstructure:"client-id" json:"client-id" yaml:"client-id"` //用户ID + Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` //密钥 + ReturnUrl string `mapstructure:"return-url" json:"return-url" yaml:"return-url"` //支付完成跳转 + CancelUrl string `mapstructure:"cancel-url" json:"cancel-url" yaml:"cancel-url"` //取消支付跳转 + OrderBack int `mapstructure:"order-back" json:"order-back" yaml:"order-back"` //订单取消时间(分钟) + OrderConfirm int `mapstructure:"order-confirm" json:"order-confirm" yaml:"order-confirm"` //订单确认时间(天) +} diff --git a/config/redis.go b/config/redis.go new file mode 100644 index 0000000..1a25178 --- /dev/null +++ b/config/redis.go @@ -0,0 +1,7 @@ +package config + +type Redis struct { + DB int `mapstructure:"db" json:"db" yaml:"db"` // redis的哪个数据库 + Addr string `mapstructure:"addr" json:"addr" yaml:"addr"` // 服务器地址:端口 + Password string `mapstructure:"password" json:"password" yaml:"password"` // 密码 +} diff --git a/config/system.go b/config/system.go new file mode 100644 index 0000000..768788a --- /dev/null +++ b/config/system.go @@ -0,0 +1,9 @@ +package config + +type System struct { + Env string `mapstructure:"env" json:"env" yaml:"env"` // 环境值 + Addr int `mapstructure:"addr" json:"addr" yaml:"addr"` // 端口值 + DbType string `mapstructure:"db-type" json:"dbType" yaml:"db-type"` // 数据库类型:mysql(默认)|sqlite|sqlserver|postgresql + OssType string `mapstructure:"oss-type" json:"ossType" yaml:"oss-type"` // Oss类型 + UseMultipoint bool `mapstructure:"use-multipoint" json:"useMultipoint" yaml:"use-multipoint"` // 多点登录拦截 +} diff --git a/config/timer.go b/config/timer.go new file mode 100644 index 0000000..1ece2bc --- /dev/null +++ b/config/timer.go @@ -0,0 +1,13 @@ +package config + +type Timer struct { + Start bool `mapstructure:"start" json:"start" yaml:"start"` // 是否启用 + Spec string `mapstructure:"spec" json:"spec" yaml:"spec"` // CRON表达式 + Detail []Detail `mapstructure:"detail" json:"detail" yaml:"detail"` +} + +type Detail struct { + TableName string `mapstructure:"tableName" json:"tableName" yaml:"tableName"` // 需要清理的表名 + CompareField string `mapstructure:"compareField" json:"compareField" yaml:"compareField"` // 需要比较时间的字段 + Interval string `mapstructure:"interval" json:"interval" yaml:"interval"` // 时间间隔 +} diff --git a/config/tools.go b/config/tools.go new file mode 100644 index 0000000..6e6d18b --- /dev/null +++ b/config/tools.go @@ -0,0 +1,5 @@ +package config + +type Tools struct { + CustomerUrl string `mapstructure:"customer-url" json:"customer-url" yaml:"customer-url"` //买家端h5域名地址 +} diff --git a/config/zap.go b/config/zap.go new file mode 100644 index 0000000..f681ca8 --- /dev/null +++ b/config/zap.go @@ -0,0 +1,13 @@ +package config + +type Zap struct { + Level string `mapstructure:"level" json:"level" yaml:"level"` // 级别 + Format string `mapstructure:"format" json:"format" yaml:"format"` // 输出 + Prefix string `mapstructure:"prefix" json:"prefix" yaml:"prefix"` // 日志前缀 + Director string `mapstructure:"director" json:"director" yaml:"director"` // 日志文件夹 + LinkName string `mapstructure:"link-name" json:"linkName" yaml:"link-name"` // 软链接名称 + ShowLine bool `mapstructure:"show-line" json:"showLine" yaml:"showLine"` // 显示行 + EncodeLevel string `mapstructure:"encode-level" json:"encodeLevel" yaml:"encode-level"` // 编码级 + StacktraceKey string `mapstructure:"stacktrace-key" json:"stacktraceKey" yaml:"stacktrace-key"` // 栈名 + LogInConsole bool `mapstructure:"log-in-console" json:"logInConsole" yaml:"log-in-console"` // 输出控制台 +} diff --git a/core/server.go b/core/server.go new file mode 100644 index 0000000..85aa2fd --- /dev/null +++ b/core/server.go @@ -0,0 +1,38 @@ +package core + +import ( + "fmt" + "pure/global" + "pure/initialize" + "time" + + "go.uber.org/zap" +) + +type server interface { + ListenAndServe() error +} + +func RunWindowsServer() { + // 初始化redis服务 + initialize.Redis() + //NewRedisEventSink(global.MG_CONFIG.Redis.DB, "expired") + + Router := initialize.Routers() + Router.Static("/form-generator", "./resource/page") + + address := fmt.Sprintf(":%d", global.MG_CONFIG.System.Addr) + s := initServer(address, Router) + // 保证文本顺序输出 + // In order to ensure that the text order output can be deleted + time.Sleep(10 * time.Microsecond) + global.MG_LOG.Info("server run success on ", zap.String("address", address)) + + fmt.Printf(` + 欢迎使用 MangGuoNews-Admin + 当前版本:V2.4.2 + 默认自动化文档地址:http://127.0.0.1%s/swagger/index.html + 默认前端文件运行地址:http://127.0.0.1%s +`, address, address) + global.MG_LOG.Error(s.ListenAndServe().Error()) +} diff --git a/core/server_other.go b/core/server_other.go new file mode 100644 index 0000000..baa7222 --- /dev/null +++ b/core/server_other.go @@ -0,0 +1,17 @@ +// +build !windows + +package core + +import ( + "github.com/fvbock/endless" + "github.com/gin-gonic/gin" + "time" +) + +func initServer(address string, router *gin.Engine) server { + s := endless.NewServer(address, router) + s.ReadHeaderTimeout = 10 * time.Millisecond + s.WriteTimeout = 10 * time.Second + s.MaxHeaderBytes = 1 << 20 + return s +} diff --git a/core/server_win.go b/core/server_win.go new file mode 100644 index 0000000..ada3c4b --- /dev/null +++ b/core/server_win.go @@ -0,0 +1,19 @@ +// +build windows + +package core + +import ( + "github.com/gin-gonic/gin" + "net/http" + "time" +) + +func initServer(address string, router *gin.Engine) server { + return &http.Server{ + Addr: address, + Handler: router, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, + } +} diff --git a/core/viper.go b/core/viper.go new file mode 100644 index 0000000..58ccb4f --- /dev/null +++ b/core/viper.go @@ -0,0 +1,56 @@ +package core + +import ( + "flag" + "fmt" + "os" + + "pure/global" + _ "pure/packfile" + "pure/utils" + + "github.com/fsnotify/fsnotify" + "github.com/spf13/viper" +) + +func Viper(path ...string) *viper.Viper { + var config string + if len(path) == 0 { + flag.StringVar(&config, "c", "", "choose config file.") + flag.Parse() + if config == "" { // 优先级: 命令行 > 环境变量 > 默认值 + if configEnv := os.Getenv(utils.ConfigEnv); configEnv == "" { + config = utils.ConfigFile + fmt.Printf("您正在使用config的默认值,config的路径为%v\n", utils.ConfigFile) + } else { + config = configEnv + fmt.Printf("您正在使用MG_CONFIG环境变量,config的路径为%v\n", config) + } + } else { + fmt.Printf("您正在使用命令行的-c参数传递的值,config的路径为%v\n", config) + } + } else { + config = path[0] + fmt.Printf("您正在使用func Viper()传递的值,config的路径为%v\n", config) + } + + v := viper.New() + v.SetConfigFile(config) + v.SetConfigType("yaml") + err := v.ReadInConfig() + if err != nil { + panic(fmt.Errorf("Fatal error config file: %s \n", err)) + } + v.WatchConfig() + + v.OnConfigChange(func(e fsnotify.Event) { + fmt.Println("config file changed:", e.Name) + if err := v.Unmarshal(&global.MG_CONFIG); err != nil { + fmt.Println(err) + } + }) + if err := v.Unmarshal(&global.MG_CONFIG); err != nil { + fmt.Println(err) + } + return v +} diff --git a/core/zap.go b/core/zap.go new file mode 100644 index 0000000..b261cb0 --- /dev/null +++ b/core/zap.go @@ -0,0 +1,103 @@ +package core + +import ( + "fmt" + "os" + "pure/global" + "pure/utils" + "time" + + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +var level zapcore.Level + +func Zap() (logger *zap.Logger) { + if ok, _ := utils.PathExists(global.MG_CONFIG.Zap.Director); !ok { // 判断是否有Director文件夹 + fmt.Printf("create %v directory\n", global.MG_CONFIG.Zap.Director) + _ = os.Mkdir(global.MG_CONFIG.Zap.Director, os.ModePerm) + } + + switch global.MG_CONFIG.Zap.Level { // 初始化配置文件的Level + case "debug": + level = zap.DebugLevel + case "info": + level = zap.InfoLevel + case "warn": + level = zap.WarnLevel + case "error": + level = zap.ErrorLevel + case "dpanic": + level = zap.DPanicLevel + case "panic": + level = zap.PanicLevel + case "fatal": + level = zap.FatalLevel + default: + level = zap.InfoLevel + } + + if level == zap.DebugLevel || level == zap.ErrorLevel { + logger = zap.New(getEncoderCore(), zap.AddStacktrace(level)) + } else { + logger = zap.New(getEncoderCore()) + } + if global.MG_CONFIG.Zap.ShowLine { + logger = logger.WithOptions(zap.AddCaller()) + } + return logger +} + +// getEncoderConfig 获取zapcore.EncoderConfig +func getEncoderConfig() (config zapcore.EncoderConfig) { + config = zapcore.EncoderConfig{ + MessageKey: "message", + LevelKey: "level", + TimeKey: "time", + NameKey: "logger", + CallerKey: "caller", + StacktraceKey: global.MG_CONFIG.Zap.StacktraceKey, + LineEnding: zapcore.DefaultLineEnding, + EncodeLevel: zapcore.LowercaseLevelEncoder, + EncodeTime: CustomTimeEncoder, + EncodeDuration: zapcore.SecondsDurationEncoder, + EncodeCaller: zapcore.FullCallerEncoder, + } + switch { + case global.MG_CONFIG.Zap.EncodeLevel == "LowercaseLevelEncoder": // 小写编码器(默认) + config.EncodeLevel = zapcore.LowercaseLevelEncoder + case global.MG_CONFIG.Zap.EncodeLevel == "LowercaseColorLevelEncoder": // 小写编码器带颜色 + config.EncodeLevel = zapcore.LowercaseColorLevelEncoder + case global.MG_CONFIG.Zap.EncodeLevel == "CapitalLevelEncoder": // 大写编码器 + config.EncodeLevel = zapcore.CapitalLevelEncoder + case global.MG_CONFIG.Zap.EncodeLevel == "CapitalColorLevelEncoder": // 大写编码器带颜色 + config.EncodeLevel = zapcore.CapitalColorLevelEncoder + default: + config.EncodeLevel = zapcore.LowercaseLevelEncoder + } + return config +} + +// getEncoder 获取zapcore.Encoder +func getEncoder() zapcore.Encoder { + if global.MG_CONFIG.Zap.Format == "json" { + return zapcore.NewJSONEncoder(getEncoderConfig()) + } + return zapcore.NewConsoleEncoder(getEncoderConfig()) +} + +// getEncoderCore 获取Encoder的zapcore.Core +func getEncoderCore() (core zapcore.Core) { + writer, err := utils.GetWriteSyncer() // 使用file-rotatelogs进行日志分割 + if err != nil { + fmt.Printf("Get Write Syncer Failed err:%v", err.Error()) + return + } + return zapcore.NewCore(getEncoder(), writer, level) +} + +// 自定义日志输出时间格式 +func CustomTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString(t.Format(global.MG_CONFIG.Zap.Prefix + "2006/01/02 - 15:04:05.000")) +} diff --git a/docs/docs.go b/docs/docs.go new file mode 100644 index 0000000..50f27bd --- /dev/null +++ b/docs/docs.go @@ -0,0 +1,4378 @@ +// Code generated by swaggo/swag. DO NOT EDIT +package docs + +import "github.com/swaggo/swag" + +const docTemplate = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "contact": {}, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/base/authorized": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "auth" + ], + "summary": "授权登录[v1.0.0]", + "parameters": [ + { + "description": "email,password...", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.UserAuthorized" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/base/sendEmail": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "tools" + ], + "summary": "发送邮件验证码[v1.0.0]", + "parameters": [ + { + "description": "phone,type", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SendEmail" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/base/sendMessage": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "tools" + ], + "summary": "发送短信验证码[v1.0.0]", + "parameters": [ + { + "description": "phone,type", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SendMessage" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/customer/base/brochure": { + "get": { + "tags": [ + "tools" + ], + "summary": "隐私协议单页", + "parameters": [ + { + "type": "string", + "name": "type", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/dict/getDictDataList": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "dict" + ], + "summary": "获取数据字典取值列表【v1.0】", + "parameters": [ + { + "type": "string", + "description": "取值 release_country=发布国家 release_channel=发布渠道 tag_type=标签类型", + "name": "typeCode", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/global/address": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "公用-收货地址" + ], + "summary": "获取用户收货地址列表【v1.0】", + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "公用-收货地址" + ], + "summary": "修改收货地址【v1.0】", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/model.Address" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "公用-收货地址" + ], + "summary": "添加收货地址【v1.0】", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/model.Address" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "公用-收货地址" + ], + "summary": "删除收货地址【v1.0】", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/global.BASE_ID" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/global/track": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "track" + ], + "summary": "查询物流信息", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/global/usSelect": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "公用-收货地址" + ], + "summary": "美国地区选择器【v1.0】", + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/banner/list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "banner" + ], + "summary": "分页获取banner列表【v1.1.0新增】", + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/response.BannerListResponse" + } + } + } + } + } + }, + "/influencer/base/brochure": { + "get": { + "tags": [ + "tools" + ], + "summary": "隐私协议单页", + "parameters": [ + { + "type": "string", + "name": "type", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/base/chain": { + "get": { + "tags": [ + "Chain" + ], + "summary": "获取区块链数据", + "parameters": [ + { + "type": "string", + "description": "区块/合约hash", + "name": "hash", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/response.ChainResp" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/base/login": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "auth" + ], + "summary": "登录[v1.0.0]", + "parameters": [ + { + "description": "email,password...", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.UserLogin" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/base/register": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "auth" + ], + "summary": "注册[v1.0.0]", + "parameters": [ + { + "description": "email,password...", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.UserRegister" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/base/version": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "version" + ], + "summary": "获取版本信息", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "string" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/goods/detail": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "goods" + ], + "summary": "获取商品详情", + "parameters": [ + { + "type": "string", + "description": "领取任务id", + "name": "claim_no", + "in": "query" + }, + { + "type": "integer", + "description": "商品id", + "name": "id", + "in": "query" + }, + { + "type": "string", + "description": "sku_no", + "name": "sku_no", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/model.TbGoodsDetail" + } + } + } + } + }, + "/influencer/mission/bonus": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取任务累计奖金", + "parameters": [ + { + "type": "string", + "description": "任务编码", + "name": "code", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/model.MissionBonus" + } + } + } + } + }, + "/influencer/mission/claim": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取我的任务详情【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/model.MissionClaimDetail" + } + } + } + }, + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "领取任务【v1.0】", + "parameters": [ + { + "description": "params", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.ClaimMission" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/mission/claim-list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取我的任务列表【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "佣金类型 1:固定佣金 2:比例抽成", + "name": "hire_type", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "是否筛选上传视频 1是", + "name": "video_upload", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MissionClaimDetail" + } + } + } + } + } + }, + "/influencer/mission/collect": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "收藏/取消收藏任务【v1.0】", + "parameters": [ + { + "description": "params", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.MissionId" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/mission/collect-list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取收藏任务列表【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MissionDetail" + } + } + } + } + } + }, + "/influencer/mission/detail": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取任务详情【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/model.MissionDetail" + } + } + } + } + }, + "/influencer/mission/list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取任务列表【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MissionDetail" + } + } + } + } + } + }, + "/influencer/mission/order-data": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取任务下订单统计数据", + "parameters": [ + { + "type": "string", + "description": "任务编码", + "name": "code", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/dto.MissionOrderStatistic" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/mission/recommend-detail": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取首页任务详情【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/response.MissionRecommendResponse" + } + } + } + } + }, + "/influencer/mission/recommend-list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取首页任务列表【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/response.MissionRecommendResponse" + } + } + } + } + } + }, + "/influencer/mission/submit-video": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "固定费用任务上传视频【v1.0】", + "parameters": [ + { + "description": "params", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.ClaimMissionVideo" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/mission/submit-works": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "领取任务的提交作品【v1.0】", + "parameters": [ + { + "description": "params", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.ClaimMissionWorksList" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/mission/sys-reward-list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取平台奖励列表【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "状态 1待发放 2已发放 3已领取", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.SysMissionReward" + } + } + } + } + } + }, + "/influencer/mission/sys-reward-summary": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取平台奖励汇总【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "状态 1待发放 2已发放 3已领取", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/response.SysMissionBonus" + } + } + } + } + }, + "/influencer/order/data": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "order" + ], + "summary": "获取订单数据", + "parameters": [ + { + "type": "string", + "description": "场景 my:我的 order-list:订单列表", + "name": "scene", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/dto.OrderData" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/order/detail": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "order" + ], + "summary": "获取订单详情", + "parameters": [ + { + "type": "string", + "description": "订单号", + "name": "orderID", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/model.OrderDetail" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/order/goods/snapshot": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "order" + ], + "summary": "获取订单商品快照", + "parameters": [ + { + "type": "string", + "description": "订单号", + "name": "orderID", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/model.OrderGoodsDetail" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/order/list": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "order" + ], + "summary": "获取订单列表", + "parameters": [ + { + "type": "string", + "description": "网红码?", + "name": "code", + "in": "query" + }, + { + "type": "string", + "description": "数据库分组", + "name": "group", + "in": "query" + }, + { + "type": "string", + "description": "订单号", + "name": "orderID", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.OrderList" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/user/bandPhone": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "网红绑定手机[v1.0.0]", + "parameters": [ + { + "description": "email,password...", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.UserBandPhone" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/user/detail": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "获取用户基本信息[v1.0.0]", + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "修改用户基本信息", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.UserDetail" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/user/logoff": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "注销账户[v1.0.1]", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": \"注销成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/user/platformAuth": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "平台认证[v1.0.0]", + "parameters": [ + { + "description": "email,password...", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.UserPlatformAuth" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/user/statistics": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "获取用户统计信息[v1.0.0]", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.UserStatistics" + } + } + } + } + }, + "/influencer/wallet/account": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "添加账户", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.AddAccount" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "string" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "解绑账户", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.DeleteAccount" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "string" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/account/default": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "设置账户默认开关", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.IdReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "string" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/accountList": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "获取账户列表", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Account" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/bill-list": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "对账中心" + ], + "summary": "获取资金流水记录", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "空:默认 1:bill-center", + "name": "scene", + "in": "query" + }, + { + "type": "string", + "description": "空:全部 1-支出 2-收入", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "1:全部 2:昨天 3:近30天", + "name": "uint", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Bill" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/bill-notify": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "对账中心" + ], + "summary": "获取账单通知列表", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.BillNotify" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/bill/data": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "对账中心" + ], + "summary": "获取对账中心数据", + "parameters": [ + { + "type": "string", + "description": "1:全部 2:昨天 3:近30天", + "name": "uint", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/dto.BillData" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/detail": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "钱包基本信息", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/model.Wallet" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/withdrawal": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "对账中心" + ], + "summary": "获取提现详情", + "parameters": [ + { + "type": "string", + "description": "流水号", + "name": "flow_no", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/model.Withdrawal" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "提现", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.WithdrawalParams" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/withdrawal-list": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "对账中心" + ], + "summary": "获取提现记录", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Withdrawal" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "dto.BillData": { + "type": "object", + "properties": { + "cancelOrderMoney": { + "description": "退款订单总额", + "type": "number" + }, + "cancelOrderNum": { + "description": "退款订单数", + "type": "integer" + }, + "flowExpend": { + "description": "出账", + "type": "number" + }, + "flowIncome": { + "description": "进账", + "type": "number" + }, + "income": { + "description": "收入总额", + "type": "number" + }, + "orderMoney": { + "description": "订单总额", + "type": "number" + }, + "orderNum": { + "description": "订单数", + "type": "integer" + }, + "rewardUnfinished": { + "description": "在途佣金", + "type": "number" + } + } + }, + "dto.MissionOrderStatistic": { + "type": "object", + "properties": { + "OrderMoney": { + "description": "订单金额", + "type": "number" + }, + "OrderUserNum": { + "description": "下单人数", + "type": "integer" + }, + "RewardRatio": { + "description": "佣金比例", + "type": "number" + }, + "SellNum": { + "description": "销售数量", + "type": "integer" + }, + "SettleReward": { + "description": "结算佣金", + "type": "number" + }, + "TransitReward": { + "description": "在途佣金", + "type": "number" + }, + "Uv": { + "description": "浏览人数", + "type": "integer" + }, + "orderDoneNum": { + "description": "完成订单总数", + "type": "integer" + }, + "orderNum": { + "description": "订单总数", + "type": "integer" + } + } + }, + "dto.OrderData": { + "type": "object", + "properties": { + "all": { + "description": "全部", + "type": "integer" + }, + "cancel": { + "description": "已取消", + "type": "integer" + }, + "finished": { + "description": "已完成", + "type": "integer" + }, + "shipped": { + "description": "已发货", + "type": "integer" + }, + "unship": { + "description": "待发货", + "type": "integer" + } + } + }, + "global.BASE_ID": { + "type": "object", + "properties": { + "id": { + "description": "主键", + "type": "integer" + } + } + }, + "model.Account": { + "type": "object", + "properties": { + "account_name": { + "description": "户名", + "type": "string" + }, + "address": { + "description": "收款人地址", + "type": "string" + }, + "bank_code": { + "description": "收款行", + "type": "string" + }, + "card_number": { + "description": "银行卡号", + "type": "string" + }, + "country": { + "description": "国家/地区", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "currency": { + "description": "币种 USD:美元", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "idCard": { + "type": "string" + }, + "is_default": { + "description": "是否为默认 0:非默认 1:默认", + "type": "boolean" + }, + "phone": { + "type": "string" + }, + "platform": { + "description": "平台 saller(买家端) / customer(客户端) / influencer(网红端)", + "type": "string" + }, + "sort": { + "description": "排序值", + "type": "integer" + }, + "swift_code": { + "description": "银行国际代码", + "type": "string" + }, + "type": { + "description": "类型 1:paypal 2:银行卡", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userID": { + "description": "用户id", + "type": "string" + } + } + }, + "model.Address": { + "type": "object", + "properties": { + "bldg": { + "description": "apt,ste,bldg", + "type": "string" + }, + "city": { + "description": "city", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "default": { + "description": "是否默认地址 1-是 2-否", + "type": "integer" + }, + "firstName": { + "description": "first name", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "lastName": { + "description": "last name", + "type": "string" + }, + "phone": { + "description": "手机号", + "type": "string" + }, + "platform": { + "description": "平台 saller(买家端) / customer(客户端) / influencer(网红端)", + "type": "string" + }, + "state": { + "description": "state", + "type": "string" + }, + "street": { + "description": "street", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userId": { + "type": "string" + }, + "zipCode": { + "description": "zip code", + "type": "string" + } + } + }, + "model.Bill": { + "type": "object", + "properties": { + "account": { + "description": "收款账户(提现)", + "type": "string" + }, + "amount": { + "description": "数量", + "type": "integer" + }, + "balance": { + "description": "余额", + "type": "number" + }, + "check_status": { + "description": "审核状态 0:待审核 1:审核通过 2:审核未通过", + "type": "string" + }, + "claim_no": { + "description": "领取任务编号", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "order_id": { + "description": "关联订单id", + "type": "string" + }, + "platform": { + "description": "平台 seller(买家端) / customer(客户端) / influencer(网红端)", + "type": "string" + }, + "price": { + "description": "金额", + "type": "number" + }, + "receipt": { + "description": "是否已到账 1-是 2-否 3-已取消付款", + "type": "integer" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "status": { + "description": "类型 1-支出 2-收入", + "type": "integer" + }, + "title": { + "description": "账单标题", + "type": "string" + }, + "transaction_id": { + "description": "交易编号", + "type": "string" + }, + "type": { + "description": "类型 1-佣金 2-订单 3-提现 4-平台奖励", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userID": { + "description": "用户id", + "type": "string" + }, + "withd_id": { + "description": "提现id", + "type": "string" + }, + "withdrawalStatus": { + "description": "提现状态 0-提现中 1-提现完成 2-提现失败", + "type": "integer" + } + } + }, + "model.BillNotify": { + "type": "object", + "properties": { + "relation_id": { + "description": "关联id", + "type": "string" + }, + "relation_type": { + "description": "关联类型", + "type": "string" + }, + "title": { + "description": "标题", + "type": "string" + } + } + }, + "model.BillView": { + "type": "object", + "properties": { + "id": { + "description": "id", + "type": "integer" + }, + "order_id": { + "description": "订单编号", + "type": "string" + }, + "transaction_id": { + "description": "交易编号", + "type": "string" + } + } + }, + "model.Breadcrumb": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "is_leaf": { + "description": "是否叶子分类", + "type": "boolean" + }, + "name": { + "type": "string" + }, + "pid": { + "description": "父id", + "type": "integer" + } + } + }, + "model.Chain": { + "type": "object", + "properties": { + "address": { + "description": "合约地址", + "type": "string" + } + } + }, + "model.MissionBonus": { + "type": "object", + "properties": { + "total": { + "type": "number" + }, + "user_total": { + "type": "number" + } + } + }, + "model.MissionClaimDetail": { + "type": "object", + "properties": { + "achieve_num": { + "description": "已完成商品数量", + "type": "integer" + }, + "claim_no": { + "description": "领取任务编号", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "email": { + "description": "发送邮箱", + "type": "string" + }, + "expire_at": { + "description": "任务推广过期时间", + "type": "string" + }, + "finished": { + "description": "任务完成状态 0:未完成 1:已完成", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "mission": { + "description": "关联任务", + "allOf": [ + { + "$ref": "#/definitions/model.MissionDetail" + } + ] + }, + "mission_id": { + "description": "任务id", + "type": "integer" + }, + "order": { + "description": "任务订单", + "allOf": [ + { + "$ref": "#/definitions/model.MissionClaimOrderInfo" + } + ] + }, + "spread_url": { + "description": "推广链接", + "type": "string" + }, + "status": { + "description": "状态 1:已领取待发货 2:已发货 3:已收货推广中", + "type": "integer" + }, + "status_except": { + "description": "状态描述", + "type": "string" + }, + "total_bonus": { + "description": "累计佣金", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "video": { + "description": "上传视频", + "allOf": [ + { + "$ref": "#/definitions/model.MissionClaimVideo" + } + ] + }, + "works": { + "description": "发布作品", + "type": "array", + "items": { + "$ref": "#/definitions/model.MissionClaimWorks" + } + } + } + }, + "model.MissionClaimOrderGoods": { + "type": "object", + "properties": { + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "image": { + "description": "规格图片url", + "type": "string" + }, + "order_id": { + "description": "订单号", + "type": "string" + }, + "price": { + "description": "价格", + "type": "number" + }, + "sku_no": { + "description": "sku编号", + "type": "string" + }, + "specs": { + "description": "规格", + "type": "string" + }, + "title": { + "description": "名称", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.MissionClaimOrderInfo": { + "type": "object", + "properties": { + "courier": { + "description": "快递公司", + "type": "string" + }, + "courier_number": { + "description": "快递单号", + "type": "string" + }, + "courier_url": { + "description": "快递查询地址", + "type": "string" + }, + "deliver": { + "description": "发货信息", + "allOf": [ + { + "$ref": "#/definitions/model.OrderDeliver" + } + ] + }, + "mission_claim_id": { + "description": "领取任务id", + "type": "integer" + }, + "order_goods": { + "description": "订单商品信息", + "allOf": [ + { + "$ref": "#/definitions/model.MissionClaimOrderGoods" + } + ] + }, + "order_id": { + "description": "订单号", + "type": "string" + }, + "send_time": { + "description": "发货时间", + "type": "string" + }, + "status": { + "description": "订单状态 2:待发货 3:已发货", + "type": "integer" + } + } + }, + "model.MissionClaimVideo": { + "type": "object", + "properties": { + "cover": { + "description": "视频封面", + "type": "string" + }, + "create_by": { + "description": "创建人", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "height": { + "description": "高度", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "mission_claim_id": { + "description": "领取任务id", + "type": "integer" + }, + "mission_id": { + "description": "任务ID", + "type": "integer" + }, + "remark": { + "type": "string" + }, + "reward_status": { + "description": "奖励发放状态 1:未发放 2:已发放", + "type": "integer" + }, + "source_type": { + "description": "类型:1:固定费用上传 2:奖励任务上传 3:后台上传", + "type": "integer" + }, + "status": { + "description": "状态 1:待审核 2:审核通过 3:审核不通过", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "video_url": { + "description": "视频上传地址", + "type": "string" + }, + "width": { + "description": "宽度", + "type": "integer" + } + } + }, + "model.MissionClaimWorks": { + "type": "object", + "properties": { + "created_at": { + "description": "创建时间", + "type": "string" + }, + "homepage": { + "description": "作品主页地址", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "image": { + "description": "作品凭证截图", + "type": "string" + }, + "mission_claim_id": { + "description": "领取任务id", + "type": "integer" + }, + "type": { + "description": "平台 1:ins 2:YouTube 3:tiktok 4:Facebook 5:Twitter", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "video_url": { + "description": "视频上传地址", + "type": "string" + } + } + }, + "model.MissionDetail": { + "type": "object", + "properties": { + "claim_days": { + "description": "任务完成天数", + "type": "integer" + }, + "claim_demands": { + "description": "任务拍摄要求", + "type": "string" + }, + "claim_num": { + "description": "接任务人数", + "type": "integer" + }, + "claim_status_except": { + "description": "可接任务状态描述", + "type": "string" + }, + "claim_status_except_eng": { + "description": "英文版状态描述", + "type": "string" + }, + "claim_stock": { + "description": "可接任务库存", + "type": "integer" + }, + "collect_status": { + "description": "收藏状态 true:已收藏 false:未收藏", + "type": "boolean" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "description": { + "description": "描述/卖点", + "type": "string" + }, + "end_time": { + "description": "任务结束时间", + "type": "string" + }, + "goods": { + "description": "商品信息", + "allOf": [ + { + "$ref": "#/definitions/model.TbGoodsSpecsView" + } + ] + }, + "goods_status": { + "description": "关联商品状态 1:正常 2:已下架", + "type": "integer" + }, + "goods_url": { + "description": "商品链接", + "type": "string" + }, + "has_sample": { + "description": "是否有样品 0:没有 1:有", + "type": "integer" + }, + "has_video": { + "description": "是否有视频素材 0:没有 1:有", + "type": "integer" + }, + "hire_money": { + "description": "hire_type==1 佣金金额", + "type": "number" + }, + "hire_money_expect": { + "description": "预计佣金描述", + "type": "string" + }, + "hire_ratio": { + "description": "hire_type==2 抽成比例", + "type": "number" + }, + "hire_type": { + "description": "佣金类型 1:固定佣金 2:比例抽成", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "num": { + "description": "商品数量", + "type": "integer" + }, + "release_channels": { + "description": "发布渠道", + "type": "string" + }, + "release_country": { + "description": "发布国家", + "type": "string" + }, + "sample_num": { + "description": "样品数量", + "type": "integer" + }, + "start_time": { + "description": "任务起始时间", + "type": "string" + }, + "status": { + "description": "状态 1:未开始 2:进行中 3:已结束", + "type": "integer" + }, + "store": { + "description": "商家信息", + "allOf": [ + { + "$ref": "#/definitions/model.SellerStoreInfo" + } + ] + }, + "title": { + "description": "标题", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "video_channel_ids": { + "description": "视频发布渠道,多个渠道英文逗号连接", + "type": "string" + }, + "video_country_id": { + "description": "视频发布国家", + "type": "string" + }, + "video_url": { + "type": "string" + } + } + }, + "model.OrderAddress": { + "type": "object", + "properties": { + "bldg": { + "description": "apt,ste,bldg", + "type": "string" + }, + "city": { + "description": "city", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "default": { + "description": "是否默认地址 1-是 2-否", + "type": "integer" + }, + "firstName": { + "description": "first name", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "lastName": { + "description": "last name", + "type": "string" + }, + "orderID": { + "type": "string" + }, + "phone": { + "description": "手机号", + "type": "string" + }, + "platform": { + "description": "平台 saller(买家端) / customer(客户端) / influencer(网红端)", + "type": "string" + }, + "state": { + "description": "state", + "type": "string" + }, + "street": { + "description": "street", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userId": { + "type": "string" + }, + "zipCode": { + "description": "zip code", + "type": "string" + } + } + }, + "model.OrderDeliver": { + "type": "object", + "properties": { + "courier": { + "description": "快递公司", + "type": "string" + }, + "courierLink": { + "description": "快递链接", + "type": "string" + }, + "courierNumber": { + "description": "快递单号", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "orderID": { + "description": "订单号", + "type": "string" + }, + "track_id": { + "description": "track表id", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.OrderDetail": { + "type": "object", + "properties": { + "IAmount": { + "description": "网红佣金", + "type": "string" + }, + "address": { + "description": "地址", + "allOf": [ + { + "$ref": "#/definitions/model.OrderAddress" + } + ] + }, + "bill": { + "description": "交易信息", + "allOf": [ + { + "$ref": "#/definitions/model.BillView" + } + ] + }, + "captureID": { + "description": "paypal收款确认id", + "type": "string" + }, + "chain": { + "description": "区块链", + "allOf": [ + { + "$ref": "#/definitions/model.Chain" + } + ] + }, + "code": { + "description": "网红码?", + "type": "string" + }, + "commodID": { + "description": "商品id", + "type": "integer" + }, + "confirmTime": { + "description": "收货时间", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "deliver": { + "description": "发货信息", + "allOf": [ + { + "$ref": "#/definitions/model.OrderDeliver" + } + ] + }, + "goods": { + "description": "商品信息", + "allOf": [ + { + "$ref": "#/definitions/model.OrderGoodsDetail" + } + ] + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "number": { + "description": "数量", + "type": "integer" + }, + "orderID": { + "description": "订单号", + "type": "string" + }, + "paidPrice": { + "description": "实付价格", + "type": "number" + }, + "payTime": { + "description": "付款时间", + "type": "string" + }, + "paypalID": { + "description": "paypal订单号", + "type": "string" + }, + "platform": { + "description": "购买平台", + "type": "string" + }, + "postSale": { + "description": "售后信息", + "allOf": [ + { + "$ref": "#/definitions/model.PostSale" + } + ] + }, + "price": { + "description": "商品价格", + "type": "number" + }, + "sendTime": { + "description": "发货时间", + "type": "string" + }, + "sku_id": { + "description": "商品规格编号", + "type": "integer" + }, + "sku_no": { + "description": "商品规格编号", + "type": "string" + }, + "status": { + "description": "订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消", + "type": "integer" + }, + "store": { + "description": "店铺信息", + "allOf": [ + { + "$ref": "#/definitions/model.SellerStoreInfo" + } + ] + }, + "store_no": { + "description": "店铺编号", + "type": "string" + }, + "type": { + "description": "类型 1-普通订单 2-预售订单", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userID": { + "description": "用户id", + "type": "string" + } + } + }, + "model.OrderGoodsDetail": { + "type": "object", + "properties": { + "attributes": { + "description": "规格详情", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbAttributeWithValues" + } + }, + "content": { + "description": "详情", + "type": "string" + }, + "content_text": { + "description": "详情-文字", + "type": "string" + }, + "cover": { + "description": "封面图", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "goods_specs": { + "description": "规格", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbOrderGoodsSpecsDetail" + } + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "images": { + "description": "图片", + "type": "string" + }, + "orderID": { + "description": "订单id", + "type": "string" + }, + "price_max": { + "description": "最高规格价格", + "type": "number" + }, + "price_min": { + "description": "最低规格价格", + "type": "number" + }, + "retail_price": { + "description": "吊牌价(零售指导价)", + "type": "number" + }, + "sku_no": { + "description": "商品规格编号", + "type": "string" + }, + "specs": { + "description": "规格", + "type": "string" + }, + "spu_no": { + "description": "编号", + "type": "string" + }, + "store_no": { + "description": "店铺编号", + "type": "string" + }, + "title": { + "description": "名称", + "type": "string" + }, + "title_eng": { + "description": "英文名称", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.OrderList": { + "type": "object", + "properties": { + "IAmount": { + "description": "网红佣金", + "type": "string" + }, + "captureID": { + "description": "paypal收款确认id", + "type": "string" + }, + "code": { + "description": "网红码?", + "type": "string" + }, + "commodID": { + "description": "商品id", + "type": "integer" + }, + "confirmTime": { + "description": "收货时间", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "goods": { + "description": "商品信息", + "allOf": [ + { + "$ref": "#/definitions/model.OrderGoodsDetail" + } + ] + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "number": { + "description": "数量", + "type": "integer" + }, + "orderID": { + "description": "订单号", + "type": "string" + }, + "paidPrice": { + "description": "实付价格", + "type": "number" + }, + "payTime": { + "description": "付款时间", + "type": "string" + }, + "paypalID": { + "description": "paypal订单号", + "type": "string" + }, + "platform": { + "description": "购买平台", + "type": "string" + }, + "price": { + "description": "商品价格", + "type": "number" + }, + "sendTime": { + "description": "发货时间", + "type": "string" + }, + "sku_id": { + "description": "商品规格编号", + "type": "integer" + }, + "sku_no": { + "description": "商品规格编号", + "type": "string" + }, + "status": { + "description": "订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消", + "type": "integer" + }, + "store_no": { + "description": "店铺编号", + "type": "string" + }, + "type": { + "description": "类型 1-普通订单 2-预售订单", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "user": { + "description": "买家信息", + "allOf": [ + { + "$ref": "#/definitions/model.UserSimple" + } + ] + }, + "userID": { + "description": "用户id", + "type": "string" + } + } + }, + "model.PostSale": { + "type": "object", + "properties": { + "created_at": { + "description": "创建时间", + "type": "string" + }, + "examine_time": { + "description": "审核时间", + "type": "string" + }, + "id": { + "description": "id", + "type": "integer" + }, + "orderId": { + "description": "订单id", + "type": "string" + }, + "refundStatus": { + "description": "退款状态 1:退款中 2:退款成功 3:退款失败", + "type": "integer" + }, + "refund_time": { + "description": "退款时间", + "type": "string" + }, + "remark": { + "description": "审核原因", + "type": "string" + }, + "status": { + "description": "处理状态 1:已提交 2:已处理 3:已拒绝 4:已撤回", + "type": "integer" + } + } + }, + "model.SellerStoreInfo": { + "type": "object", + "properties": { + "email": { + "description": "店铺联系email(注册账号email)", + "type": "string" + }, + "store_no": { + "description": "店铺编号", + "type": "string" + }, + "type": { + "description": "1:个人店铺", + "type": "integer" + } + } + }, + "model.SysMissionReward": { + "type": "object", + "properties": { + "achieve_num": { + "description": "已完成任务次数", + "type": "integer" + }, + "audit_by": { + "description": "审核人", + "type": "string" + }, + "bonus": { + "description": "奖励金额", + "type": "number" + }, + "create_by": { + "description": "创建人", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "relationId": { + "description": "关联项目id", + "type": "string" + }, + "status": { + "description": "状态 1待发放 2已发放 3已领取", + "type": "integer" + }, + "title": { + "description": "标题", + "type": "string" + }, + "type": { + "description": "奖励类型 1.视频上传 2.信息完善 3.商家任务", + "type": "integer" + }, + "update_by": { + "description": "更新人", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.TbAttributeDetail": { + "type": "object", + "properties": { + "attribute_id": { + "description": "规格属性id", + "type": "integer" + }, + "value": { + "type": "string" + }, + "value_id": { + "type": "integer" + } + } + }, + "model.TbAttributeValueItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "image": { + "description": "图片", + "type": "string" + }, + "name": { + "description": "规格属性值", + "type": "string" + } + } + }, + "model.TbAttributeWithValues": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "values": { + "type": "array", + "items": { + "$ref": "#/definitions/model.TbAttributeValueItem" + } + } + } + }, + "model.TbGoodsDetail": { + "type": "object", + "properties": { + "attributes": { + "description": "规格详情", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbAttributeWithValues" + } + }, + "breadcrumb": { + "description": "分类面包屑", + "type": "array", + "items": { + "$ref": "#/definitions/model.Breadcrumb" + } + }, + "category_id": { + "description": "分类id", + "type": "integer" + }, + "collect_status": { + "description": "收藏状态 true:已收藏 false:未收藏", + "type": "boolean" + }, + "content": { + "description": "商品详情", + "type": "string" + }, + "content_text": { + "description": "详情-文字", + "type": "string" + }, + "cover": { + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "images": { + "description": "图片", + "type": "string" + }, + "list_price": { + "description": "列表价格", + "type": "number" + }, + "online": { + "description": "上下架状态 on/off", + "type": "string" + }, + "price_max": { + "description": "最高规格价格", + "type": "number" + }, + "price_min": { + "description": "最低规格价格", + "type": "number" + }, + "retail_price": { + "description": "吊牌价(零售指导价)", + "type": "number" + }, + "specs": { + "description": "规格", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbGoodsSpecsDetail" + } + }, + "spu_no": { + "description": "编号", + "type": "string" + }, + "tags": { + "description": "标签", + "type": "string" + }, + "title": { + "description": "标题", + "type": "string" + }, + "title_eng": { + "description": "英文标题", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.TbGoodsSpecsDetail": { + "type": "object", + "properties": { + "attributes": { + "description": "规格详情", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbAttributeDetail" + } + }, + "code": { + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "goods_id": { + "type": "integer" + }, + "goods_no": { + "description": "商品编号", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "image": { + "description": "规格图片url", + "type": "string" + }, + "price": { + "description": "价格", + "type": "number" + }, + "sku_no": { + "description": "商品编码", + "type": "string" + }, + "specs": { + "description": "规格", + "type": "string" + }, + "stock": { + "description": "库存", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.TbGoodsSpecsView": { + "type": "object", + "properties": { + "attributes": { + "description": "规格详情", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbAttributeWithValues" + } + }, + "cover": { + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "images": { + "description": "图片", + "type": "string" + }, + "price_max": { + "description": "最高规格价格", + "type": "number" + }, + "price_min": { + "description": "最低规格价格", + "type": "number" + }, + "retail_price": { + "description": "吊牌价(零售指导价)", + "type": "number" + }, + "sales": { + "description": "总销售量", + "type": "integer" + }, + "specs": { + "description": "规格", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbGoodsSpecsDetail" + } + }, + "spu_no": { + "description": "编号", + "type": "string" + }, + "stock": { + "description": "总库存", + "type": "integer" + }, + "tags": { + "description": "标签", + "type": "string" + }, + "title": { + "description": "标题", + "type": "string" + }, + "title_eng": { + "description": "英文标题", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.TbOrderGoodsSpecsDetail": { + "type": "object", + "properties": { + "code": { + "description": "attribute定位标识", + "type": "string" + }, + "goods_id": { + "type": "integer" + }, + "goods_no": { + "description": "商品编号", + "type": "string" + }, + "image": { + "description": "规格图片url", + "type": "string" + }, + "orderGoodsId": { + "type": "integer" + }, + "price": { + "description": "价格", + "type": "number" + }, + "sku_no": { + "description": "Attributes []TbAttributeDetail ` + "`" + `gorm:\"-\" json:\"-\"` + "`" + ` // 规格详情", + "type": "string" + }, + "specs": { + "description": "规格", + "type": "string" + } + } + }, + "model.UsCitys": { + "type": "object", + "properties": { + "city": { + "type": "string" + }, + "county": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "idState": { + "type": "integer" + } + } + }, + "model.UsSelect": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UsCitys" + } + }, + "id": { + "type": "integer" + }, + "stateCode": { + "type": "string" + }, + "stateName": { + "type": "string" + } + } + }, + "model.UserSimple": { + "type": "object", + "properties": { + "avatar": { + "description": "头像", + "type": "string" + }, + "email": { + "description": "用户邮箱", + "type": "string" + }, + "nick_name": { + "description": "昵称", + "type": "string" + }, + "phone": { + "description": "手机号", + "type": "string" + }, + "platform": { + "description": "平台", + "type": "array", + "items": { + "$ref": "#/definitions/request.Platform" + } + }, + "tags": { + "description": "个人标签", + "type": "string" + }, + "uuid": { + "description": "用户uuid编码", + "type": "string" + } + } + }, + "model.Wallet": { + "type": "object", + "properties": { + "balance": { + "description": "可用余额", + "type": "number" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "platform": { + "description": "平台 saller(买家端) / customer(客户端) / influencer(网红端)", + "type": "string" + }, + "state": { + "description": "状态 0:正常 1:限制提现 2:禁止提现", + "type": "integer" + }, + "transitBalance": { + "description": "在途余额", + "type": "number" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userId": { + "type": "string" + } + } + }, + "model.Withdrawal": { + "type": "object", + "properties": { + "account_name": { + "description": "户名", + "type": "string" + }, + "account_type": { + "description": "账户类型 1:paypal 2:银行卡", + "type": "integer" + }, + "address": { + "description": "收款人地址", + "type": "string" + }, + "amount": { + "description": "金额", + "type": "number" + }, + "bank_code": { + "description": "收款行", + "type": "string" + }, + "bill_no": { + "description": "账单号", + "type": "string" + }, + "card_number": { + "description": "银行卡号", + "type": "string" + }, + "check_status": { + "description": "审核状态 0:待审核 1:审核通过 2:审核未通过", + "type": "string" + }, + "check_time": { + "description": "审核时间", + "type": "string" + }, + "country": { + "description": "国家/地区", + "type": "string" + }, + "create_by": { + "description": "创建人/店铺", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "currency": { + "description": "币种 USD:美元", + "type": "string" + }, + "flow_no": { + "description": "流水号", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "pay_id": { + "description": "支付id", + "type": "string" + }, + "platform": { + "description": "平台 1:网红 2:商家", + "type": "string" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "status": { + "description": "提现状态 0:进行中 1:成功 2:失败", + "type": "string" + }, + "swift_code": { + "description": "银行国际代码", + "type": "string" + }, + "title": { + "description": "标题", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "wallet_type": { + "description": "钱包类型 1:余额钱包 2:营销账户钱包", + "type": "integer" + } + } + }, + "model.WithdrawalView": { + "type": "object", + "properties": { + "flow_no": { + "description": "流水号", + "type": "string" + } + } + }, + "request.AddAccount": { + "type": "object", + "properties": { + "account_name": { + "description": "户名", + "type": "string" + }, + "address": { + "description": "收款人地址", + "type": "string" + }, + "bank_card": { + "description": "银行卡号", + "type": "string" + }, + "bank_code": { + "description": "银行编码", + "type": "string" + }, + "country": { + "description": "国家/地区", + "type": "string" + }, + "currency": { + "description": "币种 USD: 美元", + "type": "string" + }, + "is_default": { + "description": "是否默认", + "type": "boolean" + }, + "swift_code": { + "description": "swift编码", + "type": "string" + } + } + }, + "request.ClaimMission": { + "type": "object", + "properties": { + "address_id": { + "description": "收货地址id", + "type": "integer" + }, + "email": { + "description": "邮箱地址", + "type": "string" + }, + "mission_id": { + "description": "任务id", + "type": "integer" + }, + "sku_no": { + "description": "商品sku_no", + "type": "string" + }, + "spu_no": { + "description": "商品spu_no", + "type": "string" + } + } + }, + "request.ClaimMissionVideo": { + "type": "object", + "properties": { + "cover": { + "type": "string" + }, + "height": { + "description": "高度", + "type": "integer" + }, + "mission_claim_id": { + "description": "领取任务id", + "type": "integer" + }, + "source_type": { + "description": "类型:1:固定费用上传 2:奖励任务上传 3:后台上传", + "type": "integer" + }, + "video_url": { + "description": "视频上传地址", + "type": "string" + }, + "width": { + "description": "宽度", + "type": "integer" + } + } + }, + "request.ClaimMissionWorks": { + "type": "object", + "properties": { + "homepage": { + "description": "作品主页地址", + "type": "string" + }, + "id": { + "description": "id", + "type": "integer" + }, + "image": { + "description": "作品凭证截图", + "type": "string" + }, + "type": { + "description": "平台 1:ins 2:Pinterest 3:tk 4:Twitter 5:Facebook 6:Reddit", + "type": "integer" + }, + "video_url": { + "description": "视频上传地址", + "type": "string" + } + } + }, + "request.ClaimMissionWorksList": { + "type": "object", + "properties": { + "mission_claim_id": { + "description": "领取任务id", + "type": "integer" + }, + "works": { + "description": "作品列表", + "type": "array", + "items": { + "$ref": "#/definitions/request.ClaimMissionWorks" + } + } + } + }, + "request.DeleteAccount": { + "type": "object", + "properties": { + "code": { + "description": "验证码", + "type": "string" + }, + "id": { + "description": "主键", + "type": "integer" + }, + "phone": { + "description": "手机号", + "type": "string" + } + } + }, + "request.IdReq": { + "type": "object", + "properties": { + "id": { + "description": "id", + "type": "integer" + } + } + }, + "request.MissionId": { + "type": "object", + "properties": { + "mission_id": { + "description": "任务", + "type": "integer" + } + } + }, + "request.Platform": { + "type": "object", + "properties": { + "image": { + "description": "图片", + "type": "string" + }, + "is_auth": { + "description": "是否认证", + "type": "boolean" + }, + "label": { + "type": "string" + }, + "platform": { + "description": "平台 字典表获取", + "type": "string" + }, + "url": { + "description": "主页地址", + "type": "string" + } + } + }, + "request.SendEmail": { + "type": "object", + "properties": { + "email": { + "type": "string" + } + } + }, + "request.SendMessage": { + "type": "object", + "properties": { + "country_code": { + "description": "用户手机号国家代码 国际区号 86 中国 1美国", + "type": "string" + }, + "phone": { + "type": "string" + }, + "type": { + "description": "1:登录验证码 2-解绑 3-绑定 4-提现", + "type": "integer" + } + } + }, + "request.UserAuthorized": { + "type": "object", + "properties": { + "appid": { + "description": "应用id", + "type": "string" + }, + "client": { + "description": "客户端 ios android web", + "type": "string" + }, + "code": { + "description": "授权码", + "type": "string" + }, + "platform": { + "description": "平台 google facebook twitter tiktok", + "type": "string" + }, + "token": { + "description": "token", + "type": "string" + }, + "uuid": { + "description": "设备唯一标识", + "type": "string" + } + } + }, + "request.UserBandPhone": { + "type": "object", + "properties": { + "code": { + "description": "验证码", + "type": "string" + }, + "phone": { + "description": "手机号", + "type": "string" + } + } + }, + "request.UserDetail": { + "type": "object", + "properties": { + "platform": { + "description": "平台及地址逗号隔开 eg:(ins:https://baidu.com/user/1,qq:12345678)", + "type": "string" + }, + "tags": { + "description": "个人标签", + "type": "string" + }, + "type": { + "description": "修改字段 platform-平台 tags-个人标签", + "type": "string" + } + } + }, + "request.UserLogin": { + "type": "object", + "properties": { + "appid": { + "description": "应用id", + "type": "string" + }, + "code": { + "description": "验证码", + "type": "string" + }, + "country_code": { + "description": "用户手机号国家代码 国际区号 86 中国 1美国", + "type": "string" + }, + "email": { + "description": "邮箱", + "type": "string" + }, + "password": { + "description": "密码", + "type": "string" + }, + "phone": { + "description": "手机号", + "type": "string" + }, + "type": { + "description": "1-手机号 2-邮箱", + "type": "string" + } + } + }, + "request.UserPlatformAuth": { + "type": "object", + "properties": { + "platform": { + "description": "平台", + "allOf": [ + { + "$ref": "#/definitions/request.Platform" + } + ] + }, + "tags": { + "description": "个人标签", + "type": "string" + } + } + }, + "request.UserRegister": { + "type": "object", + "properties": { + "appid": { + "description": "应用id", + "type": "string" + }, + "avatar": { + "description": "头像", + "type": "string" + }, + "code": { + "description": "验证码", + "type": "string" + }, + "country_code": { + "description": "用户手机号国家代码 国际区号 86 中国 1美国", + "type": "string" + }, + "email": { + "description": "邮箱", + "type": "string" + }, + "nickname": { + "description": "昵称", + "type": "string" + } + } + }, + "request.WithdrawalParams": { + "type": "object", + "properties": { + "accountID": { + "description": "提现账户id", + "type": "integer" + }, + "amount": { + "description": "Code string ` + "`" + `json:\"code\"` + "`" + ` // 验证码", + "type": "number" + } + } + }, + "response.BannerListResponse": { + "type": "object", + "properties": { + "coverUrl": { + "description": "封面图", + "type": "string" + }, + "id": { + "description": "主键", + "type": "integer" + }, + "link": { + "description": "链接地址", + "type": "string" + }, + "linkType": { + "description": "链接类型 0:内链 1:外链", + "type": "string" + }, + "relationId": { + "description": "关联项目id", + "type": "string" + }, + "relationType": { + "description": "关联类型 01-任务", + "type": "string" + }, + "sort_index": { + "description": "序号索引", + "type": "integer" + }, + "status": { + "description": "状态 0=下架 1=上架", + "type": "string" + }, + "title": { + "description": "标题", + "type": "string" + }, + "type": { + "description": "任务-0101 平台奖励页-0102", + "type": "string" + } + } + }, + "response.ChainResp": { + "type": "object", + "properties": { + "block_adress": { + "description": "所在区块", + "type": "string" + }, + "block_height": { + "description": "块高度", + "type": "integer" + }, + "hash": { + "description": "交易哈希", + "type": "string" + }, + "time": { + "description": "上链时间", + "type": "string" + } + } + }, + "response.MissionRecommendResponse": { + "type": "object", + "properties": { + "achieve_num": { + "description": "已完成商品数量", + "type": "integer" + }, + "bought_num": { + "description": "购买人数", + "type": "number" + }, + "claim_num": { + "description": "任务领取人数", + "type": "integer" + }, + "cover": { + "description": "封面", + "type": "string" + }, + "create_by": { + "description": "创建人", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "end_time": { + "description": "任务结束时间", + "type": "string" + }, + "goods_title": { + "description": "商品标题", + "type": "string" + }, + "goods_title_eng": { + "description": "商品英文标题", + "type": "string" + }, + "height": { + "description": "高度", + "type": "integer" + }, + "hire_money": { + "description": "hire_type==1 佣金金额", + "type": "number" + }, + "hire_money_expect": { + "description": "预计佣金描述", + "type": "string" + }, + "hire_ratio": { + "description": "hire_type==2 抽成比例", + "type": "number" + }, + "hire_type": { + "description": "佣金类型 1:固定佣金 2:比例抽成", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "influencer": { + "$ref": "#/definitions/model.UserSimple" + }, + "mission_id": { + "description": "任务ID", + "type": "integer" + }, + "mission_status": { + "description": "任务状态", + "type": "integer" + }, + "relation_id": { + "description": "关联ID,任务视频ID", + "type": "integer" + }, + "release_channels": { + "description": "发布渠道", + "type": "string" + }, + "release_country": { + "description": "发布国家", + "type": "string" + }, + "sort": { + "description": "倒序 //排序", + "type": "integer" + }, + "start_time": { + "description": "任务起始时间", + "type": "string" + }, + "status": { + "description": "状态 1:上架 2:下架", + "type": "integer" + }, + "tag": { + "description": "todo 标签系统", + "type": "string" + }, + "title": { + "description": "任务标题", + "type": "string" + }, + "total_bonus": { + "description": "累计奖励", + "type": "number" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "video_url": { + "description": "视频地址", + "type": "string" + }, + "width": { + "description": "宽度", + "type": "integer" + } + } + }, + "response.SysBonusDetail": { + "type": "object", + "properties": { + "achieve_max": { + "description": "最大完成次数", + "type": "integer" + }, + "achieve_num": { + "description": "已完成任务次数", + "type": "integer" + }, + "bonus": { + "description": "奖金", + "type": "number" + }, + "mission_list": { + "description": "任务列表", + "type": "array", + "items": { + "$ref": "#/definitions/response.SysMissionDesc" + } + }, + "title": { + "description": "标题", + "type": "string" + }, + "total": { + "description": "奖励次数", + "type": "integer" + }, + "type": { + "description": "奖励类型 1.视频上传 2.信息完善 3.商家任务", + "type": "integer" + } + } + }, + "response.SysMissionBonus": { + "type": "object", + "properties": { + "total": { + "description": "奖励总笔数", + "type": "integer" + }, + "total_bonus": { + "description": "奖励汇总金额", + "type": "number" + }, + "video_bonus": { + "description": "视频上传", + "allOf": [ + { + "$ref": "#/definitions/response.SysBonusDetail" + } + ] + } + } + }, + "response.SysMissionDesc": { + "type": "object", + "properties": { + "achieve_num": { + "type": "integer" + }, + "bonus": { + "description": "奖励金额", + "type": "number" + }, + "description": { + "description": "描述", + "type": "string" + }, + "description_eng": { + "description": "描述英文", + "type": "string" + }, + "status": { + "description": "状态 1待发放 2已发放 3已领取 0未完成", + "type": "integer" + }, + "title": { + "description": "任务标题", + "type": "string" + }, + "title_eng": { + "description": "任务标题英文", + "type": "string" + } + } + }, + "response.UserStatistics": { + "type": "object", + "properties": { + "claim_mission_num": { + "description": "领取任务数量", + "type": "integer" + }, + "collection_mission_num": { + "description": "收藏任务数量", + "type": "integer" + }, + "platform_num": { + "description": "认证平台数量", + "type": "integer" + } + } + } + }, + "securityDefinitions": { + "ApiKeyAuth": { + "type": "apiKey", + "name": "x-token", + "in": "header" + } + } +}` + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ + Version: "0.0.1", + Host: "", + BasePath: "", + Schemes: []string{}, + Title: "Swagger Example API", + Description: "接口文档", + InfoInstanceName: "swagger", + SwaggerTemplate: docTemplate, +} + +func init() { + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) +} diff --git a/docs/swagger.json b/docs/swagger.json new file mode 100644 index 0000000..1b2ac21 --- /dev/null +++ b/docs/swagger.json @@ -0,0 +1,4354 @@ +{ + "swagger": "2.0", + "info": { + "description": "接口文档", + "title": "Swagger Example API", + "contact": {}, + "version": "0.0.1" + }, + "paths": { + "/base/authorized": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "auth" + ], + "summary": "授权登录[v1.0.0]", + "parameters": [ + { + "description": "email,password...", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.UserAuthorized" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/base/sendEmail": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "tools" + ], + "summary": "发送邮件验证码[v1.0.0]", + "parameters": [ + { + "description": "phone,type", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SendEmail" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/base/sendMessage": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "tools" + ], + "summary": "发送短信验证码[v1.0.0]", + "parameters": [ + { + "description": "phone,type", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SendMessage" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/customer/base/brochure": { + "get": { + "tags": [ + "tools" + ], + "summary": "隐私协议单页", + "parameters": [ + { + "type": "string", + "name": "type", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/dict/getDictDataList": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "dict" + ], + "summary": "获取数据字典取值列表【v1.0】", + "parameters": [ + { + "type": "string", + "description": "取值 release_country=发布国家 release_channel=发布渠道 tag_type=标签类型", + "name": "typeCode", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/global/address": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "公用-收货地址" + ], + "summary": "获取用户收货地址列表【v1.0】", + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "公用-收货地址" + ], + "summary": "修改收货地址【v1.0】", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/model.Address" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "公用-收货地址" + ], + "summary": "添加收货地址【v1.0】", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/model.Address" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "公用-收货地址" + ], + "summary": "删除收货地址【v1.0】", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/global.BASE_ID" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/global/track": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "track" + ], + "summary": "查询物流信息", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/global/usSelect": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "公用-收货地址" + ], + "summary": "美国地区选择器【v1.0】", + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/banner/list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "banner" + ], + "summary": "分页获取banner列表【v1.1.0新增】", + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/response.BannerListResponse" + } + } + } + } + } + }, + "/influencer/base/brochure": { + "get": { + "tags": [ + "tools" + ], + "summary": "隐私协议单页", + "parameters": [ + { + "type": "string", + "name": "type", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/base/chain": { + "get": { + "tags": [ + "Chain" + ], + "summary": "获取区块链数据", + "parameters": [ + { + "type": "string", + "description": "区块/合约hash", + "name": "hash", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/response.ChainResp" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/base/login": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "auth" + ], + "summary": "登录[v1.0.0]", + "parameters": [ + { + "description": "email,password...", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.UserLogin" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/base/register": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "auth" + ], + "summary": "注册[v1.0.0]", + "parameters": [ + { + "description": "email,password...", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.UserRegister" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/base/version": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "version" + ], + "summary": "获取版本信息", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "string" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/goods/detail": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "goods" + ], + "summary": "获取商品详情", + "parameters": [ + { + "type": "string", + "description": "领取任务id", + "name": "claim_no", + "in": "query" + }, + { + "type": "integer", + "description": "商品id", + "name": "id", + "in": "query" + }, + { + "type": "string", + "description": "sku_no", + "name": "sku_no", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/model.TbGoodsDetail" + } + } + } + } + }, + "/influencer/mission/bonus": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取任务累计奖金", + "parameters": [ + { + "type": "string", + "description": "任务编码", + "name": "code", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/model.MissionBonus" + } + } + } + } + }, + "/influencer/mission/claim": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取我的任务详情【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/model.MissionClaimDetail" + } + } + } + }, + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "领取任务【v1.0】", + "parameters": [ + { + "description": "params", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.ClaimMission" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/mission/claim-list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取我的任务列表【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "佣金类型 1:固定佣金 2:比例抽成", + "name": "hire_type", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "是否筛选上传视频 1是", + "name": "video_upload", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MissionClaimDetail" + } + } + } + } + } + }, + "/influencer/mission/collect": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "收藏/取消收藏任务【v1.0】", + "parameters": [ + { + "description": "params", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.MissionId" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/mission/collect-list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取收藏任务列表【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MissionDetail" + } + } + } + } + } + }, + "/influencer/mission/detail": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取任务详情【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/model.MissionDetail" + } + } + } + } + }, + "/influencer/mission/list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取任务列表【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.MissionDetail" + } + } + } + } + } + }, + "/influencer/mission/order-data": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取任务下订单统计数据", + "parameters": [ + { + "type": "string", + "description": "任务编码", + "name": "code", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/dto.MissionOrderStatistic" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/mission/recommend-detail": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取首页任务详情【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/response.MissionRecommendResponse" + } + } + } + } + }, + "/influencer/mission/recommend-list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取首页任务列表【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/response.MissionRecommendResponse" + } + } + } + } + } + }, + "/influencer/mission/submit-video": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "固定费用任务上传视频【v1.0】", + "parameters": [ + { + "description": "params", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.ClaimMissionVideo" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/mission/submit-works": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "领取任务的提交作品【v1.0】", + "parameters": [ + { + "description": "params", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.ClaimMissionWorksList" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/mission/sys-reward-list": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取平台奖励列表【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "状态 1待发放 2已发放 3已领取", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.SysMissionReward" + } + } + } + } + } + }, + "/influencer/mission/sys-reward-summary": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "tags": [ + "mission" + ], + "summary": "获取平台奖励汇总【v1.0】", + "parameters": [ + { + "type": "integer", + "description": "状态 1待发放 2已发放 3已领取", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": {}}", + "schema": { + "$ref": "#/definitions/response.SysMissionBonus" + } + } + } + } + }, + "/influencer/order/data": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "order" + ], + "summary": "获取订单数据", + "parameters": [ + { + "type": "string", + "description": "场景 my:我的 order-list:订单列表", + "name": "scene", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/dto.OrderData" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/order/detail": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "order" + ], + "summary": "获取订单详情", + "parameters": [ + { + "type": "string", + "description": "订单号", + "name": "orderID", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/model.OrderDetail" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/order/goods/snapshot": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "order" + ], + "summary": "获取订单商品快照", + "parameters": [ + { + "type": "string", + "description": "订单号", + "name": "orderID", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/model.OrderGoodsDetail" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/order/list": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "order" + ], + "summary": "获取订单列表", + "parameters": [ + { + "type": "string", + "description": "网红码?", + "name": "code", + "in": "query" + }, + { + "type": "string", + "description": "数据库分组", + "name": "group", + "in": "query" + }, + { + "type": "string", + "description": "订单号", + "name": "orderID", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.OrderList" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/user/bandPhone": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "网红绑定手机[v1.0.0]", + "parameters": [ + { + "description": "email,password...", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.UserBandPhone" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/user/detail": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "获取用户基本信息[v1.0.0]", + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "修改用户基本信息", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.UserDetail" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/user/logoff": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "注销账户[v1.0.1]", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": \"注销成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/user/platformAuth": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "平台认证[v1.0.0]", + "parameters": [ + { + "description": "email,password...", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.UserPlatformAuth" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/user/statistics": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户" + ], + "summary": "获取用户统计信息[v1.0.0]", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.UserStatistics" + } + } + } + } + }, + "/influencer/wallet/account": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "添加账户", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.AddAccount" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "string" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "解绑账户", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.DeleteAccount" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "string" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/account/default": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "设置账户默认开关", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.IdReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "string" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/accountList": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "获取账户列表", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Account" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/bill-list": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "对账中心" + ], + "summary": "获取资金流水记录", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "空:默认 1:bill-center", + "name": "scene", + "in": "query" + }, + { + "type": "string", + "description": "空:全部 1-支出 2-收入", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "1:全部 2:昨天 3:近30天", + "name": "uint", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Bill" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/bill-notify": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "对账中心" + ], + "summary": "获取账单通知列表", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.BillNotify" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/bill/data": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "对账中心" + ], + "summary": "获取对账中心数据", + "parameters": [ + { + "type": "string", + "description": "1:全部 2:昨天 3:近30天", + "name": "uint", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/dto.BillData" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/detail": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "钱包基本信息", + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/model.Wallet" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/withdrawal": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "对账中心" + ], + "summary": "获取提现详情", + "parameters": [ + { + "type": "string", + "description": "流水号", + "name": "flow_no", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/model.Withdrawal" + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "网红端-用户钱包" + ], + "summary": "提现", + "parameters": [ + { + "description": "data...", + "name": "data", + "in": "body", + "schema": { + "$ref": "#/definitions/request.WithdrawalParams" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/influencer/wallet/withdrawal-list": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "tags": [ + "对账中心" + ], + "summary": "获取提现记录", + "parameters": [ + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 0, \"data\": [...]}", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Withdrawal" + } + } + }, + "201": { + "description": "{\"code\": 1, \"message\": \"\"}", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "dto.BillData": { + "type": "object", + "properties": { + "cancelOrderMoney": { + "description": "退款订单总额", + "type": "number" + }, + "cancelOrderNum": { + "description": "退款订单数", + "type": "integer" + }, + "flowExpend": { + "description": "出账", + "type": "number" + }, + "flowIncome": { + "description": "进账", + "type": "number" + }, + "income": { + "description": "收入总额", + "type": "number" + }, + "orderMoney": { + "description": "订单总额", + "type": "number" + }, + "orderNum": { + "description": "订单数", + "type": "integer" + }, + "rewardUnfinished": { + "description": "在途佣金", + "type": "number" + } + } + }, + "dto.MissionOrderStatistic": { + "type": "object", + "properties": { + "OrderMoney": { + "description": "订单金额", + "type": "number" + }, + "OrderUserNum": { + "description": "下单人数", + "type": "integer" + }, + "RewardRatio": { + "description": "佣金比例", + "type": "number" + }, + "SellNum": { + "description": "销售数量", + "type": "integer" + }, + "SettleReward": { + "description": "结算佣金", + "type": "number" + }, + "TransitReward": { + "description": "在途佣金", + "type": "number" + }, + "Uv": { + "description": "浏览人数", + "type": "integer" + }, + "orderDoneNum": { + "description": "完成订单总数", + "type": "integer" + }, + "orderNum": { + "description": "订单总数", + "type": "integer" + } + } + }, + "dto.OrderData": { + "type": "object", + "properties": { + "all": { + "description": "全部", + "type": "integer" + }, + "cancel": { + "description": "已取消", + "type": "integer" + }, + "finished": { + "description": "已完成", + "type": "integer" + }, + "shipped": { + "description": "已发货", + "type": "integer" + }, + "unship": { + "description": "待发货", + "type": "integer" + } + } + }, + "global.BASE_ID": { + "type": "object", + "properties": { + "id": { + "description": "主键", + "type": "integer" + } + } + }, + "model.Account": { + "type": "object", + "properties": { + "account_name": { + "description": "户名", + "type": "string" + }, + "address": { + "description": "收款人地址", + "type": "string" + }, + "bank_code": { + "description": "收款行", + "type": "string" + }, + "card_number": { + "description": "银行卡号", + "type": "string" + }, + "country": { + "description": "国家/地区", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "currency": { + "description": "币种 USD:美元", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "idCard": { + "type": "string" + }, + "is_default": { + "description": "是否为默认 0:非默认 1:默认", + "type": "boolean" + }, + "phone": { + "type": "string" + }, + "platform": { + "description": "平台 saller(买家端) / customer(客户端) / influencer(网红端)", + "type": "string" + }, + "sort": { + "description": "排序值", + "type": "integer" + }, + "swift_code": { + "description": "银行国际代码", + "type": "string" + }, + "type": { + "description": "类型 1:paypal 2:银行卡", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userID": { + "description": "用户id", + "type": "string" + } + } + }, + "model.Address": { + "type": "object", + "properties": { + "bldg": { + "description": "apt,ste,bldg", + "type": "string" + }, + "city": { + "description": "city", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "default": { + "description": "是否默认地址 1-是 2-否", + "type": "integer" + }, + "firstName": { + "description": "first name", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "lastName": { + "description": "last name", + "type": "string" + }, + "phone": { + "description": "手机号", + "type": "string" + }, + "platform": { + "description": "平台 saller(买家端) / customer(客户端) / influencer(网红端)", + "type": "string" + }, + "state": { + "description": "state", + "type": "string" + }, + "street": { + "description": "street", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userId": { + "type": "string" + }, + "zipCode": { + "description": "zip code", + "type": "string" + } + } + }, + "model.Bill": { + "type": "object", + "properties": { + "account": { + "description": "收款账户(提现)", + "type": "string" + }, + "amount": { + "description": "数量", + "type": "integer" + }, + "balance": { + "description": "余额", + "type": "number" + }, + "check_status": { + "description": "审核状态 0:待审核 1:审核通过 2:审核未通过", + "type": "string" + }, + "claim_no": { + "description": "领取任务编号", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "order_id": { + "description": "关联订单id", + "type": "string" + }, + "platform": { + "description": "平台 seller(买家端) / customer(客户端) / influencer(网红端)", + "type": "string" + }, + "price": { + "description": "金额", + "type": "number" + }, + "receipt": { + "description": "是否已到账 1-是 2-否 3-已取消付款", + "type": "integer" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "status": { + "description": "类型 1-支出 2-收入", + "type": "integer" + }, + "title": { + "description": "账单标题", + "type": "string" + }, + "transaction_id": { + "description": "交易编号", + "type": "string" + }, + "type": { + "description": "类型 1-佣金 2-订单 3-提现 4-平台奖励", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userID": { + "description": "用户id", + "type": "string" + }, + "withd_id": { + "description": "提现id", + "type": "string" + }, + "withdrawalStatus": { + "description": "提现状态 0-提现中 1-提现完成 2-提现失败", + "type": "integer" + } + } + }, + "model.BillNotify": { + "type": "object", + "properties": { + "relation_id": { + "description": "关联id", + "type": "string" + }, + "relation_type": { + "description": "关联类型", + "type": "string" + }, + "title": { + "description": "标题", + "type": "string" + } + } + }, + "model.BillView": { + "type": "object", + "properties": { + "id": { + "description": "id", + "type": "integer" + }, + "order_id": { + "description": "订单编号", + "type": "string" + }, + "transaction_id": { + "description": "交易编号", + "type": "string" + } + } + }, + "model.Breadcrumb": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "is_leaf": { + "description": "是否叶子分类", + "type": "boolean" + }, + "name": { + "type": "string" + }, + "pid": { + "description": "父id", + "type": "integer" + } + } + }, + "model.Chain": { + "type": "object", + "properties": { + "address": { + "description": "合约地址", + "type": "string" + } + } + }, + "model.MissionBonus": { + "type": "object", + "properties": { + "total": { + "type": "number" + }, + "user_total": { + "type": "number" + } + } + }, + "model.MissionClaimDetail": { + "type": "object", + "properties": { + "achieve_num": { + "description": "已完成商品数量", + "type": "integer" + }, + "claim_no": { + "description": "领取任务编号", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "email": { + "description": "发送邮箱", + "type": "string" + }, + "expire_at": { + "description": "任务推广过期时间", + "type": "string" + }, + "finished": { + "description": "任务完成状态 0:未完成 1:已完成", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "mission": { + "description": "关联任务", + "allOf": [ + { + "$ref": "#/definitions/model.MissionDetail" + } + ] + }, + "mission_id": { + "description": "任务id", + "type": "integer" + }, + "order": { + "description": "任务订单", + "allOf": [ + { + "$ref": "#/definitions/model.MissionClaimOrderInfo" + } + ] + }, + "spread_url": { + "description": "推广链接", + "type": "string" + }, + "status": { + "description": "状态 1:已领取待发货 2:已发货 3:已收货推广中", + "type": "integer" + }, + "status_except": { + "description": "状态描述", + "type": "string" + }, + "total_bonus": { + "description": "累计佣金", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "video": { + "description": "上传视频", + "allOf": [ + { + "$ref": "#/definitions/model.MissionClaimVideo" + } + ] + }, + "works": { + "description": "发布作品", + "type": "array", + "items": { + "$ref": "#/definitions/model.MissionClaimWorks" + } + } + } + }, + "model.MissionClaimOrderGoods": { + "type": "object", + "properties": { + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "image": { + "description": "规格图片url", + "type": "string" + }, + "order_id": { + "description": "订单号", + "type": "string" + }, + "price": { + "description": "价格", + "type": "number" + }, + "sku_no": { + "description": "sku编号", + "type": "string" + }, + "specs": { + "description": "规格", + "type": "string" + }, + "title": { + "description": "名称", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.MissionClaimOrderInfo": { + "type": "object", + "properties": { + "courier": { + "description": "快递公司", + "type": "string" + }, + "courier_number": { + "description": "快递单号", + "type": "string" + }, + "courier_url": { + "description": "快递查询地址", + "type": "string" + }, + "deliver": { + "description": "发货信息", + "allOf": [ + { + "$ref": "#/definitions/model.OrderDeliver" + } + ] + }, + "mission_claim_id": { + "description": "领取任务id", + "type": "integer" + }, + "order_goods": { + "description": "订单商品信息", + "allOf": [ + { + "$ref": "#/definitions/model.MissionClaimOrderGoods" + } + ] + }, + "order_id": { + "description": "订单号", + "type": "string" + }, + "send_time": { + "description": "发货时间", + "type": "string" + }, + "status": { + "description": "订单状态 2:待发货 3:已发货", + "type": "integer" + } + } + }, + "model.MissionClaimVideo": { + "type": "object", + "properties": { + "cover": { + "description": "视频封面", + "type": "string" + }, + "create_by": { + "description": "创建人", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "height": { + "description": "高度", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "mission_claim_id": { + "description": "领取任务id", + "type": "integer" + }, + "mission_id": { + "description": "任务ID", + "type": "integer" + }, + "remark": { + "type": "string" + }, + "reward_status": { + "description": "奖励发放状态 1:未发放 2:已发放", + "type": "integer" + }, + "source_type": { + "description": "类型:1:固定费用上传 2:奖励任务上传 3:后台上传", + "type": "integer" + }, + "status": { + "description": "状态 1:待审核 2:审核通过 3:审核不通过", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "video_url": { + "description": "视频上传地址", + "type": "string" + }, + "width": { + "description": "宽度", + "type": "integer" + } + } + }, + "model.MissionClaimWorks": { + "type": "object", + "properties": { + "created_at": { + "description": "创建时间", + "type": "string" + }, + "homepage": { + "description": "作品主页地址", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "image": { + "description": "作品凭证截图", + "type": "string" + }, + "mission_claim_id": { + "description": "领取任务id", + "type": "integer" + }, + "type": { + "description": "平台 1:ins 2:YouTube 3:tiktok 4:Facebook 5:Twitter", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "video_url": { + "description": "视频上传地址", + "type": "string" + } + } + }, + "model.MissionDetail": { + "type": "object", + "properties": { + "claim_days": { + "description": "任务完成天数", + "type": "integer" + }, + "claim_demands": { + "description": "任务拍摄要求", + "type": "string" + }, + "claim_num": { + "description": "接任务人数", + "type": "integer" + }, + "claim_status_except": { + "description": "可接任务状态描述", + "type": "string" + }, + "claim_status_except_eng": { + "description": "英文版状态描述", + "type": "string" + }, + "claim_stock": { + "description": "可接任务库存", + "type": "integer" + }, + "collect_status": { + "description": "收藏状态 true:已收藏 false:未收藏", + "type": "boolean" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "description": { + "description": "描述/卖点", + "type": "string" + }, + "end_time": { + "description": "任务结束时间", + "type": "string" + }, + "goods": { + "description": "商品信息", + "allOf": [ + { + "$ref": "#/definitions/model.TbGoodsSpecsView" + } + ] + }, + "goods_status": { + "description": "关联商品状态 1:正常 2:已下架", + "type": "integer" + }, + "goods_url": { + "description": "商品链接", + "type": "string" + }, + "has_sample": { + "description": "是否有样品 0:没有 1:有", + "type": "integer" + }, + "has_video": { + "description": "是否有视频素材 0:没有 1:有", + "type": "integer" + }, + "hire_money": { + "description": "hire_type==1 佣金金额", + "type": "number" + }, + "hire_money_expect": { + "description": "预计佣金描述", + "type": "string" + }, + "hire_ratio": { + "description": "hire_type==2 抽成比例", + "type": "number" + }, + "hire_type": { + "description": "佣金类型 1:固定佣金 2:比例抽成", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "num": { + "description": "商品数量", + "type": "integer" + }, + "release_channels": { + "description": "发布渠道", + "type": "string" + }, + "release_country": { + "description": "发布国家", + "type": "string" + }, + "sample_num": { + "description": "样品数量", + "type": "integer" + }, + "start_time": { + "description": "任务起始时间", + "type": "string" + }, + "status": { + "description": "状态 1:未开始 2:进行中 3:已结束", + "type": "integer" + }, + "store": { + "description": "商家信息", + "allOf": [ + { + "$ref": "#/definitions/model.SellerStoreInfo" + } + ] + }, + "title": { + "description": "标题", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "video_channel_ids": { + "description": "视频发布渠道,多个渠道英文逗号连接", + "type": "string" + }, + "video_country_id": { + "description": "视频发布国家", + "type": "string" + }, + "video_url": { + "type": "string" + } + } + }, + "model.OrderAddress": { + "type": "object", + "properties": { + "bldg": { + "description": "apt,ste,bldg", + "type": "string" + }, + "city": { + "description": "city", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "default": { + "description": "是否默认地址 1-是 2-否", + "type": "integer" + }, + "firstName": { + "description": "first name", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "lastName": { + "description": "last name", + "type": "string" + }, + "orderID": { + "type": "string" + }, + "phone": { + "description": "手机号", + "type": "string" + }, + "platform": { + "description": "平台 saller(买家端) / customer(客户端) / influencer(网红端)", + "type": "string" + }, + "state": { + "description": "state", + "type": "string" + }, + "street": { + "description": "street", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userId": { + "type": "string" + }, + "zipCode": { + "description": "zip code", + "type": "string" + } + } + }, + "model.OrderDeliver": { + "type": "object", + "properties": { + "courier": { + "description": "快递公司", + "type": "string" + }, + "courierLink": { + "description": "快递链接", + "type": "string" + }, + "courierNumber": { + "description": "快递单号", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "orderID": { + "description": "订单号", + "type": "string" + }, + "track_id": { + "description": "track表id", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.OrderDetail": { + "type": "object", + "properties": { + "IAmount": { + "description": "网红佣金", + "type": "string" + }, + "address": { + "description": "地址", + "allOf": [ + { + "$ref": "#/definitions/model.OrderAddress" + } + ] + }, + "bill": { + "description": "交易信息", + "allOf": [ + { + "$ref": "#/definitions/model.BillView" + } + ] + }, + "captureID": { + "description": "paypal收款确认id", + "type": "string" + }, + "chain": { + "description": "区块链", + "allOf": [ + { + "$ref": "#/definitions/model.Chain" + } + ] + }, + "code": { + "description": "网红码?", + "type": "string" + }, + "commodID": { + "description": "商品id", + "type": "integer" + }, + "confirmTime": { + "description": "收货时间", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "deliver": { + "description": "发货信息", + "allOf": [ + { + "$ref": "#/definitions/model.OrderDeliver" + } + ] + }, + "goods": { + "description": "商品信息", + "allOf": [ + { + "$ref": "#/definitions/model.OrderGoodsDetail" + } + ] + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "number": { + "description": "数量", + "type": "integer" + }, + "orderID": { + "description": "订单号", + "type": "string" + }, + "paidPrice": { + "description": "实付价格", + "type": "number" + }, + "payTime": { + "description": "付款时间", + "type": "string" + }, + "paypalID": { + "description": "paypal订单号", + "type": "string" + }, + "platform": { + "description": "购买平台", + "type": "string" + }, + "postSale": { + "description": "售后信息", + "allOf": [ + { + "$ref": "#/definitions/model.PostSale" + } + ] + }, + "price": { + "description": "商品价格", + "type": "number" + }, + "sendTime": { + "description": "发货时间", + "type": "string" + }, + "sku_id": { + "description": "商品规格编号", + "type": "integer" + }, + "sku_no": { + "description": "商品规格编号", + "type": "string" + }, + "status": { + "description": "订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消", + "type": "integer" + }, + "store": { + "description": "店铺信息", + "allOf": [ + { + "$ref": "#/definitions/model.SellerStoreInfo" + } + ] + }, + "store_no": { + "description": "店铺编号", + "type": "string" + }, + "type": { + "description": "类型 1-普通订单 2-预售订单", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userID": { + "description": "用户id", + "type": "string" + } + } + }, + "model.OrderGoodsDetail": { + "type": "object", + "properties": { + "attributes": { + "description": "规格详情", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbAttributeWithValues" + } + }, + "content": { + "description": "详情", + "type": "string" + }, + "content_text": { + "description": "详情-文字", + "type": "string" + }, + "cover": { + "description": "封面图", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "goods_specs": { + "description": "规格", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbOrderGoodsSpecsDetail" + } + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "images": { + "description": "图片", + "type": "string" + }, + "orderID": { + "description": "订单id", + "type": "string" + }, + "price_max": { + "description": "最高规格价格", + "type": "number" + }, + "price_min": { + "description": "最低规格价格", + "type": "number" + }, + "retail_price": { + "description": "吊牌价(零售指导价)", + "type": "number" + }, + "sku_no": { + "description": "商品规格编号", + "type": "string" + }, + "specs": { + "description": "规格", + "type": "string" + }, + "spu_no": { + "description": "编号", + "type": "string" + }, + "store_no": { + "description": "店铺编号", + "type": "string" + }, + "title": { + "description": "名称", + "type": "string" + }, + "title_eng": { + "description": "英文名称", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.OrderList": { + "type": "object", + "properties": { + "IAmount": { + "description": "网红佣金", + "type": "string" + }, + "captureID": { + "description": "paypal收款确认id", + "type": "string" + }, + "code": { + "description": "网红码?", + "type": "string" + }, + "commodID": { + "description": "商品id", + "type": "integer" + }, + "confirmTime": { + "description": "收货时间", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "goods": { + "description": "商品信息", + "allOf": [ + { + "$ref": "#/definitions/model.OrderGoodsDetail" + } + ] + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "number": { + "description": "数量", + "type": "integer" + }, + "orderID": { + "description": "订单号", + "type": "string" + }, + "paidPrice": { + "description": "实付价格", + "type": "number" + }, + "payTime": { + "description": "付款时间", + "type": "string" + }, + "paypalID": { + "description": "paypal订单号", + "type": "string" + }, + "platform": { + "description": "购买平台", + "type": "string" + }, + "price": { + "description": "商品价格", + "type": "number" + }, + "sendTime": { + "description": "发货时间", + "type": "string" + }, + "sku_id": { + "description": "商品规格编号", + "type": "integer" + }, + "sku_no": { + "description": "商品规格编号", + "type": "string" + }, + "status": { + "description": "订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消", + "type": "integer" + }, + "store_no": { + "description": "店铺编号", + "type": "string" + }, + "type": { + "description": "类型 1-普通订单 2-预售订单", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "user": { + "description": "买家信息", + "allOf": [ + { + "$ref": "#/definitions/model.UserSimple" + } + ] + }, + "userID": { + "description": "用户id", + "type": "string" + } + } + }, + "model.PostSale": { + "type": "object", + "properties": { + "created_at": { + "description": "创建时间", + "type": "string" + }, + "examine_time": { + "description": "审核时间", + "type": "string" + }, + "id": { + "description": "id", + "type": "integer" + }, + "orderId": { + "description": "订单id", + "type": "string" + }, + "refundStatus": { + "description": "退款状态 1:退款中 2:退款成功 3:退款失败", + "type": "integer" + }, + "refund_time": { + "description": "退款时间", + "type": "string" + }, + "remark": { + "description": "审核原因", + "type": "string" + }, + "status": { + "description": "处理状态 1:已提交 2:已处理 3:已拒绝 4:已撤回", + "type": "integer" + } + } + }, + "model.SellerStoreInfo": { + "type": "object", + "properties": { + "email": { + "description": "店铺联系email(注册账号email)", + "type": "string" + }, + "store_no": { + "description": "店铺编号", + "type": "string" + }, + "type": { + "description": "1:个人店铺", + "type": "integer" + } + } + }, + "model.SysMissionReward": { + "type": "object", + "properties": { + "achieve_num": { + "description": "已完成任务次数", + "type": "integer" + }, + "audit_by": { + "description": "审核人", + "type": "string" + }, + "bonus": { + "description": "奖励金额", + "type": "number" + }, + "create_by": { + "description": "创建人", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "relationId": { + "description": "关联项目id", + "type": "string" + }, + "status": { + "description": "状态 1待发放 2已发放 3已领取", + "type": "integer" + }, + "title": { + "description": "标题", + "type": "string" + }, + "type": { + "description": "奖励类型 1.视频上传 2.信息完善 3.商家任务", + "type": "integer" + }, + "update_by": { + "description": "更新人", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.TbAttributeDetail": { + "type": "object", + "properties": { + "attribute_id": { + "description": "规格属性id", + "type": "integer" + }, + "value": { + "type": "string" + }, + "value_id": { + "type": "integer" + } + } + }, + "model.TbAttributeValueItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "image": { + "description": "图片", + "type": "string" + }, + "name": { + "description": "规格属性值", + "type": "string" + } + } + }, + "model.TbAttributeWithValues": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "values": { + "type": "array", + "items": { + "$ref": "#/definitions/model.TbAttributeValueItem" + } + } + } + }, + "model.TbGoodsDetail": { + "type": "object", + "properties": { + "attributes": { + "description": "规格详情", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbAttributeWithValues" + } + }, + "breadcrumb": { + "description": "分类面包屑", + "type": "array", + "items": { + "$ref": "#/definitions/model.Breadcrumb" + } + }, + "category_id": { + "description": "分类id", + "type": "integer" + }, + "collect_status": { + "description": "收藏状态 true:已收藏 false:未收藏", + "type": "boolean" + }, + "content": { + "description": "商品详情", + "type": "string" + }, + "content_text": { + "description": "详情-文字", + "type": "string" + }, + "cover": { + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "images": { + "description": "图片", + "type": "string" + }, + "list_price": { + "description": "列表价格", + "type": "number" + }, + "online": { + "description": "上下架状态 on/off", + "type": "string" + }, + "price_max": { + "description": "最高规格价格", + "type": "number" + }, + "price_min": { + "description": "最低规格价格", + "type": "number" + }, + "retail_price": { + "description": "吊牌价(零售指导价)", + "type": "number" + }, + "specs": { + "description": "规格", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbGoodsSpecsDetail" + } + }, + "spu_no": { + "description": "编号", + "type": "string" + }, + "tags": { + "description": "标签", + "type": "string" + }, + "title": { + "description": "标题", + "type": "string" + }, + "title_eng": { + "description": "英文标题", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.TbGoodsSpecsDetail": { + "type": "object", + "properties": { + "attributes": { + "description": "规格详情", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbAttributeDetail" + } + }, + "code": { + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "goods_id": { + "type": "integer" + }, + "goods_no": { + "description": "商品编号", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "image": { + "description": "规格图片url", + "type": "string" + }, + "price": { + "description": "价格", + "type": "number" + }, + "sku_no": { + "description": "商品编码", + "type": "string" + }, + "specs": { + "description": "规格", + "type": "string" + }, + "stock": { + "description": "库存", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.TbGoodsSpecsView": { + "type": "object", + "properties": { + "attributes": { + "description": "规格详情", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbAttributeWithValues" + } + }, + "cover": { + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "images": { + "description": "图片", + "type": "string" + }, + "price_max": { + "description": "最高规格价格", + "type": "number" + }, + "price_min": { + "description": "最低规格价格", + "type": "number" + }, + "retail_price": { + "description": "吊牌价(零售指导价)", + "type": "number" + }, + "sales": { + "description": "总销售量", + "type": "integer" + }, + "specs": { + "description": "规格", + "type": "array", + "items": { + "$ref": "#/definitions/model.TbGoodsSpecsDetail" + } + }, + "spu_no": { + "description": "编号", + "type": "string" + }, + "stock": { + "description": "总库存", + "type": "integer" + }, + "tags": { + "description": "标签", + "type": "string" + }, + "title": { + "description": "标题", + "type": "string" + }, + "title_eng": { + "description": "英文标题", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + } + } + }, + "model.TbOrderGoodsSpecsDetail": { + "type": "object", + "properties": { + "code": { + "description": "attribute定位标识", + "type": "string" + }, + "goods_id": { + "type": "integer" + }, + "goods_no": { + "description": "商品编号", + "type": "string" + }, + "image": { + "description": "规格图片url", + "type": "string" + }, + "orderGoodsId": { + "type": "integer" + }, + "price": { + "description": "价格", + "type": "number" + }, + "sku_no": { + "description": "Attributes []TbAttributeDetail `gorm:\"-\" json:\"-\"` // 规格详情", + "type": "string" + }, + "specs": { + "description": "规格", + "type": "string" + } + } + }, + "model.UsCitys": { + "type": "object", + "properties": { + "city": { + "type": "string" + }, + "county": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "idState": { + "type": "integer" + } + } + }, + "model.UsSelect": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UsCitys" + } + }, + "id": { + "type": "integer" + }, + "stateCode": { + "type": "string" + }, + "stateName": { + "type": "string" + } + } + }, + "model.UserSimple": { + "type": "object", + "properties": { + "avatar": { + "description": "头像", + "type": "string" + }, + "email": { + "description": "用户邮箱", + "type": "string" + }, + "nick_name": { + "description": "昵称", + "type": "string" + }, + "phone": { + "description": "手机号", + "type": "string" + }, + "platform": { + "description": "平台", + "type": "array", + "items": { + "$ref": "#/definitions/request.Platform" + } + }, + "tags": { + "description": "个人标签", + "type": "string" + }, + "uuid": { + "description": "用户uuid编码", + "type": "string" + } + } + }, + "model.Wallet": { + "type": "object", + "properties": { + "balance": { + "description": "可用余额", + "type": "number" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "platform": { + "description": "平台 saller(买家端) / customer(客户端) / influencer(网红端)", + "type": "string" + }, + "state": { + "description": "状态 0:正常 1:限制提现 2:禁止提现", + "type": "integer" + }, + "transitBalance": { + "description": "在途余额", + "type": "number" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "userId": { + "type": "string" + } + } + }, + "model.Withdrawal": { + "type": "object", + "properties": { + "account_name": { + "description": "户名", + "type": "string" + }, + "account_type": { + "description": "账户类型 1:paypal 2:银行卡", + "type": "integer" + }, + "address": { + "description": "收款人地址", + "type": "string" + }, + "amount": { + "description": "金额", + "type": "number" + }, + "bank_code": { + "description": "收款行", + "type": "string" + }, + "bill_no": { + "description": "账单号", + "type": "string" + }, + "card_number": { + "description": "银行卡号", + "type": "string" + }, + "check_status": { + "description": "审核状态 0:待审核 1:审核通过 2:审核未通过", + "type": "string" + }, + "check_time": { + "description": "审核时间", + "type": "string" + }, + "country": { + "description": "国家/地区", + "type": "string" + }, + "create_by": { + "description": "创建人/店铺", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "currency": { + "description": "币种 USD:美元", + "type": "string" + }, + "flow_no": { + "description": "流水号", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "pay_id": { + "description": "支付id", + "type": "string" + }, + "platform": { + "description": "平台 1:网红 2:商家", + "type": "string" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "status": { + "description": "提现状态 0:进行中 1:成功 2:失败", + "type": "string" + }, + "swift_code": { + "description": "银行国际代码", + "type": "string" + }, + "title": { + "description": "标题", + "type": "string" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "wallet_type": { + "description": "钱包类型 1:余额钱包 2:营销账户钱包", + "type": "integer" + } + } + }, + "model.WithdrawalView": { + "type": "object", + "properties": { + "flow_no": { + "description": "流水号", + "type": "string" + } + } + }, + "request.AddAccount": { + "type": "object", + "properties": { + "account_name": { + "description": "户名", + "type": "string" + }, + "address": { + "description": "收款人地址", + "type": "string" + }, + "bank_card": { + "description": "银行卡号", + "type": "string" + }, + "bank_code": { + "description": "银行编码", + "type": "string" + }, + "country": { + "description": "国家/地区", + "type": "string" + }, + "currency": { + "description": "币种 USD: 美元", + "type": "string" + }, + "is_default": { + "description": "是否默认", + "type": "boolean" + }, + "swift_code": { + "description": "swift编码", + "type": "string" + } + } + }, + "request.ClaimMission": { + "type": "object", + "properties": { + "address_id": { + "description": "收货地址id", + "type": "integer" + }, + "email": { + "description": "邮箱地址", + "type": "string" + }, + "mission_id": { + "description": "任务id", + "type": "integer" + }, + "sku_no": { + "description": "商品sku_no", + "type": "string" + }, + "spu_no": { + "description": "商品spu_no", + "type": "string" + } + } + }, + "request.ClaimMissionVideo": { + "type": "object", + "properties": { + "cover": { + "type": "string" + }, + "height": { + "description": "高度", + "type": "integer" + }, + "mission_claim_id": { + "description": "领取任务id", + "type": "integer" + }, + "source_type": { + "description": "类型:1:固定费用上传 2:奖励任务上传 3:后台上传", + "type": "integer" + }, + "video_url": { + "description": "视频上传地址", + "type": "string" + }, + "width": { + "description": "宽度", + "type": "integer" + } + } + }, + "request.ClaimMissionWorks": { + "type": "object", + "properties": { + "homepage": { + "description": "作品主页地址", + "type": "string" + }, + "id": { + "description": "id", + "type": "integer" + }, + "image": { + "description": "作品凭证截图", + "type": "string" + }, + "type": { + "description": "平台 1:ins 2:Pinterest 3:tk 4:Twitter 5:Facebook 6:Reddit", + "type": "integer" + }, + "video_url": { + "description": "视频上传地址", + "type": "string" + } + } + }, + "request.ClaimMissionWorksList": { + "type": "object", + "properties": { + "mission_claim_id": { + "description": "领取任务id", + "type": "integer" + }, + "works": { + "description": "作品列表", + "type": "array", + "items": { + "$ref": "#/definitions/request.ClaimMissionWorks" + } + } + } + }, + "request.DeleteAccount": { + "type": "object", + "properties": { + "code": { + "description": "验证码", + "type": "string" + }, + "id": { + "description": "主键", + "type": "integer" + }, + "phone": { + "description": "手机号", + "type": "string" + } + } + }, + "request.IdReq": { + "type": "object", + "properties": { + "id": { + "description": "id", + "type": "integer" + } + } + }, + "request.MissionId": { + "type": "object", + "properties": { + "mission_id": { + "description": "任务", + "type": "integer" + } + } + }, + "request.Platform": { + "type": "object", + "properties": { + "image": { + "description": "图片", + "type": "string" + }, + "is_auth": { + "description": "是否认证", + "type": "boolean" + }, + "label": { + "type": "string" + }, + "platform": { + "description": "平台 字典表获取", + "type": "string" + }, + "url": { + "description": "主页地址", + "type": "string" + } + } + }, + "request.SendEmail": { + "type": "object", + "properties": { + "email": { + "type": "string" + } + } + }, + "request.SendMessage": { + "type": "object", + "properties": { + "country_code": { + "description": "用户手机号国家代码 国际区号 86 中国 1美国", + "type": "string" + }, + "phone": { + "type": "string" + }, + "type": { + "description": "1:登录验证码 2-解绑 3-绑定 4-提现", + "type": "integer" + } + } + }, + "request.UserAuthorized": { + "type": "object", + "properties": { + "appid": { + "description": "应用id", + "type": "string" + }, + "client": { + "description": "客户端 ios android web", + "type": "string" + }, + "code": { + "description": "授权码", + "type": "string" + }, + "platform": { + "description": "平台 google facebook twitter tiktok", + "type": "string" + }, + "token": { + "description": "token", + "type": "string" + }, + "uuid": { + "description": "设备唯一标识", + "type": "string" + } + } + }, + "request.UserBandPhone": { + "type": "object", + "properties": { + "code": { + "description": "验证码", + "type": "string" + }, + "phone": { + "description": "手机号", + "type": "string" + } + } + }, + "request.UserDetail": { + "type": "object", + "properties": { + "platform": { + "description": "平台及地址逗号隔开 eg:(ins:https://baidu.com/user/1,qq:12345678)", + "type": "string" + }, + "tags": { + "description": "个人标签", + "type": "string" + }, + "type": { + "description": "修改字段 platform-平台 tags-个人标签", + "type": "string" + } + } + }, + "request.UserLogin": { + "type": "object", + "properties": { + "appid": { + "description": "应用id", + "type": "string" + }, + "code": { + "description": "验证码", + "type": "string" + }, + "country_code": { + "description": "用户手机号国家代码 国际区号 86 中国 1美国", + "type": "string" + }, + "email": { + "description": "邮箱", + "type": "string" + }, + "password": { + "description": "密码", + "type": "string" + }, + "phone": { + "description": "手机号", + "type": "string" + }, + "type": { + "description": "1-手机号 2-邮箱", + "type": "string" + } + } + }, + "request.UserPlatformAuth": { + "type": "object", + "properties": { + "platform": { + "description": "平台", + "allOf": [ + { + "$ref": "#/definitions/request.Platform" + } + ] + }, + "tags": { + "description": "个人标签", + "type": "string" + } + } + }, + "request.UserRegister": { + "type": "object", + "properties": { + "appid": { + "description": "应用id", + "type": "string" + }, + "avatar": { + "description": "头像", + "type": "string" + }, + "code": { + "description": "验证码", + "type": "string" + }, + "country_code": { + "description": "用户手机号国家代码 国际区号 86 中国 1美国", + "type": "string" + }, + "email": { + "description": "邮箱", + "type": "string" + }, + "nickname": { + "description": "昵称", + "type": "string" + } + } + }, + "request.WithdrawalParams": { + "type": "object", + "properties": { + "accountID": { + "description": "提现账户id", + "type": "integer" + }, + "amount": { + "description": "Code string `json:\"code\"` // 验证码", + "type": "number" + } + } + }, + "response.BannerListResponse": { + "type": "object", + "properties": { + "coverUrl": { + "description": "封面图", + "type": "string" + }, + "id": { + "description": "主键", + "type": "integer" + }, + "link": { + "description": "链接地址", + "type": "string" + }, + "linkType": { + "description": "链接类型 0:内链 1:外链", + "type": "string" + }, + "relationId": { + "description": "关联项目id", + "type": "string" + }, + "relationType": { + "description": "关联类型 01-任务", + "type": "string" + }, + "sort_index": { + "description": "序号索引", + "type": "integer" + }, + "status": { + "description": "状态 0=下架 1=上架", + "type": "string" + }, + "title": { + "description": "标题", + "type": "string" + }, + "type": { + "description": "任务-0101 平台奖励页-0102", + "type": "string" + } + } + }, + "response.ChainResp": { + "type": "object", + "properties": { + "block_adress": { + "description": "所在区块", + "type": "string" + }, + "block_height": { + "description": "块高度", + "type": "integer" + }, + "hash": { + "description": "交易哈希", + "type": "string" + }, + "time": { + "description": "上链时间", + "type": "string" + } + } + }, + "response.MissionRecommendResponse": { + "type": "object", + "properties": { + "achieve_num": { + "description": "已完成商品数量", + "type": "integer" + }, + "bought_num": { + "description": "购买人数", + "type": "number" + }, + "claim_num": { + "description": "任务领取人数", + "type": "integer" + }, + "cover": { + "description": "封面", + "type": "string" + }, + "create_by": { + "description": "创建人", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "end_time": { + "description": "任务结束时间", + "type": "string" + }, + "goods_title": { + "description": "商品标题", + "type": "string" + }, + "goods_title_eng": { + "description": "商品英文标题", + "type": "string" + }, + "height": { + "description": "高度", + "type": "integer" + }, + "hire_money": { + "description": "hire_type==1 佣金金额", + "type": "number" + }, + "hire_money_expect": { + "description": "预计佣金描述", + "type": "string" + }, + "hire_ratio": { + "description": "hire_type==2 抽成比例", + "type": "number" + }, + "hire_type": { + "description": "佣金类型 1:固定佣金 2:比例抽成", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "influencer": { + "$ref": "#/definitions/model.UserSimple" + }, + "mission_id": { + "description": "任务ID", + "type": "integer" + }, + "mission_status": { + "description": "任务状态", + "type": "integer" + }, + "relation_id": { + "description": "关联ID,任务视频ID", + "type": "integer" + }, + "release_channels": { + "description": "发布渠道", + "type": "string" + }, + "release_country": { + "description": "发布国家", + "type": "string" + }, + "sort": { + "description": "倒序 //排序", + "type": "integer" + }, + "start_time": { + "description": "任务起始时间", + "type": "string" + }, + "status": { + "description": "状态 1:上架 2:下架", + "type": "integer" + }, + "tag": { + "description": "todo 标签系统", + "type": "string" + }, + "title": { + "description": "任务标题", + "type": "string" + }, + "total_bonus": { + "description": "累计奖励", + "type": "number" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "video_url": { + "description": "视频地址", + "type": "string" + }, + "width": { + "description": "宽度", + "type": "integer" + } + } + }, + "response.SysBonusDetail": { + "type": "object", + "properties": { + "achieve_max": { + "description": "最大完成次数", + "type": "integer" + }, + "achieve_num": { + "description": "已完成任务次数", + "type": "integer" + }, + "bonus": { + "description": "奖金", + "type": "number" + }, + "mission_list": { + "description": "任务列表", + "type": "array", + "items": { + "$ref": "#/definitions/response.SysMissionDesc" + } + }, + "title": { + "description": "标题", + "type": "string" + }, + "total": { + "description": "奖励次数", + "type": "integer" + }, + "type": { + "description": "奖励类型 1.视频上传 2.信息完善 3.商家任务", + "type": "integer" + } + } + }, + "response.SysMissionBonus": { + "type": "object", + "properties": { + "total": { + "description": "奖励总笔数", + "type": "integer" + }, + "total_bonus": { + "description": "奖励汇总金额", + "type": "number" + }, + "video_bonus": { + "description": "视频上传", + "allOf": [ + { + "$ref": "#/definitions/response.SysBonusDetail" + } + ] + } + } + }, + "response.SysMissionDesc": { + "type": "object", + "properties": { + "achieve_num": { + "type": "integer" + }, + "bonus": { + "description": "奖励金额", + "type": "number" + }, + "description": { + "description": "描述", + "type": "string" + }, + "description_eng": { + "description": "描述英文", + "type": "string" + }, + "status": { + "description": "状态 1待发放 2已发放 3已领取 0未完成", + "type": "integer" + }, + "title": { + "description": "任务标题", + "type": "string" + }, + "title_eng": { + "description": "任务标题英文", + "type": "string" + } + } + }, + "response.UserStatistics": { + "type": "object", + "properties": { + "claim_mission_num": { + "description": "领取任务数量", + "type": "integer" + }, + "collection_mission_num": { + "description": "收藏任务数量", + "type": "integer" + }, + "platform_num": { + "description": "认证平台数量", + "type": "integer" + } + } + } + }, + "securityDefinitions": { + "ApiKeyAuth": { + "type": "apiKey", + "name": "x-token", + "in": "header" + } + } +} \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..4187061 --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,2897 @@ +definitions: + dto.BillData: + properties: + cancelOrderMoney: + description: 退款订单总额 + type: number + cancelOrderNum: + description: 退款订单数 + type: integer + flowExpend: + description: 出账 + type: number + flowIncome: + description: 进账 + type: number + income: + description: 收入总额 + type: number + orderMoney: + description: 订单总额 + type: number + orderNum: + description: 订单数 + type: integer + rewardUnfinished: + description: 在途佣金 + type: number + type: object + dto.MissionOrderStatistic: + properties: + OrderMoney: + description: 订单金额 + type: number + OrderUserNum: + description: 下单人数 + type: integer + RewardRatio: + description: 佣金比例 + type: number + SellNum: + description: 销售数量 + type: integer + SettleReward: + description: 结算佣金 + type: number + TransitReward: + description: 在途佣金 + type: number + Uv: + description: 浏览人数 + type: integer + orderDoneNum: + description: 完成订单总数 + type: integer + orderNum: + description: 订单总数 + type: integer + type: object + dto.OrderData: + properties: + all: + description: 全部 + type: integer + cancel: + description: 已取消 + type: integer + finished: + description: 已完成 + type: integer + shipped: + description: 已发货 + type: integer + unship: + description: 待发货 + type: integer + type: object + global.BASE_ID: + properties: + id: + description: 主键 + type: integer + type: object + model.Account: + properties: + account_name: + description: 户名 + type: string + address: + description: 收款人地址 + type: string + bank_code: + description: 收款行 + type: string + card_number: + description: 银行卡号 + type: string + country: + description: 国家/地区 + type: string + created_at: + description: 创建时间 + type: string + currency: + description: 币种 USD:美元 + type: string + id: + description: 主键ID + type: integer + idCard: + type: string + is_default: + description: 是否为默认 0:非默认 1:默认 + type: boolean + phone: + type: string + platform: + description: 平台 saller(买家端) / customer(客户端) / influencer(网红端) + type: string + sort: + description: 排序值 + type: integer + swift_code: + description: 银行国际代码 + type: string + type: + description: 类型 1:paypal 2:银行卡 + type: integer + updated_at: + description: 更新时间 + type: string + userID: + description: 用户id + type: string + type: object + model.Address: + properties: + bldg: + description: apt,ste,bldg + type: string + city: + description: city + type: string + created_at: + description: 创建时间 + type: string + default: + description: 是否默认地址 1-是 2-否 + type: integer + firstName: + description: first name + type: string + id: + description: 主键ID + type: integer + lastName: + description: last name + type: string + phone: + description: 手机号 + type: string + platform: + description: 平台 saller(买家端) / customer(客户端) / influencer(网红端) + type: string + state: + description: state + type: string + street: + description: street + type: string + updated_at: + description: 更新时间 + type: string + userId: + type: string + zipCode: + description: zip code + type: string + type: object + model.Bill: + properties: + account: + description: 收款账户(提现) + type: string + amount: + description: 数量 + type: integer + balance: + description: 余额 + type: number + check_status: + description: 审核状态 0:待审核 1:审核通过 2:审核未通过 + type: string + claim_no: + description: 领取任务编号 + type: string + created_at: + description: 创建时间 + type: string + id: + description: 主键ID + type: integer + order_id: + description: 关联订单id + type: string + platform: + description: 平台 seller(买家端) / customer(客户端) / influencer(网红端) + type: string + price: + description: 金额 + type: number + receipt: + description: 是否已到账 1-是 2-否 3-已取消付款 + type: integer + remark: + description: 备注 + type: string + status: + description: 类型 1-支出 2-收入 + type: integer + title: + description: 账单标题 + type: string + transaction_id: + description: 交易编号 + type: string + type: + description: 类型 1-佣金 2-订单 3-提现 4-平台奖励 + type: string + updated_at: + description: 更新时间 + type: string + userID: + description: 用户id + type: string + withd_id: + description: 提现id + type: string + withdrawalStatus: + description: 提现状态 0-提现中 1-提现完成 2-提现失败 + type: integer + type: object + model.BillNotify: + properties: + relation_id: + description: 关联id + type: string + relation_type: + description: 关联类型 + type: string + title: + description: 标题 + type: string + type: object + model.BillView: + properties: + id: + description: id + type: integer + order_id: + description: 订单编号 + type: string + transaction_id: + description: 交易编号 + type: string + type: object + model.Breadcrumb: + properties: + id: + type: integer + is_leaf: + description: 是否叶子分类 + type: boolean + name: + type: string + pid: + description: 父id + type: integer + type: object + model.Chain: + properties: + address: + description: 合约地址 + type: string + type: object + model.MissionBonus: + properties: + total: + type: number + user_total: + type: number + type: object + model.MissionClaimDetail: + properties: + achieve_num: + description: 已完成商品数量 + type: integer + claim_no: + description: 领取任务编号 + type: string + created_at: + description: 创建时间 + type: string + email: + description: 发送邮箱 + type: string + expire_at: + description: 任务推广过期时间 + type: string + finished: + description: 任务完成状态 0:未完成 1:已完成 + type: integer + id: + description: 主键ID + type: integer + mission: + allOf: + - $ref: '#/definitions/model.MissionDetail' + description: 关联任务 + mission_id: + description: 任务id + type: integer + order: + allOf: + - $ref: '#/definitions/model.MissionClaimOrderInfo' + description: 任务订单 + spread_url: + description: 推广链接 + type: string + status: + description: 状态 1:已领取待发货 2:已发货 3:已收货推广中 + type: integer + status_except: + description: 状态描述 + type: string + total_bonus: + description: 累计佣金 + type: integer + updated_at: + description: 更新时间 + type: string + video: + allOf: + - $ref: '#/definitions/model.MissionClaimVideo' + description: 上传视频 + works: + description: 发布作品 + items: + $ref: '#/definitions/model.MissionClaimWorks' + type: array + type: object + model.MissionClaimOrderGoods: + properties: + created_at: + description: 创建时间 + type: string + id: + description: 主键ID + type: integer + image: + description: 规格图片url + type: string + order_id: + description: 订单号 + type: string + price: + description: 价格 + type: number + sku_no: + description: sku编号 + type: string + specs: + description: 规格 + type: string + title: + description: 名称 + type: string + updated_at: + description: 更新时间 + type: string + type: object + model.MissionClaimOrderInfo: + properties: + courier: + description: 快递公司 + type: string + courier_number: + description: 快递单号 + type: string + courier_url: + description: 快递查询地址 + type: string + deliver: + allOf: + - $ref: '#/definitions/model.OrderDeliver' + description: 发货信息 + mission_claim_id: + description: 领取任务id + type: integer + order_goods: + allOf: + - $ref: '#/definitions/model.MissionClaimOrderGoods' + description: 订单商品信息 + order_id: + description: 订单号 + type: string + send_time: + description: 发货时间 + type: string + status: + description: 订单状态 2:待发货 3:已发货 + type: integer + type: object + model.MissionClaimVideo: + properties: + cover: + description: 视频封面 + type: string + create_by: + description: 创建人 + type: string + created_at: + description: 创建时间 + type: string + height: + description: 高度 + type: integer + id: + description: 主键ID + type: integer + mission_claim_id: + description: 领取任务id + type: integer + mission_id: + description: 任务ID + type: integer + remark: + type: string + reward_status: + description: 奖励发放状态 1:未发放 2:已发放 + type: integer + source_type: + description: 类型:1:固定费用上传 2:奖励任务上传 3:后台上传 + type: integer + status: + description: 状态 1:待审核 2:审核通过 3:审核不通过 + type: integer + updated_at: + description: 更新时间 + type: string + video_url: + description: 视频上传地址 + type: string + width: + description: 宽度 + type: integer + type: object + model.MissionClaimWorks: + properties: + created_at: + description: 创建时间 + type: string + homepage: + description: 作品主页地址 + type: string + id: + description: 主键ID + type: integer + image: + description: 作品凭证截图 + type: string + mission_claim_id: + description: 领取任务id + type: integer + type: + description: 平台 1:ins 2:YouTube 3:tiktok 4:Facebook 5:Twitter + type: integer + updated_at: + description: 更新时间 + type: string + video_url: + description: 视频上传地址 + type: string + type: object + model.MissionDetail: + properties: + claim_days: + description: 任务完成天数 + type: integer + claim_demands: + description: 任务拍摄要求 + type: string + claim_num: + description: 接任务人数 + type: integer + claim_status_except: + description: 可接任务状态描述 + type: string + claim_status_except_eng: + description: 英文版状态描述 + type: string + claim_stock: + description: 可接任务库存 + type: integer + collect_status: + description: 收藏状态 true:已收藏 false:未收藏 + type: boolean + created_at: + description: 创建时间 + type: string + description: + description: 描述/卖点 + type: string + end_time: + description: 任务结束时间 + type: string + goods: + allOf: + - $ref: '#/definitions/model.TbGoodsSpecsView' + description: 商品信息 + goods_status: + description: 关联商品状态 1:正常 2:已下架 + type: integer + goods_url: + description: 商品链接 + type: string + has_sample: + description: 是否有样品 0:没有 1:有 + type: integer + has_video: + description: 是否有视频素材 0:没有 1:有 + type: integer + hire_money: + description: hire_type==1 佣金金额 + type: number + hire_money_expect: + description: 预计佣金描述 + type: string + hire_ratio: + description: hire_type==2 抽成比例 + type: number + hire_type: + description: 佣金类型 1:固定佣金 2:比例抽成 + type: integer + id: + description: 主键ID + type: integer + num: + description: 商品数量 + type: integer + release_channels: + description: 发布渠道 + type: string + release_country: + description: 发布国家 + type: string + sample_num: + description: 样品数量 + type: integer + start_time: + description: 任务起始时间 + type: string + status: + description: 状态 1:未开始 2:进行中 3:已结束 + type: integer + store: + allOf: + - $ref: '#/definitions/model.SellerStoreInfo' + description: 商家信息 + title: + description: 标题 + type: string + updated_at: + description: 更新时间 + type: string + video_channel_ids: + description: 视频发布渠道,多个渠道英文逗号连接 + type: string + video_country_id: + description: 视频发布国家 + type: string + video_url: + type: string + type: object + model.OrderAddress: + properties: + bldg: + description: apt,ste,bldg + type: string + city: + description: city + type: string + created_at: + description: 创建时间 + type: string + default: + description: 是否默认地址 1-是 2-否 + type: integer + firstName: + description: first name + type: string + id: + description: 主键ID + type: integer + lastName: + description: last name + type: string + orderID: + type: string + phone: + description: 手机号 + type: string + platform: + description: 平台 saller(买家端) / customer(客户端) / influencer(网红端) + type: string + state: + description: state + type: string + street: + description: street + type: string + updated_at: + description: 更新时间 + type: string + userId: + type: string + zipCode: + description: zip code + type: string + type: object + model.OrderDeliver: + properties: + courier: + description: 快递公司 + type: string + courierLink: + description: 快递链接 + type: string + courierNumber: + description: 快递单号 + type: string + created_at: + description: 创建时间 + type: string + id: + description: 主键ID + type: integer + orderID: + description: 订单号 + type: string + track_id: + description: track表id + type: integer + updated_at: + description: 更新时间 + type: string + type: object + model.OrderDetail: + properties: + IAmount: + description: 网红佣金 + type: string + address: + allOf: + - $ref: '#/definitions/model.OrderAddress' + description: 地址 + bill: + allOf: + - $ref: '#/definitions/model.BillView' + description: 交易信息 + captureID: + description: paypal收款确认id + type: string + chain: + allOf: + - $ref: '#/definitions/model.Chain' + description: 区块链 + code: + description: 网红码? + type: string + commodID: + description: 商品id + type: integer + confirmTime: + description: 收货时间 + type: string + created_at: + description: 创建时间 + type: string + deliver: + allOf: + - $ref: '#/definitions/model.OrderDeliver' + description: 发货信息 + goods: + allOf: + - $ref: '#/definitions/model.OrderGoodsDetail' + description: 商品信息 + id: + description: 主键ID + type: integer + number: + description: 数量 + type: integer + orderID: + description: 订单号 + type: string + paidPrice: + description: 实付价格 + type: number + payTime: + description: 付款时间 + type: string + paypalID: + description: paypal订单号 + type: string + platform: + description: 购买平台 + type: string + postSale: + allOf: + - $ref: '#/definitions/model.PostSale' + description: 售后信息 + price: + description: 商品价格 + type: number + sendTime: + description: 发货时间 + type: string + sku_id: + description: 商品规格编号 + type: integer + sku_no: + description: 商品规格编号 + type: string + status: + description: 订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消 + type: integer + store: + allOf: + - $ref: '#/definitions/model.SellerStoreInfo' + description: 店铺信息 + store_no: + description: 店铺编号 + type: string + type: + description: 类型 1-普通订单 2-预售订单 + type: integer + updated_at: + description: 更新时间 + type: string + userID: + description: 用户id + type: string + type: object + model.OrderGoodsDetail: + properties: + attributes: + description: 规格详情 + items: + $ref: '#/definitions/model.TbAttributeWithValues' + type: array + content: + description: 详情 + type: string + content_text: + description: 详情-文字 + type: string + cover: + description: 封面图 + type: string + created_at: + description: 创建时间 + type: string + goods_specs: + description: 规格 + items: + $ref: '#/definitions/model.TbOrderGoodsSpecsDetail' + type: array + id: + description: 主键ID + type: integer + images: + description: 图片 + type: string + orderID: + description: 订单id + type: string + price_max: + description: 最高规格价格 + type: number + price_min: + description: 最低规格价格 + type: number + retail_price: + description: 吊牌价(零售指导价) + type: number + sku_no: + description: 商品规格编号 + type: string + specs: + description: 规格 + type: string + spu_no: + description: 编号 + type: string + store_no: + description: 店铺编号 + type: string + title: + description: 名称 + type: string + title_eng: + description: 英文名称 + type: string + updated_at: + description: 更新时间 + type: string + type: object + model.OrderList: + properties: + IAmount: + description: 网红佣金 + type: string + captureID: + description: paypal收款确认id + type: string + code: + description: 网红码? + type: string + commodID: + description: 商品id + type: integer + confirmTime: + description: 收货时间 + type: string + created_at: + description: 创建时间 + type: string + goods: + allOf: + - $ref: '#/definitions/model.OrderGoodsDetail' + description: 商品信息 + id: + description: 主键ID + type: integer + number: + description: 数量 + type: integer + orderID: + description: 订单号 + type: string + paidPrice: + description: 实付价格 + type: number + payTime: + description: 付款时间 + type: string + paypalID: + description: paypal订单号 + type: string + platform: + description: 购买平台 + type: string + price: + description: 商品价格 + type: number + sendTime: + description: 发货时间 + type: string + sku_id: + description: 商品规格编号 + type: integer + sku_no: + description: 商品规格编号 + type: string + status: + description: 订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消 + type: integer + store_no: + description: 店铺编号 + type: string + type: + description: 类型 1-普通订单 2-预售订单 + type: integer + updated_at: + description: 更新时间 + type: string + user: + allOf: + - $ref: '#/definitions/model.UserSimple' + description: 买家信息 + userID: + description: 用户id + type: string + type: object + model.PostSale: + properties: + created_at: + description: 创建时间 + type: string + examine_time: + description: 审核时间 + type: string + id: + description: id + type: integer + orderId: + description: 订单id + type: string + refund_time: + description: 退款时间 + type: string + refundStatus: + description: 退款状态 1:退款中 2:退款成功 3:退款失败 + type: integer + remark: + description: 审核原因 + type: string + status: + description: 处理状态 1:已提交 2:已处理 3:已拒绝 4:已撤回 + type: integer + type: object + model.SellerStoreInfo: + properties: + email: + description: 店铺联系email(注册账号email) + type: string + store_no: + description: 店铺编号 + type: string + type: + description: 1:个人店铺 + type: integer + type: object + model.SysMissionReward: + properties: + achieve_num: + description: 已完成任务次数 + type: integer + audit_by: + description: 审核人 + type: string + bonus: + description: 奖励金额 + type: number + create_by: + description: 创建人 + type: string + created_at: + description: 创建时间 + type: string + id: + description: 主键ID + type: integer + relationId: + description: 关联项目id + type: string + status: + description: 状态 1待发放 2已发放 3已领取 + type: integer + title: + description: 标题 + type: string + type: + description: 奖励类型 1.视频上传 2.信息完善 3.商家任务 + type: integer + update_by: + description: 更新人 + type: string + updated_at: + description: 更新时间 + type: string + type: object + model.TbAttributeDetail: + properties: + attribute_id: + description: 规格属性id + type: integer + value: + type: string + value_id: + type: integer + type: object + model.TbAttributeValueItem: + properties: + id: + type: integer + image: + description: 图片 + type: string + name: + description: 规格属性值 + type: string + type: object + model.TbAttributeWithValues: + properties: + id: + type: integer + name: + type: string + values: + items: + $ref: '#/definitions/model.TbAttributeValueItem' + type: array + type: object + model.TbGoodsDetail: + properties: + attributes: + description: 规格详情 + items: + $ref: '#/definitions/model.TbAttributeWithValues' + type: array + breadcrumb: + description: 分类面包屑 + items: + $ref: '#/definitions/model.Breadcrumb' + type: array + category_id: + description: 分类id + type: integer + collect_status: + description: 收藏状态 true:已收藏 false:未收藏 + type: boolean + content: + description: 商品详情 + type: string + content_text: + description: 详情-文字 + type: string + cover: + type: string + created_at: + description: 创建时间 + type: string + id: + description: 主键ID + type: integer + images: + description: 图片 + type: string + list_price: + description: 列表价格 + type: number + online: + description: 上下架状态 on/off + type: string + price_max: + description: 最高规格价格 + type: number + price_min: + description: 最低规格价格 + type: number + retail_price: + description: 吊牌价(零售指导价) + type: number + specs: + description: 规格 + items: + $ref: '#/definitions/model.TbGoodsSpecsDetail' + type: array + spu_no: + description: 编号 + type: string + tags: + description: 标签 + type: string + title: + description: 标题 + type: string + title_eng: + description: 英文标题 + type: string + updated_at: + description: 更新时间 + type: string + type: object + model.TbGoodsSpecsDetail: + properties: + attributes: + description: 规格详情 + items: + $ref: '#/definitions/model.TbAttributeDetail' + type: array + code: + type: string + created_at: + description: 创建时间 + type: string + goods_id: + type: integer + goods_no: + description: 商品编号 + type: string + id: + description: 主键ID + type: integer + image: + description: 规格图片url + type: string + price: + description: 价格 + type: number + sku_no: + description: 商品编码 + type: string + specs: + description: 规格 + type: string + stock: + description: 库存 + type: integer + updated_at: + description: 更新时间 + type: string + type: object + model.TbGoodsSpecsView: + properties: + attributes: + description: 规格详情 + items: + $ref: '#/definitions/model.TbAttributeWithValues' + type: array + cover: + type: string + created_at: + description: 创建时间 + type: string + id: + description: 主键ID + type: integer + images: + description: 图片 + type: string + price_max: + description: 最高规格价格 + type: number + price_min: + description: 最低规格价格 + type: number + retail_price: + description: 吊牌价(零售指导价) + type: number + sales: + description: 总销售量 + type: integer + specs: + description: 规格 + items: + $ref: '#/definitions/model.TbGoodsSpecsDetail' + type: array + spu_no: + description: 编号 + type: string + stock: + description: 总库存 + type: integer + tags: + description: 标签 + type: string + title: + description: 标题 + type: string + title_eng: + description: 英文标题 + type: string + updated_at: + description: 更新时间 + type: string + type: object + model.TbOrderGoodsSpecsDetail: + properties: + code: + description: attribute定位标识 + type: string + goods_id: + type: integer + goods_no: + description: 商品编号 + type: string + image: + description: 规格图片url + type: string + orderGoodsId: + type: integer + price: + description: 价格 + type: number + sku_no: + description: Attributes []TbAttributeDetail `gorm:"-" json:"-"` // 规格详情 + type: string + specs: + description: 规格 + type: string + type: object + model.UsCitys: + properties: + city: + type: string + county: + type: string + id: + type: integer + idState: + type: integer + type: object + model.UsSelect: + properties: + children: + items: + $ref: '#/definitions/model.UsCitys' + type: array + id: + type: integer + stateCode: + type: string + stateName: + type: string + type: object + model.UserSimple: + properties: + avatar: + description: 头像 + type: string + email: + description: 用户邮箱 + type: string + nick_name: + description: 昵称 + type: string + phone: + description: 手机号 + type: string + platform: + description: 平台 + items: + $ref: '#/definitions/request.Platform' + type: array + tags: + description: 个人标签 + type: string + uuid: + description: 用户uuid编码 + type: string + type: object + model.Wallet: + properties: + balance: + description: 可用余额 + type: number + created_at: + description: 创建时间 + type: string + id: + description: 主键ID + type: integer + platform: + description: 平台 saller(买家端) / customer(客户端) / influencer(网红端) + type: string + state: + description: 状态 0:正常 1:限制提现 2:禁止提现 + type: integer + transitBalance: + description: 在途余额 + type: number + updated_at: + description: 更新时间 + type: string + userId: + type: string + type: object + model.Withdrawal: + properties: + account_name: + description: 户名 + type: string + account_type: + description: 账户类型 1:paypal 2:银行卡 + type: integer + address: + description: 收款人地址 + type: string + amount: + description: 金额 + type: number + bank_code: + description: 收款行 + type: string + bill_no: + description: 账单号 + type: string + card_number: + description: 银行卡号 + type: string + check_status: + description: 审核状态 0:待审核 1:审核通过 2:审核未通过 + type: string + check_time: + description: 审核时间 + type: string + country: + description: 国家/地区 + type: string + create_by: + description: 创建人/店铺 + type: string + created_at: + description: 创建时间 + type: string + currency: + description: 币种 USD:美元 + type: string + flow_no: + description: 流水号 + type: string + id: + description: 主键ID + type: integer + pay_id: + description: 支付id + type: string + platform: + description: 平台 1:网红 2:商家 + type: string + remark: + description: 备注 + type: string + status: + description: 提现状态 0:进行中 1:成功 2:失败 + type: string + swift_code: + description: 银行国际代码 + type: string + title: + description: 标题 + type: string + updated_at: + description: 更新时间 + type: string + wallet_type: + description: 钱包类型 1:余额钱包 2:营销账户钱包 + type: integer + type: object + model.WithdrawalView: + properties: + flow_no: + description: 流水号 + type: string + type: object + request.AddAccount: + properties: + account_name: + description: 户名 + type: string + address: + description: 收款人地址 + type: string + bank_card: + description: 银行卡号 + type: string + bank_code: + description: 银行编码 + type: string + country: + description: 国家/地区 + type: string + currency: + description: '币种 USD: 美元' + type: string + is_default: + description: 是否默认 + type: boolean + swift_code: + description: swift编码 + type: string + type: object + request.ClaimMission: + properties: + address_id: + description: 收货地址id + type: integer + email: + description: 邮箱地址 + type: string + mission_id: + description: 任务id + type: integer + sku_no: + description: 商品sku_no + type: string + spu_no: + description: 商品spu_no + type: string + type: object + request.ClaimMissionVideo: + properties: + cover: + type: string + height: + description: 高度 + type: integer + mission_claim_id: + description: 领取任务id + type: integer + source_type: + description: 类型:1:固定费用上传 2:奖励任务上传 3:后台上传 + type: integer + video_url: + description: 视频上传地址 + type: string + width: + description: 宽度 + type: integer + type: object + request.ClaimMissionWorks: + properties: + homepage: + description: 作品主页地址 + type: string + id: + description: id + type: integer + image: + description: 作品凭证截图 + type: string + type: + description: 平台 1:ins 2:Pinterest 3:tk 4:Twitter 5:Facebook 6:Reddit + type: integer + video_url: + description: 视频上传地址 + type: string + type: object + request.ClaimMissionWorksList: + properties: + mission_claim_id: + description: 领取任务id + type: integer + works: + description: 作品列表 + items: + $ref: '#/definitions/request.ClaimMissionWorks' + type: array + type: object + request.DeleteAccount: + properties: + code: + description: 验证码 + type: string + id: + description: 主键 + type: integer + phone: + description: 手机号 + type: string + type: object + request.IdReq: + properties: + id: + description: id + type: integer + type: object + request.MissionId: + properties: + mission_id: + description: 任务 + type: integer + type: object + request.Platform: + properties: + image: + description: 图片 + type: string + is_auth: + description: 是否认证 + type: boolean + label: + type: string + platform: + description: 平台 字典表获取 + type: string + url: + description: 主页地址 + type: string + type: object + request.SendEmail: + properties: + email: + type: string + type: object + request.SendMessage: + properties: + country_code: + description: 用户手机号国家代码 国际区号 86 中国 1美国 + type: string + phone: + type: string + type: + description: 1:登录验证码 2-解绑 3-绑定 4-提现 + type: integer + type: object + request.UserAuthorized: + properties: + appid: + description: 应用id + type: string + client: + description: 客户端 ios android web + type: string + code: + description: 授权码 + type: string + platform: + description: 平台 google facebook twitter tiktok + type: string + token: + description: token + type: string + uuid: + description: 设备唯一标识 + type: string + type: object + request.UserBandPhone: + properties: + code: + description: 验证码 + type: string + phone: + description: 手机号 + type: string + type: object + request.UserDetail: + properties: + platform: + description: 平台及地址逗号隔开 eg:(ins:https://baidu.com/user/1,qq:12345678) + type: string + tags: + description: 个人标签 + type: string + type: + description: 修改字段 platform-平台 tags-个人标签 + type: string + type: object + request.UserLogin: + properties: + appid: + description: 应用id + type: string + code: + description: 验证码 + type: string + country_code: + description: 用户手机号国家代码 国际区号 86 中国 1美国 + type: string + email: + description: 邮箱 + type: string + password: + description: 密码 + type: string + phone: + description: 手机号 + type: string + type: + description: 1-手机号 2-邮箱 + type: string + type: object + request.UserPlatformAuth: + properties: + platform: + allOf: + - $ref: '#/definitions/request.Platform' + description: 平台 + tags: + description: 个人标签 + type: string + type: object + request.UserRegister: + properties: + appid: + description: 应用id + type: string + avatar: + description: 头像 + type: string + code: + description: 验证码 + type: string + country_code: + description: 用户手机号国家代码 国际区号 86 中国 1美国 + type: string + email: + description: 邮箱 + type: string + nickname: + description: 昵称 + type: string + type: object + request.WithdrawalParams: + properties: + accountID: + description: 提现账户id + type: integer + amount: + description: Code string `json:"code"` // 验证码 + type: number + type: object + response.BannerListResponse: + properties: + coverUrl: + description: 封面图 + type: string + id: + description: 主键 + type: integer + link: + description: 链接地址 + type: string + linkType: + description: 链接类型 0:内链 1:外链 + type: string + relationId: + description: 关联项目id + type: string + relationType: + description: 关联类型 01-任务 + type: string + sort_index: + description: 序号索引 + type: integer + status: + description: 状态 0=下架 1=上架 + type: string + title: + description: 标题 + type: string + type: + description: 任务-0101 平台奖励页-0102 + type: string + type: object + response.ChainResp: + properties: + block_adress: + description: 所在区块 + type: string + block_height: + description: 块高度 + type: integer + hash: + description: 交易哈希 + type: string + time: + description: 上链时间 + type: string + type: object + response.MissionRecommendResponse: + properties: + achieve_num: + description: 已完成商品数量 + type: integer + bought_num: + description: 购买人数 + type: number + claim_num: + description: 任务领取人数 + type: integer + cover: + description: 封面 + type: string + create_by: + description: 创建人 + type: string + created_at: + description: 创建时间 + type: string + end_time: + description: 任务结束时间 + type: string + goods_title: + description: 商品标题 + type: string + goods_title_eng: + description: 商品英文标题 + type: string + height: + description: 高度 + type: integer + hire_money: + description: hire_type==1 佣金金额 + type: number + hire_money_expect: + description: 预计佣金描述 + type: string + hire_ratio: + description: hire_type==2 抽成比例 + type: number + hire_type: + description: 佣金类型 1:固定佣金 2:比例抽成 + type: integer + id: + description: 主键ID + type: integer + influencer: + $ref: '#/definitions/model.UserSimple' + mission_id: + description: 任务ID + type: integer + mission_status: + description: 任务状态 + type: integer + relation_id: + description: 关联ID,任务视频ID + type: integer + release_channels: + description: 发布渠道 + type: string + release_country: + description: 发布国家 + type: string + sort: + description: 倒序 //排序 + type: integer + start_time: + description: 任务起始时间 + type: string + status: + description: 状态 1:上架 2:下架 + type: integer + tag: + description: todo 标签系统 + type: string + title: + description: 任务标题 + type: string + total_bonus: + description: 累计奖励 + type: number + updated_at: + description: 更新时间 + type: string + video_url: + description: 视频地址 + type: string + width: + description: 宽度 + type: integer + type: object + response.SysBonusDetail: + properties: + achieve_max: + description: 最大完成次数 + type: integer + achieve_num: + description: 已完成任务次数 + type: integer + bonus: + description: 奖金 + type: number + mission_list: + description: 任务列表 + items: + $ref: '#/definitions/response.SysMissionDesc' + type: array + title: + description: 标题 + type: string + total: + description: 奖励次数 + type: integer + type: + description: 奖励类型 1.视频上传 2.信息完善 3.商家任务 + type: integer + type: object + response.SysMissionBonus: + properties: + total: + description: 奖励总笔数 + type: integer + total_bonus: + description: 奖励汇总金额 + type: number + video_bonus: + allOf: + - $ref: '#/definitions/response.SysBonusDetail' + description: 视频上传 + type: object + response.SysMissionDesc: + properties: + achieve_num: + type: integer + bonus: + description: 奖励金额 + type: number + description: + description: 描述 + type: string + description_eng: + description: 描述英文 + type: string + status: + description: 状态 1待发放 2已发放 3已领取 0未完成 + type: integer + title: + description: 任务标题 + type: string + title_eng: + description: 任务标题英文 + type: string + type: object + response.UserStatistics: + properties: + claim_mission_num: + description: 领取任务数量 + type: integer + collection_mission_num: + description: 收藏任务数量 + type: integer + platform_num: + description: 认证平台数量 + type: integer + type: object +info: + contact: {} + description: 接口文档 + title: Swagger Example API + version: 0.0.1 +paths: + /base/authorized: + post: + parameters: + - description: email,password... + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.UserAuthorized' + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 授权登录[v1.0.0] + tags: + - auth + /base/sendEmail: + post: + consumes: + - application/json + parameters: + - description: phone,type + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.SendEmail' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"获取成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 发送邮件验证码[v1.0.0] + tags: + - tools + /base/sendMessage: + post: + consumes: + - application/json + parameters: + - description: phone,type + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.SendMessage' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"获取成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 发送短信验证码[v1.0.0] + tags: + - tools + /customer/base/brochure: + get: + parameters: + - in: query + name: type + type: string + responses: + "200": + description: '{"success":true,"data":{},"msg":""}' + schema: + type: string + summary: 隐私协议单页 + tags: + - tools + /dict/getDictDataList: + get: + consumes: + - application/json + parameters: + - description: 取值 release_country=发布国家 release_channel=发布渠道 tag_type=标签类型 + in: query + name: typeCode + type: string + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"获取成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 获取数据字典取值列表【v1.0】 + tags: + - dict + /global/address: + delete: + parameters: + - description: data... + in: body + name: data + schema: + $ref: '#/definitions/global.BASE_ID' + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 删除收货地址【v1.0】 + tags: + - 公用-收货地址 + get: + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取用户收货地址列表【v1.0】 + tags: + - 公用-收货地址 + post: + parameters: + - description: data... + in: body + name: data + schema: + $ref: '#/definitions/model.Address' + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 添加收货地址【v1.0】 + tags: + - 公用-收货地址 + put: + parameters: + - description: data... + in: body + name: data + schema: + $ref: '#/definitions/model.Address' + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 修改收货地址【v1.0】 + tags: + - 公用-收货地址 + /global/track: + get: + parameters: + - description: id + in: query + name: id + type: integer + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 查询物流信息 + tags: + - track + /global/usSelect: + get: + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 美国地区选择器【v1.0】 + tags: + - 公用-收货地址 + /influencer/banner/list: + get: + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"获取成功"}' + schema: + items: + $ref: '#/definitions/response.BannerListResponse' + type: array + security: + - ApiKeyAuth: [] + summary: 分页获取banner列表【v1.1.0新增】 + tags: + - banner + /influencer/base/brochure: + get: + parameters: + - in: query + name: type + type: string + responses: + "200": + description: '{"success":true,"data":{},"msg":""}' + schema: + type: string + summary: 隐私协议单页 + tags: + - tools + /influencer/base/chain: + get: + parameters: + - description: 区块/合约hash + in: query + name: hash + type: string + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + items: + $ref: '#/definitions/response.ChainResp' + type: array + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + summary: 获取区块链数据 + tags: + - Chain + /influencer/base/login: + post: + parameters: + - description: email,password... + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.UserLogin' + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 登录[v1.0.0] + tags: + - auth + /influencer/base/register: + post: + parameters: + - description: email,password... + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.UserRegister' + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 注册[v1.0.0] + tags: + - auth + /influencer/base/version: + get: + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + type: string + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取版本信息 + tags: + - version + /influencer/goods/detail: + get: + parameters: + - description: 领取任务id + in: query + name: claim_no + type: string + - description: 商品id + in: query + name: id + type: integer + - description: sku_no + in: query + name: sku_no + type: string + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + $ref: '#/definitions/model.TbGoodsDetail' + security: + - ApiKeyAuth: [] + summary: 获取商品详情 + tags: + - goods + /influencer/mission/bonus: + get: + parameters: + - description: 任务编码 + in: query + name: code + type: string + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + $ref: '#/definitions/model.MissionBonus' + security: + - ApiKeyAuth: [] + summary: 获取任务累计奖金 + tags: + - mission + /influencer/mission/claim: + get: + parameters: + - description: id + in: query + name: id + type: integer + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + $ref: '#/definitions/model.MissionClaimDetail' + security: + - ApiKeyAuth: [] + summary: 获取我的任务详情【v1.0】 + tags: + - mission + post: + parameters: + - description: params + in: body + name: data + schema: + $ref: '#/definitions/request.ClaimMission' + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 领取任务【v1.0】 + tags: + - mission + /influencer/mission/claim-list: + get: + parameters: + - description: 佣金类型 1:固定佣金 2:比例抽成 + in: query + name: hire_type + type: integer + - description: 页码 + in: query + name: page + type: integer + - description: 每页大小 + in: query + name: pageSize + type: integer + - description: 是否筛选上传视频 1是 + in: query + name: video_upload + type: integer + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + items: + $ref: '#/definitions/model.MissionClaimDetail' + type: array + security: + - ApiKeyAuth: [] + summary: 获取我的任务列表【v1.0】 + tags: + - mission + /influencer/mission/collect: + post: + parameters: + - description: params + in: body + name: data + schema: + $ref: '#/definitions/request.MissionId' + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 收藏/取消收藏任务【v1.0】 + tags: + - mission + /influencer/mission/collect-list: + get: + parameters: + - description: 页码 + in: query + name: page + type: integer + - description: 每页大小 + in: query + name: pageSize + type: integer + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + items: + $ref: '#/definitions/model.MissionDetail' + type: array + security: + - ApiKeyAuth: [] + summary: 获取收藏任务列表【v1.0】 + tags: + - mission + /influencer/mission/detail: + get: + parameters: + - description: id + in: query + name: id + type: integer + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + $ref: '#/definitions/model.MissionDetail' + security: + - ApiKeyAuth: [] + summary: 获取任务详情【v1.0】 + tags: + - mission + /influencer/mission/list: + get: + parameters: + - description: 页码 + in: query + name: page + type: integer + - description: 每页大小 + in: query + name: pageSize + type: integer + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + items: + $ref: '#/definitions/model.MissionDetail' + type: array + security: + - ApiKeyAuth: [] + summary: 获取任务列表【v1.0】 + tags: + - mission + /influencer/mission/order-data: + get: + parameters: + - description: 任务编码 + in: query + name: code + type: string + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + $ref: '#/definitions/dto.MissionOrderStatistic' + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取任务下订单统计数据 + tags: + - mission + /influencer/mission/recommend-detail: + get: + parameters: + - description: id + in: query + name: id + type: integer + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + $ref: '#/definitions/response.MissionRecommendResponse' + security: + - ApiKeyAuth: [] + summary: 获取首页任务详情【v1.0】 + tags: + - mission + /influencer/mission/recommend-list: + get: + parameters: + - description: 页码 + in: query + name: page + type: integer + - description: 每页大小 + in: query + name: pageSize + type: integer + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + items: + $ref: '#/definitions/response.MissionRecommendResponse' + type: array + security: + - ApiKeyAuth: [] + summary: 获取首页任务列表【v1.0】 + tags: + - mission + /influencer/mission/submit-video: + post: + parameters: + - description: params + in: body + name: data + schema: + $ref: '#/definitions/request.ClaimMissionVideo' + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 固定费用任务上传视频【v1.0】 + tags: + - mission + /influencer/mission/submit-works: + post: + parameters: + - description: params + in: body + name: data + schema: + $ref: '#/definitions/request.ClaimMissionWorksList' + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 领取任务的提交作品【v1.0】 + tags: + - mission + /influencer/mission/sys-reward-list: + get: + parameters: + - description: 页码 + in: query + name: page + type: integer + - description: 每页大小 + in: query + name: pageSize + type: integer + - description: 状态 1待发放 2已发放 3已领取 + in: query + name: status + type: integer + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + items: + $ref: '#/definitions/model.SysMissionReward' + type: array + security: + - ApiKeyAuth: [] + summary: 获取平台奖励列表【v1.0】 + tags: + - mission + /influencer/mission/sys-reward-summary: + get: + parameters: + - description: 状态 1待发放 2已发放 3已领取 + in: query + name: status + type: integer + responses: + "200": + description: '{"code": 200, "data": {}}' + schema: + $ref: '#/definitions/response.SysMissionBonus' + security: + - ApiKeyAuth: [] + summary: 获取平台奖励汇总【v1.0】 + tags: + - mission + /influencer/order/data: + get: + parameters: + - description: 场景 my:我的 order-list:订单列表 + in: query + name: scene + type: string + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + $ref: '#/definitions/dto.OrderData' + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取订单数据 + tags: + - order + /influencer/order/detail: + get: + parameters: + - description: 订单号 + in: query + name: orderID + type: string + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + $ref: '#/definitions/model.OrderDetail' + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取订单详情 + tags: + - order + /influencer/order/goods/snapshot: + get: + parameters: + - description: 订单号 + in: query + name: orderID + type: string + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + $ref: '#/definitions/model.OrderGoodsDetail' + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取订单商品快照 + tags: + - order + /influencer/order/list: + get: + parameters: + - description: 网红码? + in: query + name: code + type: string + - description: 数据库分组 + in: query + name: group + type: string + - description: 订单号 + in: query + name: orderID + type: string + - description: 页码 + in: query + name: page + type: integer + - description: 每页大小 + in: query + name: pageSize + type: integer + - description: 订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消 + in: query + name: status + type: integer + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + items: + $ref: '#/definitions/model.OrderList' + type: array + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取订单列表 + tags: + - order + /influencer/user/bandPhone: + post: + parameters: + - description: email,password... + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.UserBandPhone' + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 网红绑定手机[v1.0.0] + tags: + - 网红端-用户 + /influencer/user/detail: + get: + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取用户基本信息[v1.0.0] + tags: + - 网红端-用户 + put: + parameters: + - description: data... + in: body + name: data + schema: + $ref: '#/definitions/request.UserDetail' + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 修改用户基本信息 + tags: + - 网红端-用户 + /influencer/user/logoff: + post: + responses: + "200": + description: '{"code": 0, "data": "注销成功"}' + schema: + type: string + security: + - Bearer: [] + summary: 注销账户[v1.0.1] + tags: + - 网红端-用户 + /influencer/user/platformAuth: + post: + parameters: + - description: email,password... + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.UserPlatformAuth' + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 平台认证[v1.0.0] + tags: + - 网红端-用户 + /influencer/user/statistics: + get: + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + $ref: '#/definitions/response.UserStatistics' + security: + - Bearer: [] + summary: 获取用户统计信息[v1.0.0] + tags: + - 网红端-用户 + /influencer/wallet/account: + delete: + parameters: + - description: data... + in: body + name: data + schema: + $ref: '#/definitions/request.DeleteAccount' + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + type: string + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 解绑账户 + tags: + - 网红端-用户钱包 + post: + parameters: + - description: data... + in: body + name: data + schema: + $ref: '#/definitions/request.AddAccount' + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + type: string + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 添加账户 + tags: + - 网红端-用户钱包 + /influencer/wallet/account/default: + put: + parameters: + - description: data... + in: body + name: data + schema: + $ref: '#/definitions/request.IdReq' + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + type: string + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 设置账户默认开关 + tags: + - 网红端-用户钱包 + /influencer/wallet/accountList: + get: + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + items: + $ref: '#/definitions/model.Account' + type: array + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取账户列表 + tags: + - 网红端-用户钱包 + /influencer/wallet/bill-list: + get: + parameters: + - description: 页码 + in: query + name: page + type: integer + - description: 每页大小 + in: query + name: pageSize + type: integer + - description: 空:默认 1:bill-center + in: query + name: scene + type: string + - description: 空:全部 1-支出 2-收入 + in: query + name: status + type: string + - description: 1:全部 2:昨天 3:近30天 + in: query + name: uint + type: string + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + items: + $ref: '#/definitions/model.Bill' + type: array + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取资金流水记录 + tags: + - 对账中心 + /influencer/wallet/bill-notify: + get: + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + items: + $ref: '#/definitions/model.BillNotify' + type: array + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取账单通知列表 + tags: + - 对账中心 + /influencer/wallet/bill/data: + get: + parameters: + - description: 1:全部 2:昨天 3:近30天 + in: query + name: uint + type: string + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + $ref: '#/definitions/dto.BillData' + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取对账中心数据 + tags: + - 对账中心 + /influencer/wallet/detail: + get: + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + $ref: '#/definitions/model.Wallet' + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 钱包基本信息 + tags: + - 网红端-用户钱包 + /influencer/wallet/withdrawal: + get: + parameters: + - description: 流水号 + in: query + name: flow_no + type: string + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + $ref: '#/definitions/model.Withdrawal' + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取提现详情 + tags: + - 对账中心 + post: + parameters: + - description: data... + in: body + name: data + schema: + $ref: '#/definitions/request.WithdrawalParams' + responses: + "200": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 提现 + tags: + - 网红端-用户钱包 + /influencer/wallet/withdrawal-list: + get: + parameters: + - description: 页码 + in: query + name: page + type: integer + - description: 每页大小 + in: query + name: pageSize + type: integer + responses: + "200": + description: '{"code": 0, "data": [...]}' + schema: + items: + $ref: '#/definitions/model.Withdrawal' + type: array + "201": + description: '{"code": 1, "message": ""}' + schema: + type: string + security: + - Bearer: [] + summary: 获取提现记录 + tags: + - 对账中心 +securityDefinitions: + ApiKeyAuth: + in: header + name: x-token + type: apiKey +swagger: "2.0" diff --git a/dto/customer.pb.go b/dto/customer.pb.go new file mode 100644 index 0000000..2b30d0e --- /dev/null +++ b/dto/customer.pb.go @@ -0,0 +1,820 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.12 +// source: customer.proto + +package dto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type LoginRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email"` + Phone string `protobuf:"bytes,2,opt,name=phone,proto3" json:"phone"` + Code string `protobuf:"bytes,3,opt,name=code,proto3" json:"code"` + Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password"` + Type string `protobuf:"bytes,5,opt,name=type,proto3" json:"type"` + Appid string `protobuf:"bytes,6,opt,name=appid,proto3" json:"appid"` +} + +func (x *LoginRequest) Reset() { + *x = LoginRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_customer_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginRequest) ProtoMessage() {} + +func (x *LoginRequest) ProtoReflect() protoreflect.Message { + mi := &file_customer_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginRequest.ProtoReflect.Descriptor instead. +func (*LoginRequest) Descriptor() ([]byte, []int) { + return file_customer_proto_rawDescGZIP(), []int{0} +} + +func (x *LoginRequest) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +func (x *LoginRequest) GetPhone() string { + if x != nil { + return x.Phone + } + return "" +} + +func (x *LoginRequest) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +func (x *LoginRequest) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *LoginRequest) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *LoginRequest) GetAppid() string { + if x != nil { + return x.Appid + } + return "" +} + +type RegisterRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email"` + Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code"` + Nickname string `protobuf:"bytes,3,opt,name=nickname,proto3" json:"nickname"` + Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar"` + Appid string `protobuf:"bytes,5,opt,name=appid,proto3" json:"appid"` +} + +func (x *RegisterRequest) Reset() { + *x = RegisterRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_customer_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterRequest) ProtoMessage() {} + +func (x *RegisterRequest) ProtoReflect() protoreflect.Message { + mi := &file_customer_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterRequest.ProtoReflect.Descriptor instead. +func (*RegisterRequest) Descriptor() ([]byte, []int) { + return file_customer_proto_rawDescGZIP(), []int{1} +} + +func (x *RegisterRequest) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +func (x *RegisterRequest) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +func (x *RegisterRequest) GetNickname() string { + if x != nil { + return x.Nickname + } + return "" +} + +func (x *RegisterRequest) GetAvatar() string { + if x != nil { + return x.Avatar + } + return "" +} + +func (x *RegisterRequest) GetAppid() string { + if x != nil { + return x.Appid + } + return "" +} + +type SmsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Phone string `protobuf:"bytes,1,opt,name=phone,proto3" json:"phone"` +} + +func (x *SmsRequest) Reset() { + *x = SmsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_customer_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SmsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SmsRequest) ProtoMessage() {} + +func (x *SmsRequest) ProtoReflect() protoreflect.Message { + mi := &file_customer_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SmsRequest.ProtoReflect.Descriptor instead. +func (*SmsRequest) Descriptor() ([]byte, []int) { + return file_customer_proto_rawDescGZIP(), []int{2} +} + +func (x *SmsRequest) GetPhone() string { + if x != nil { + return x.Phone + } + return "" +} + +type WithdrawRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Phone string `protobuf:"bytes,1,opt,name=phone,proto3" json:"phone"` //账户绑定手机号 + Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code"` //验证码 + Amount float64 `protobuf:"fixed64,3,opt,name=amount,proto3" json:"amount"` //提现金额 + AccountID int32 `protobuf:"varint,4,opt,name=accountID,proto3" json:"accountID"` //账户id +} + +func (x *WithdrawRequest) Reset() { + *x = WithdrawRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_customer_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WithdrawRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WithdrawRequest) ProtoMessage() {} + +func (x *WithdrawRequest) ProtoReflect() protoreflect.Message { + mi := &file_customer_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WithdrawRequest.ProtoReflect.Descriptor instead. +func (*WithdrawRequest) Descriptor() ([]byte, []int) { + return file_customer_proto_rawDescGZIP(), []int{3} +} + +func (x *WithdrawRequest) GetPhone() string { + if x != nil { + return x.Phone + } + return "" +} + +func (x *WithdrawRequest) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +func (x *WithdrawRequest) GetAmount() float64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *WithdrawRequest) GetAccountID() int32 { + if x != nil { + return x.AccountID + } + return 0 +} + +type OrderData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + All int64 `protobuf:"varint,1,opt,name=all,proto3" json:"all"` // 全部 + Unship int64 `protobuf:"varint,2,opt,name=unship,proto3" json:"unship"` // 待发货 + Shipped int64 `protobuf:"varint,3,opt,name=shipped,proto3" json:"shipped"` // 已发货 + Finished int64 `protobuf:"varint,4,opt,name=finished,proto3" json:"finished"` // 已完成 + Cancel int64 `protobuf:"varint,5,opt,name=cancel,proto3" json:"cancel"` // 已取消 +} + +func (x *OrderData) Reset() { + *x = OrderData{} + if protoimpl.UnsafeEnabled { + mi := &file_customer_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OrderData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OrderData) ProtoMessage() {} + +func (x *OrderData) ProtoReflect() protoreflect.Message { + mi := &file_customer_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OrderData.ProtoReflect.Descriptor instead. +func (*OrderData) Descriptor() ([]byte, []int) { + return file_customer_proto_rawDescGZIP(), []int{4} +} + +func (x *OrderData) GetAll() int64 { + if x != nil { + return x.All + } + return 0 +} + +func (x *OrderData) GetUnship() int64 { + if x != nil { + return x.Unship + } + return 0 +} + +func (x *OrderData) GetShipped() int64 { + if x != nil { + return x.Shipped + } + return 0 +} + +func (x *OrderData) GetFinished() int64 { + if x != nil { + return x.Finished + } + return 0 +} + +func (x *OrderData) GetCancel() int64 { + if x != nil { + return x.Cancel + } + return 0 +} + +type BillData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Income float64 `protobuf:"fixed64,1,opt,name=income,proto3" json:"income"` // 收入总额 + RewardUnfinished float64 `protobuf:"fixed64,2,opt,name=rewardUnfinished,proto3" json:"rewardUnfinished"` // 在途佣金 + OrderMoney float64 `protobuf:"fixed64,3,opt,name=orderMoney,proto3" json:"orderMoney"` // 订单总额 + OrderNum int64 `protobuf:"varint,4,opt,name=orderNum,proto3" json:"orderNum"` // 订单数 + CancelOrderNum int64 `protobuf:"varint,5,opt,name=cancelOrderNum,proto3" json:"cancelOrderNum"` // 退款订单数 + CancelOrderMoney float64 `protobuf:"fixed64,6,opt,name=cancelOrderMoney,proto3" json:"cancelOrderMoney"` // 退款订单总额 + FlowIncome float64 `protobuf:"fixed64,7,opt,name=flowIncome,proto3" json:"flowIncome"` // 进账 + FlowExpend float64 `protobuf:"fixed64,8,opt,name=flowExpend,proto3" json:"flowExpend"` // 出账 +} + +func (x *BillData) Reset() { + *x = BillData{} + if protoimpl.UnsafeEnabled { + mi := &file_customer_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BillData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BillData) ProtoMessage() {} + +func (x *BillData) ProtoReflect() protoreflect.Message { + mi := &file_customer_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BillData.ProtoReflect.Descriptor instead. +func (*BillData) Descriptor() ([]byte, []int) { + return file_customer_proto_rawDescGZIP(), []int{5} +} + +func (x *BillData) GetIncome() float64 { + if x != nil { + return x.Income + } + return 0 +} + +func (x *BillData) GetRewardUnfinished() float64 { + if x != nil { + return x.RewardUnfinished + } + return 0 +} + +func (x *BillData) GetOrderMoney() float64 { + if x != nil { + return x.OrderMoney + } + return 0 +} + +func (x *BillData) GetOrderNum() int64 { + if x != nil { + return x.OrderNum + } + return 0 +} + +func (x *BillData) GetCancelOrderNum() int64 { + if x != nil { + return x.CancelOrderNum + } + return 0 +} + +func (x *BillData) GetCancelOrderMoney() float64 { + if x != nil { + return x.CancelOrderMoney + } + return 0 +} + +func (x *BillData) GetFlowIncome() float64 { + if x != nil { + return x.FlowIncome + } + return 0 +} + +func (x *BillData) GetFlowExpend() float64 { + if x != nil { + return x.FlowExpend + } + return 0 +} + +type MissionOrderStatistic struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OrderNum int64 `protobuf:"varint,1,opt,name=orderNum,proto3" json:"orderNum"` // 订单总数 + OrderDoneNum int64 `protobuf:"varint,2,opt,name=orderDoneNum,proto3" json:"orderDoneNum"` // 完成订单总数 + OrderMoney float64 `protobuf:"fixed64,3,opt,name=OrderMoney,proto3" json:"OrderMoney"` // 订单金额 + SettleReward float64 `protobuf:"fixed64,4,opt,name=SettleReward,proto3" json:"SettleReward"` // 结算佣金 + TransitReward float64 `protobuf:"fixed64,5,opt,name=TransitReward,proto3" json:"TransitReward"` // 在途佣金 + RewardRatio float64 `protobuf:"fixed64,6,opt,name=RewardRatio,proto3" json:"RewardRatio"` // 佣金比例 + Uv int64 `protobuf:"varint,7,opt,name=Uv,proto3" json:"Uv"` // 浏览人数 + OrderUserNum int64 `protobuf:"varint,8,opt,name=OrderUserNum,proto3" json:"OrderUserNum"` // 下单人数 + SellNum int64 `protobuf:"varint,9,opt,name=SellNum,proto3" json:"SellNum"` // 销售数量 +} + +func (x *MissionOrderStatistic) Reset() { + *x = MissionOrderStatistic{} + if protoimpl.UnsafeEnabled { + mi := &file_customer_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MissionOrderStatistic) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MissionOrderStatistic) ProtoMessage() {} + +func (x *MissionOrderStatistic) ProtoReflect() protoreflect.Message { + mi := &file_customer_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MissionOrderStatistic.ProtoReflect.Descriptor instead. +func (*MissionOrderStatistic) Descriptor() ([]byte, []int) { + return file_customer_proto_rawDescGZIP(), []int{6} +} + +func (x *MissionOrderStatistic) GetOrderNum() int64 { + if x != nil { + return x.OrderNum + } + return 0 +} + +func (x *MissionOrderStatistic) GetOrderDoneNum() int64 { + if x != nil { + return x.OrderDoneNum + } + return 0 +} + +func (x *MissionOrderStatistic) GetOrderMoney() float64 { + if x != nil { + return x.OrderMoney + } + return 0 +} + +func (x *MissionOrderStatistic) GetSettleReward() float64 { + if x != nil { + return x.SettleReward + } + return 0 +} + +func (x *MissionOrderStatistic) GetTransitReward() float64 { + if x != nil { + return x.TransitReward + } + return 0 +} + +func (x *MissionOrderStatistic) GetRewardRatio() float64 { + if x != nil { + return x.RewardRatio + } + return 0 +} + +func (x *MissionOrderStatistic) GetUv() int64 { + if x != nil { + return x.Uv + } + return 0 +} + +func (x *MissionOrderStatistic) GetOrderUserNum() int64 { + if x != nil { + return x.OrderUserNum + } + return 0 +} + +func (x *MissionOrderStatistic) GetSellNum() int64 { + if x != nil { + return x.SellNum + } + return 0 +} + +var File_customer_proto protoreflect.FileDescriptor + +var file_customer_proto_rawDesc = []byte{ + 0x0a, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x03, 0x61, 0x70, 0x69, 0x22, 0x94, 0x01, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05, + 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x6f, + 0x6e, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x69, 0x64, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x69, 0x64, 0x22, 0x85, 0x01, 0x0a, + 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x69, + 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, + 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x14, + 0x0a, 0x05, 0x61, 0x70, 0x70, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, + 0x70, 0x70, 0x69, 0x64, 0x22, 0x22, 0x0a, 0x0a, 0x53, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x22, 0x71, 0x0a, 0x0f, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, + 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x6f, 0x6e, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, + 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x44, 0x22, 0x83, 0x01, 0x0a, 0x09, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x75, + 0x6e, 0x73, 0x68, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x6e, 0x73, + 0x68, 0x69, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x68, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x68, 0x69, 0x70, 0x70, 0x65, 0x64, 0x12, 0x1a, 0x0a, + 0x08, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x08, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x61, 0x6e, + 0x63, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x22, 0x9e, 0x02, 0x0a, 0x08, 0x42, 0x69, 0x6c, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x12, 0x16, + 0x0a, 0x06, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, + 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, + 0x55, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, + 0x52, 0x10, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x55, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, + 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x6e, 0x65, 0x79, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x6e, + 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x12, 0x26, + 0x0a, 0x0e, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, + 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x6e, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, + 0x52, 0x10, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x6e, + 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x65, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x63, 0x6f, + 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x70, 0x65, 0x6e, 0x64, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x66, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x70, 0x65, + 0x6e, 0x64, 0x22, 0xb1, 0x02, 0x0a, 0x15, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4f, 0x72, + 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x12, 0x1a, 0x0a, 0x08, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x12, 0x22, 0x0a, 0x0c, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x44, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x44, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x12, 0x1e, 0x0a, 0x0a, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x6e, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, + 0x52, 0x0a, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x6e, 0x65, 0x79, 0x12, 0x22, 0x0a, 0x0c, + 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x01, 0x52, 0x0c, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, + 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, + 0x52, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x52, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x55, 0x76, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x55, 0x76, 0x12, 0x22, 0x0a, 0x0c, 0x4f, 0x72, 0x64, 0x65, + 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x12, 0x18, 0x0a, 0x07, + 0x53, 0x65, 0x6c, 0x6c, 0x4e, 0x75, 0x6d, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x53, + 0x65, 0x6c, 0x6c, 0x4e, 0x75, 0x6d, 0x42, 0x0a, 0x5a, 0x08, 0x70, 0x75, 0x72, 0x65, 0x2f, 0x64, + 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_customer_proto_rawDescOnce sync.Once + file_customer_proto_rawDescData = file_customer_proto_rawDesc +) + +func file_customer_proto_rawDescGZIP() []byte { + file_customer_proto_rawDescOnce.Do(func() { + file_customer_proto_rawDescData = protoimpl.X.CompressGZIP(file_customer_proto_rawDescData) + }) + return file_customer_proto_rawDescData +} + +var file_customer_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_customer_proto_goTypes = []interface{}{ + (*LoginRequest)(nil), // 0: api.LoginRequest + (*RegisterRequest)(nil), // 1: api.RegisterRequest + (*SmsRequest)(nil), // 2: api.SmsRequest + (*WithdrawRequest)(nil), // 3: api.WithdrawRequest + (*OrderData)(nil), // 4: api.OrderData + (*BillData)(nil), // 5: api.BillData + (*MissionOrderStatistic)(nil), // 6: api.MissionOrderStatistic +} +var file_customer_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_customer_proto_init() } +func file_customer_proto_init() { + if File_customer_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_customer_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_customer_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_customer_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SmsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_customer_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WithdrawRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_customer_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OrderData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_customer_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BillData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_customer_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MissionOrderStatistic); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_customer_proto_rawDesc, + NumEnums: 0, + NumMessages: 7, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_customer_proto_goTypes, + DependencyIndexes: file_customer_proto_depIdxs, + MessageInfos: file_customer_proto_msgTypes, + }.Build() + File_customer_proto = out.File + file_customer_proto_rawDesc = nil + file_customer_proto_goTypes = nil + file_customer_proto_depIdxs = nil +} diff --git a/dto/customer.proto b/dto/customer.proto new file mode 100644 index 0000000..25a422e --- /dev/null +++ b/dto/customer.proto @@ -0,0 +1,60 @@ +syntax = "proto3"; + +package api; + +option go_package = "pure/dto"; + +message LoginRequest{ + string email = 1; + string phone = 2; + string code = 3; + string password = 4; + string type = 5; + string appid = 6; +} + +message RegisterRequest{ + string email = 1; + string code = 2; + string nickname = 3; + string avatar = 4; + string appid = 5; +} + +message SmsRequest { + string phone = 1; +} +message WithdrawRequest { + string phone = 1;//账户绑定手机号 + string code = 2; //验证码 + double amount = 3;//提现金额 + int32 accountID = 4;//账户id +} +message OrderData{ + int64 all = 1;// 全部 + int64 unship = 2;// 待发货 + int64 shipped = 3;// 已发货 + int64 finished = 4;// 已完成 + int64 cancel = 5;// 已取消 +} +message BillData{ + double income = 1;// 收入总额 + double rewardUnfinished = 2;// 在途佣金 + double orderMoney = 3;// 订单总额 + int64 orderNum = 4;// 订单数 + int64 cancelOrderNum = 5;// 退款订单数 + double cancelOrderMoney = 6;// 退款订单总额 + double flowIncome = 7;// 进账 + double flowExpend = 8;// 出账 +} +message MissionOrderStatistic{ + int64 orderNum = 1;// 订单总数 + int64 orderDoneNum = 2;// 完成订单总数 + double OrderMoney = 3;// 订单金额 + double SettleReward = 4;// 结算佣金 + double TransitReward = 5;// 在途佣金 + double RewardRatio = 6; // 佣金比例 + int64 Uv = 7;// 浏览人数 + int64 OrderUserNum = 8;// 下单人数 + int64 SellNum = 9;// 销售数量 +} \ No newline at end of file diff --git a/global/global.go b/global/global.go new file mode 100644 index 0000000..ebbdf2e --- /dev/null +++ b/global/global.go @@ -0,0 +1,25 @@ +package global + +import ( + "pure/config" + "pure/initialize/api" + "pure/utils/timer" + + "github.com/go-redis/redis" + "github.com/spf13/viper" + "go.uber.org/zap" + "gorm.io/gorm" +) + +var ( + MG_DB *gorm.DB + MG_REDIS *redis.Client + MG_CONFIG config.Server + MG_VP *viper.Viper + MG_LOG *zap.Logger + PAY_CLIENT api.GreeterClient + SMS_CLIENT api.SmsClient + EMAIL_CLIENT api.EmailClient + MG_Language interface{} + MG_Timer timer.Timer = timer.NewTimerTask() +) diff --git a/global/model.go b/global/model.go new file mode 100644 index 0000000..1e7b3c1 --- /dev/null +++ b/global/model.go @@ -0,0 +1,56 @@ +package global + +import ( + "time" + + "gorm.io/gorm" +) + +type MG_MODEL struct { + ID uint `gorm:"AUTO_INCREMENT;PRIMARY_KEY;" json:"id"` // 主键ID + CreatedAt time.Time `json:"created_at"` // 创建时间 + UpdatedAt time.Time `json:"updated_at"` // 更新时间 + DeletedAt gorm.DeletedAt `json:"-"` // 删除时间 +} +type Pure_MODEL struct { + ID uint `gorm:"AUTO_INCREMENT;PRIMARY_KEY;" json:"id"` // 主键ID + CreatedAt time.Time `json:"created_at"` // 创建时间 + UpdatedAt time.Time `json:"updated_at"` // 更新时间 +} + +type TIME_MODEL struct { + CreatedAt time.Time `json:"-"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"-"` +} + +type ID_BACKUP_STR struct { + ID string `gorm:"primary_key;size:50" json:"id" form:"id"` //主键 + // Kid int `json:"kid" form:"kid"` + Backup int `json:"backup" form:"backup"` + Check int `json:"check" form:"check"` + CurrentCheck string `json:"currentCheck" form:"currentCheck"` +} + +type BASE_ID struct { + ID uint `gorm:"AUTO_INCREMENT;primary_key;" json:"id" form:"id"` //主键 +} + +type ID_SORT struct { + ID string `json:"id"` + Sort int `json:"sort"` +} + +type ID_COUNT struct { + ID string `json:"id"` + Count int `json:"count"` +} + +type RedisValueScore struct { + Value string `json:"value"` + Score float64 `json:"score"` +} + +type BASE_ID_STR struct { + ID string `gorm:"primary_key;size:50" json:"id" form:"id"` //主键 +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d55e886 --- /dev/null +++ b/go.mod @@ -0,0 +1,118 @@ +module pure + +go 1.20 + +require ( + github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible + github.com/dgrijalva/jwt-go v3.2.0+incompatible + github.com/fsnotify/fsnotify v1.6.0 + github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 + github.com/gin-gonic/gin v1.9.0 + github.com/go-kratos/kratos/contrib/registry/nacos/v2 v2.0.0-20230830131453-6c026bce56a9 + github.com/go-kratos/kratos/v2 v2.7.0 + github.com/go-redis/redis v6.15.9+incompatible + github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible + github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible + github.com/nacos-group/nacos-sdk-go v1.1.4 + github.com/pili-engineering/pili-sdk-go.v2 v0.0.0-20200608105005-bb506e708987 + github.com/plutov/paypal v2.0.5+incompatible + github.com/robfig/cron/v3 v3.0.1 + github.com/satori/go.uuid v1.2.0 + github.com/shirou/gopsutil v2.21.11+incompatible + github.com/spf13/cast v1.5.1 + github.com/spf13/viper v1.16.0 + github.com/swaggo/files v1.0.1 + github.com/swaggo/gin-swagger v1.6.0 + github.com/swaggo/swag v1.8.12 + github.com/taskcluster/slugid-go v1.1.0 + github.com/tencentyun/cos-go-sdk-v5 v0.7.42 + github.com/unrolled/secure v1.13.0 + github.com/w3liu/go-common v0.0.0-20210108072342-826b2f3582be + go.uber.org/zap v1.25.0 + google.golang.org/grpc v1.56.1 + google.golang.org/protobuf v1.31.0 + gorm.io/driver/mysql v1.5.1 + gorm.io/gorm v1.25.4 +) + +require ( + cloud.google.com/go/compute v1.20.1 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/google/uuid v1.3.0 // indirect + google.golang.org/appengine v1.6.8 // indirect +) + +require ( + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/PuerkitoBio/purell v1.1.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 // indirect + github.com/buger/jsonparser v1.1.1 // indirect + github.com/bytedance/sonic v1.8.0 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/clbanning/mxj v1.8.4 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-errors/errors v1.0.1 // indirect + github.com/go-kratos/aegis v0.2.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.19.6 // indirect + github.com/go-openapi/spec v0.20.4 // indirect + github.com/go-openapi/swag v0.19.15 // indirect + github.com/go-playground/form/v4 v4.2.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.11.2 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/goccy/go-json v0.10.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-querystring v1.0.0 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect + github.com/jonboulle/clockwork v0.4.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/leodido/go-urn v1.2.1 // indirect + github.com/lestrrat-go/strftime v1.0.6 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.6 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mozillazg/go-httpheader v0.2.1 // indirect + github.com/pborman/uuid v1.2.0 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/qiniu/x v1.10.5 // indirect + github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.4.2 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.9 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.13.0 + golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + golang.org/x/time v0.1.0 // indirect + golang.org/x/tools v0.7.0 // indirect + google.golang.org/genproto v0.0.0-20230629202037-9506855d4529 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529 + google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2237152 --- /dev/null +++ b/go.sum @@ -0,0 +1,781 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= +cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= +github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 h1:zOVTBdCKFd9JbCKz9/nt+FovbjPFmb7mUnp8nH9fQBA= +github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk= +github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible h1:Sg/2xHwDrioHpxTN6WMiwbXTpUEinBpHsN7mG21Rc2k= +github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA= +github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= +github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.11.2-0.20230627204322-7d0032219fcb h1:kxNVXsNro/lpR5WD+P1FI/yUHn2G03Glber3k8cQL2Y= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 h1:6VSn3hB5U5GeA6kQw4TwWIWbOhtvR2hmbBJnTOtqTWc= +github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6/go.mod h1:YxOVT5+yHzKvwhsiSIWmbAYM3Dr9AEEbER2dVayfBkg= +github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= +github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +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-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kratos/aegis v0.2.0 h1:dObzCDWn3XVjUkgxyBp6ZeWtx/do0DPZ7LY3yNSJLUQ= +github.com/go-kratos/aegis v0.2.0/go.mod h1:v0R2m73WgEEYB3XYu6aE2WcMwsZkJ/Rzuf5eVccm7bI= +github.com/go-kratos/kratos/contrib/registry/nacos/v2 v2.0.0-20230830131453-6c026bce56a9 h1:m6eNghBfLhxZbOJR5yUFSZ4KswrxTlU2oK6lQWROXtI= +github.com/go-kratos/kratos/contrib/registry/nacos/v2 v2.0.0-20230830131453-6c026bce56a9/go.mod h1:6xVbnCGYP1wqhz+nu9ct2K6K+mZkCqm/R6zlMRY7Sug= +github.com/go-kratos/kratos/v2 v2.7.0 h1:9DaVgU9YoHPb/BxDVqeVlVCMduRhiSewG3xE+e9ZAZ8= +github.com/go-kratos/kratos/v2 v2.7.0/go.mod h1:CPn82O93OLHjtnbuyOKhAG5TkSvw+mFnL32c4lZFDwU= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/form/v4 v4.2.0 h1:N1wh+Goz61e6w66vo8vJkQt+uwZSoLz50kZPJWR8eic= +github.com/go-playground/form/v4 v4.2.0/go.mod h1:q1a2BY+AQUUzhl6xA/6hBetay6dEIhMHjgvJiGo6K7U= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= +github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= +github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/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.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.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.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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= +github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA= +github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= +github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4= +github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= +github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= +github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= +github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ= +github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60= +github.com/nacos-group/nacos-sdk-go v1.1.4 h1:qyrZ7HTWM4aeymFfqnbgNRERh7TWuER10pCB7ddRcTY= +github.com/nacos-group/nacos-sdk-go v1.1.4/go.mod h1:cBv9wy5iObs7khOqov1ERFQrCuTR4ILpgaiaVMxEmGI= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pili-engineering/pili-sdk-go.v2 v0.0.0-20200608105005-bb506e708987 h1:PIPYQRZ0S1yjLPO05uNtYz5fcsiJ5Xo/vdQCrwde0fM= +github.com/pili-engineering/pili-sdk-go.v2 v0.0.0-20200608105005-bb506e708987/go.mod h1:nd8f4Fi29T7yRtBjAZwPOvsRurUzq7Jja5vWUB+aprk= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/plutov/paypal v2.0.5+incompatible h1:i5ma4HiHO0MUvJGHaKkL2aqOj0B19q8WoJm1jgzQjlM= +github.com/plutov/paypal v2.0.5+incompatible/go.mod h1:jOStyiXeDrJ9dHA/yVUB2ahyYPjd5rMXUZ4N7XM37nQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/qiniu/x v1.10.5 h1:7V/CYWEmo9axJULvrJN6sMYh2FdY+esN5h8jwDkA4b0= +github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/shirou/gopsutil v2.21.11+incompatible h1:lOGOyCG67a5dv2hq5Z1BLDUqqKp3HkbjPcz5j6XMS0U= +github.com/shirou/gopsutil v2.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= +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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= +github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= +github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M= +github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo= +github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w= +github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/taskcluster/slugid-go v1.1.0 h1:SWsUplliyamdYzOKVM4+lDohZKuL63fKreGkvIKJ9aI= +github.com/taskcluster/slugid-go v1.1.0/go.mod h1:5sOAcPHjqso1UkKxSl77CkKgOwha0D9X0msBKBj0AOg= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0= +github.com/tencentyun/cos-go-sdk-v5 v0.7.42 h1:Up1704BJjI5orycXKjpVpvuOInt9GC5pqY4knyE9Uds= +github.com/tencentyun/cos-go-sdk-v5 v0.7.42/go.mod h1:LUFnaqRmGk6pEHOaRmdn2dCZR2j0cSsM5xowWFPTPao= +github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= +github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/unrolled/secure v1.13.0 h1:sdr3Phw2+f8Px8HE5sd1EHdj1aV3yUwed/uZXChLFsk= +github.com/unrolled/secure v1.13.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40= +github.com/w3liu/go-common v0.0.0-20210108072342-826b2f3582be h1:NW489IqqgOz/+fV4oDC2NJqQFH+gYYQt8WRLj4v94Ok= +github.com/w3liu/go-common v0.0.0-20210108072342-826b2f3582be/go.mod h1:yHAS/DWXivtrBrO4K45DpIFjQ6LgOi4bUBz7A1iClsE= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +go.mongodb.org/mongo-driver v1.2.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= +go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20230629202037-9506855d4529 h1:9JucMWR7sPvCxUFd6UsOUNmA5kCcWOfORaT3tpAsKQs= +google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= +google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529 h1:s5YSX+ZH5b5vS9rnpGymvIyMpLRJizowqDlOuyjXnTk= +google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529 h1:DEH99RbiLZhMxrpEJCZ0A+wdTe0EOgou/poSLx9vWf4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ= +google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw= +gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o= +gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= +gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= +xorm.io/xorm v1.0.6/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4= diff --git a/initialize/api/email.pb.go b/initialize/api/email.pb.go new file mode 100644 index 0000000..df90a58 --- /dev/null +++ b/initialize/api/email.pb.go @@ -0,0 +1,253 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.12 +// source: initialize/api/email.proto + +package api + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type SendRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // 收件人 必填参数 + To []string `protobuf:"bytes,1,rep,name=to,proto3" json:"to,omitempty"` + // 邮件主题,必填参数 + Subject string `protobuf:"bytes,2,opt,name=subject,proto3" json:"subject,omitempty"` + // 消息体,支持富文本 + Body string `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"` + // 附件地址 + Files []string `protobuf:"bytes,4,rep,name=files,proto3" json:"files,omitempty"` +} + +func (x *SendRequest) Reset() { + *x = SendRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_initialize_api_email_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendRequest) ProtoMessage() {} + +func (x *SendRequest) ProtoReflect() protoreflect.Message { + mi := &file_initialize_api_email_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendRequest.ProtoReflect.Descriptor instead. +func (*SendRequest) Descriptor() ([]byte, []int) { + return file_initialize_api_email_proto_rawDescGZIP(), []int{0} +} + +func (x *SendRequest) GetTo() []string { + if x != nil { + return x.To + } + return nil +} + +func (x *SendRequest) GetSubject() string { + if x != nil { + return x.Subject + } + return "" +} + +func (x *SendRequest) GetBody() string { + if x != nil { + return x.Body + } + return "" +} + +func (x *SendRequest) GetFiles() []string { + if x != nil { + return x.Files + } + return nil +} + +// The response message containing the greetings +type SendEmailReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *SendEmailReply) Reset() { + *x = SendEmailReply{} + if protoimpl.UnsafeEnabled { + mi := &file_initialize_api_email_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendEmailReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendEmailReply) ProtoMessage() {} + +func (x *SendEmailReply) ProtoReflect() protoreflect.Message { + mi := &file_initialize_api_email_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendEmailReply.ProtoReflect.Descriptor instead. +func (*SendEmailReply) Descriptor() ([]byte, []int) { + return file_initialize_api_email_proto_rawDescGZIP(), []int{1} +} + +func (x *SendEmailReply) GetCode() int32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *SendEmailReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_initialize_api_email_proto protoreflect.FileDescriptor + +var file_initialize_api_email_proto_rawDesc = []byte{ + 0x0a, 0x1a, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x61, 0x70, + 0x69, 0x22, 0x61, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x22, 0x3e, 0x0a, 0x0e, 0x53, 0x65, 0x6e, 0x64, 0x45, 0x6d, 0x61, 0x69, + 0x6c, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x32, 0x3d, 0x0a, 0x05, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x34, 0x0a, + 0x09, 0x53, 0x65, 0x6e, 0x64, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x10, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x22, 0x00, 0x42, 0x10, 0x5a, 0x0e, 0x62, 0x6b, 0x62, 0x2d, 0x6e, 0x6f, 0x74, 0x69, 0x66, + 0x79, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_initialize_api_email_proto_rawDescOnce sync.Once + file_initialize_api_email_proto_rawDescData = file_initialize_api_email_proto_rawDesc +) + +func file_initialize_api_email_proto_rawDescGZIP() []byte { + file_initialize_api_email_proto_rawDescOnce.Do(func() { + file_initialize_api_email_proto_rawDescData = protoimpl.X.CompressGZIP(file_initialize_api_email_proto_rawDescData) + }) + return file_initialize_api_email_proto_rawDescData +} + +var file_initialize_api_email_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_initialize_api_email_proto_goTypes = []interface{}{ + (*SendRequest)(nil), // 0: api.SendRequest + (*SendEmailReply)(nil), // 1: api.SendEmailReply +} +var file_initialize_api_email_proto_depIdxs = []int32{ + 0, // 0: api.Email.SendEmail:input_type -> api.SendRequest + 1, // 1: api.Email.SendEmail:output_type -> api.SendEmailReply + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_initialize_api_email_proto_init() } +func file_initialize_api_email_proto_init() { + if File_initialize_api_email_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_initialize_api_email_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SendRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_initialize_api_email_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SendEmailReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_initialize_api_email_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_initialize_api_email_proto_goTypes, + DependencyIndexes: file_initialize_api_email_proto_depIdxs, + MessageInfos: file_initialize_api_email_proto_msgTypes, + }.Build() + File_initialize_api_email_proto = out.File + file_initialize_api_email_proto_rawDesc = nil + file_initialize_api_email_proto_goTypes = nil + file_initialize_api_email_proto_depIdxs = nil +} diff --git a/initialize/api/email.proto b/initialize/api/email.proto new file mode 100644 index 0000000..1832d7d --- /dev/null +++ b/initialize/api/email.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; + +package api; + + +option go_package = "bkb-notify/api"; + + +// The Email service definition. +service Email { + // 发送一个邮件 + rpc SendEmail (SendRequest) returns (SendEmailReply) { + + } +} + +message SendRequest { + //收件人 必填参数 + repeated string to=1; + //邮件主题,必填参数 + string subject=2; + //消息体,支持富文本 + string body=3; + //附件地址 + repeated string files=4; +} + +// The response message containing the greetings +message SendEmailReply { + int32 code = 1; + string message = 2; +} diff --git a/initialize/api/email_grpc.pb.go b/initialize/api/email_grpc.pb.go new file mode 100644 index 0000000..bb6edd9 --- /dev/null +++ b/initialize/api/email_grpc.pb.go @@ -0,0 +1,111 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v3.21.12 +// source: initialize/api/email.proto + +package api + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + Email_SendEmail_FullMethodName = "/api.Email/SendEmail" +) + +// EmailClient is the client API for Email service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type EmailClient interface { + // 发送一个邮件 + SendEmail(ctx context.Context, in *SendRequest, opts ...grpc.CallOption) (*SendEmailReply, error) +} + +type emailClient struct { + cc grpc.ClientConnInterface +} + +func NewEmailClient(cc grpc.ClientConnInterface) EmailClient { + return &emailClient{cc} +} + +func (c *emailClient) SendEmail(ctx context.Context, in *SendRequest, opts ...grpc.CallOption) (*SendEmailReply, error) { + out := new(SendEmailReply) + err := c.cc.Invoke(ctx, Email_SendEmail_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// EmailServer is the server API for Email service. +// All implementations must embed UnimplementedEmailServer +// for forward compatibility +type EmailServer interface { + // 发送一个邮件 + SendEmail(context.Context, *SendRequest) (*SendEmailReply, error) + mustEmbedUnimplementedEmailServer() +} + +// UnimplementedEmailServer must be embedded to have forward compatible implementations. +type UnimplementedEmailServer struct { +} + +func (UnimplementedEmailServer) SendEmail(context.Context, *SendRequest) (*SendEmailReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SendEmail not implemented") +} +func (UnimplementedEmailServer) mustEmbedUnimplementedEmailServer() {} + +// UnsafeEmailServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to EmailServer will +// result in compilation errors. +type UnsafeEmailServer interface { + mustEmbedUnimplementedEmailServer() +} + +func RegisterEmailServer(s grpc.ServiceRegistrar, srv EmailServer) { + s.RegisterService(&Email_ServiceDesc, srv) +} + +func _Email_SendEmail_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SendRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EmailServer).SendEmail(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Email_SendEmail_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EmailServer).SendEmail(ctx, req.(*SendRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Email_ServiceDesc is the grpc.ServiceDesc for Email service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Email_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "api.Email", + HandlerType: (*EmailServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SendEmail", + Handler: _Email_SendEmail_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "initialize/api/email.proto", +} diff --git a/initialize/api/greeter.pb.go b/initialize/api/greeter.pb.go new file mode 100644 index 0000000..9e2c7de --- /dev/null +++ b/initialize/api/greeter.pb.go @@ -0,0 +1,1429 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc v4.23.4 +// source: greeter.proto + +package api + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The response message containing the greetings +type PingReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *PingReply) Reset() { + *x = PingReply{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingReply) ProtoMessage() {} + +func (x *PingReply) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingReply.ProtoReflect.Descriptor instead. +func (*PingReply) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{0} +} + +func (x *PingReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type Country struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *Country) Reset() { + *x = Country{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Country) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Country) ProtoMessage() {} + +func (x *Country) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Country.ProtoReflect.Descriptor instead. +func (*Country) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{1} +} + +func (x *Country) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Country) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type CountryReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + List []*Country `protobuf:"bytes,1,rep,name=list,proto3" json:"list,omitempty"` +} + +func (x *CountryReply) Reset() { + *x = CountryReply{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CountryReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CountryReply) ProtoMessage() {} + +func (x *CountryReply) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CountryReply.ProtoReflect.Descriptor instead. +func (*CountryReply) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{2} +} + +func (x *CountryReply) GetList() []*Country { + if x != nil { + return x.List + } + return nil +} + +type DistrictRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Country int32 `protobuf:"varint,1,opt,name=country,proto3" json:"country,omitempty"` +} + +func (x *DistrictRequest) Reset() { + *x = DistrictRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DistrictRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DistrictRequest) ProtoMessage() {} + +func (x *DistrictRequest) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DistrictRequest.ProtoReflect.Descriptor instead. +func (*DistrictRequest) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{3} +} + +func (x *DistrictRequest) GetCountry() int32 { + if x != nil { + return x.Country + } + return 0 +} + +type District struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Label string `protobuf:"bytes,1,opt,name=label,proto3" json:"label,omitempty"` + Adcode string `protobuf:"bytes,2,opt,name=adcode,proto3" json:"adcode,omitempty"` + ParentId int32 `protobuf:"varint,3,opt,name=parentId,proto3" json:"parentId,omitempty"` + Children []*District `protobuf:"bytes,4,rep,name=children,proto3" json:"children,omitempty"` +} + +func (x *District) Reset() { + *x = District{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *District) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*District) ProtoMessage() {} + +func (x *District) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use District.ProtoReflect.Descriptor instead. +func (*District) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{4} +} + +func (x *District) GetLabel() string { + if x != nil { + return x.Label + } + return "" +} + +func (x *District) GetAdcode() string { + if x != nil { + return x.Adcode + } + return "" +} + +func (x *District) GetParentId() int32 { + if x != nil { + return x.ParentId + } + return 0 +} + +func (x *District) GetChildren() []*District { + if x != nil { + return x.Children + } + return nil +} + +type DistrictReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + List []*District `protobuf:"bytes,1,rep,name=list,proto3" json:"list,omitempty"` +} + +func (x *DistrictReply) Reset() { + *x = DistrictReply{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DistrictReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DistrictReply) ProtoMessage() {} + +func (x *DistrictReply) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DistrictReply.ProtoReflect.Descriptor instead. +func (*DistrictReply) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{5} +} + +func (x *DistrictReply) GetList() []*District { + if x != nil { + return x.List + } + return nil +} + +type PayTransRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Appid string `protobuf:"bytes,1,opt,name=appid,proto3" json:"appid,omitempty"` + Mchid string `protobuf:"bytes,2,opt,name=mchid,proto3" json:"mchid,omitempty"` + OutTradeNo string `protobuf:"bytes,3,opt,name=out_trade_no,json=outTradeNo,proto3" json:"out_trade_no,omitempty"` + Attach string `protobuf:"bytes,4,opt,name=attach,proto3" json:"attach,omitempty"` + NotifyUrl string `protobuf:"bytes,5,opt,name=notify_url,json=notifyUrl,proto3" json:"notify_url,omitempty"` + Amount float64 `protobuf:"fixed64,6,opt,name=amount,proto3" json:"amount,omitempty"` + Currency string `protobuf:"bytes,7,opt,name=currency,proto3" json:"currency,omitempty"` + PayChannel string `protobuf:"bytes,8,opt,name=pay_channel,json=payChannel,proto3" json:"pay_channel,omitempty"` + ReturnUrl string `protobuf:"bytes,9,opt,name=return_url,json=returnUrl,proto3" json:"return_url,omitempty"` + CancelUrl string `protobuf:"bytes,10,opt,name=cancel_url,json=cancelUrl,proto3" json:"cancel_url,omitempty"` +} + +func (x *PayTransRequest) Reset() { + *x = PayTransRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PayTransRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayTransRequest) ProtoMessage() {} + +func (x *PayTransRequest) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayTransRequest.ProtoReflect.Descriptor instead. +func (*PayTransRequest) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{6} +} + +func (x *PayTransRequest) GetAppid() string { + if x != nil { + return x.Appid + } + return "" +} + +func (x *PayTransRequest) GetMchid() string { + if x != nil { + return x.Mchid + } + return "" +} + +func (x *PayTransRequest) GetOutTradeNo() string { + if x != nil { + return x.OutTradeNo + } + return "" +} + +func (x *PayTransRequest) GetAttach() string { + if x != nil { + return x.Attach + } + return "" +} + +func (x *PayTransRequest) GetNotifyUrl() string { + if x != nil { + return x.NotifyUrl + } + return "" +} + +func (x *PayTransRequest) GetAmount() float64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *PayTransRequest) GetCurrency() string { + if x != nil { + return x.Currency + } + return "" +} + +func (x *PayTransRequest) GetPayChannel() string { + if x != nil { + return x.PayChannel + } + return "" +} + +func (x *PayTransRequest) GetReturnUrl() string { + if x != nil { + return x.ReturnUrl + } + return "" +} + +func (x *PayTransRequest) GetCancelUrl() string { + if x != nil { + return x.CancelUrl + } + return "" +} + +type PayTransResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *PayTransResponse) Reset() { + *x = PayTransResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PayTransResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayTransResponse) ProtoMessage() {} + +func (x *PayTransResponse) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayTransResponse.ProtoReflect.Descriptor instead. +func (*PayTransResponse) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{7} +} + +func (x *PayTransResponse) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +func (x *PayTransResponse) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *PayTransResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type PayUrlRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Mchid string `protobuf:"bytes,1,opt,name=mchid,proto3" json:"mchid,omitempty"` + PayChannel string `protobuf:"bytes,2,opt,name=pay_channel,json=payChannel,proto3" json:"pay_channel,omitempty"` + TransactionId string `protobuf:"bytes,3,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` +} + +func (x *PayUrlRequest) Reset() { + *x = PayUrlRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PayUrlRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayUrlRequest) ProtoMessage() {} + +func (x *PayUrlRequest) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayUrlRequest.ProtoReflect.Descriptor instead. +func (*PayUrlRequest) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{8} +} + +func (x *PayUrlRequest) GetMchid() string { + if x != nil { + return x.Mchid + } + return "" +} + +func (x *PayUrlRequest) GetPayChannel() string { + if x != nil { + return x.PayChannel + } + return "" +} + +func (x *PayUrlRequest) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +type PayUrlResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PayChannel string `protobuf:"bytes,1,opt,name=pay_channel,json=payChannel,proto3" json:"pay_channel,omitempty"` + PayId string `protobuf:"bytes,2,opt,name=pay_id,json=payId,proto3" json:"pay_id,omitempty"` + PayReturn string `protobuf:"bytes,3,opt,name=pay_return,json=payReturn,proto3" json:"pay_return,omitempty"` + PayStatus string `protobuf:"bytes,4,opt,name=pay_status,json=payStatus,proto3" json:"pay_status,omitempty"` +} + +func (x *PayUrlResponse) Reset() { + *x = PayUrlResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PayUrlResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayUrlResponse) ProtoMessage() {} + +func (x *PayUrlResponse) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayUrlResponse.ProtoReflect.Descriptor instead. +func (*PayUrlResponse) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{9} +} + +func (x *PayUrlResponse) GetPayChannel() string { + if x != nil { + return x.PayChannel + } + return "" +} + +func (x *PayUrlResponse) GetPayId() string { + if x != nil { + return x.PayId + } + return "" +} + +func (x *PayUrlResponse) GetPayReturn() string { + if x != nil { + return x.PayReturn + } + return "" +} + +func (x *PayUrlResponse) GetPayStatus() string { + if x != nil { + return x.PayStatus + } + return "" +} + +type PaybackRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Mchid string `protobuf:"bytes,1,opt,name=mchid,proto3" json:"mchid,omitempty"` + PayChannel string `protobuf:"bytes,2,opt,name=pay_channel,json=payChannel,proto3" json:"pay_channel,omitempty"` + PayId string `protobuf:"bytes,3,opt,name=pay_id,json=payId,proto3" json:"pay_id,omitempty"` + EventType string `protobuf:"bytes,4,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` +} + +func (x *PaybackRequest) Reset() { + *x = PaybackRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PaybackRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PaybackRequest) ProtoMessage() {} + +func (x *PaybackRequest) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PaybackRequest.ProtoReflect.Descriptor instead. +func (*PaybackRequest) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{10} +} + +func (x *PaybackRequest) GetMchid() string { + if x != nil { + return x.Mchid + } + return "" +} + +func (x *PaybackRequest) GetPayChannel() string { + if x != nil { + return x.PayChannel + } + return "" +} + +func (x *PaybackRequest) GetPayId() string { + if x != nil { + return x.PayId + } + return "" +} + +func (x *PaybackRequest) GetEventType() string { + if x != nil { + return x.EventType + } + return "" +} + +type PaybackResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OutTradeNo string `protobuf:"bytes,1,opt,name=out_trade_no,json=outTradeNo,proto3" json:"out_trade_no,omitempty"` + TradeState string `protobuf:"bytes,2,opt,name=trade_state,json=tradeState,proto3" json:"trade_state,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *PaybackResp) Reset() { + *x = PaybackResp{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PaybackResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PaybackResp) ProtoMessage() {} + +func (x *PaybackResp) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PaybackResp.ProtoReflect.Descriptor instead. +func (*PaybackResp) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{11} +} + +func (x *PaybackResp) GetOutTradeNo() string { + if x != nil { + return x.OutTradeNo + } + return "" +} + +func (x *PaybackResp) GetTradeState() string { + if x != nil { + return x.TradeState + } + return "" +} + +func (x *PaybackResp) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type GetPayTransOutTradeNoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Appid string `protobuf:"bytes,1,opt,name=appid,proto3" json:"appid,omitempty"` + Mchid string `protobuf:"bytes,2,opt,name=mchid,proto3" json:"mchid,omitempty"` + OutTradeNo string `protobuf:"bytes,3,opt,name=out_trade_no,json=outTradeNo,proto3" json:"out_trade_no,omitempty"` +} + +func (x *GetPayTransOutTradeNoRequest) Reset() { + *x = GetPayTransOutTradeNoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetPayTransOutTradeNoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPayTransOutTradeNoRequest) ProtoMessage() {} + +func (x *GetPayTransOutTradeNoRequest) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPayTransOutTradeNoRequest.ProtoReflect.Descriptor instead. +func (*GetPayTransOutTradeNoRequest) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{12} +} + +func (x *GetPayTransOutTradeNoRequest) GetAppid() string { + if x != nil { + return x.Appid + } + return "" +} + +func (x *GetPayTransOutTradeNoRequest) GetMchid() string { + if x != nil { + return x.Mchid + } + return "" +} + +func (x *GetPayTransOutTradeNoRequest) GetOutTradeNo() string { + if x != nil { + return x.OutTradeNo + } + return "" +} + +type GetPayTransactionResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Data *GetPayTransaction `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *GetPayTransactionResp) Reset() { + *x = GetPayTransactionResp{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetPayTransactionResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPayTransactionResp) ProtoMessage() {} + +func (x *GetPayTransactionResp) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPayTransactionResp.ProtoReflect.Descriptor instead. +func (*GetPayTransactionResp) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{13} +} + +func (x *GetPayTransactionResp) GetData() *GetPayTransaction { + if x != nil { + return x.Data + } + return nil +} + +type GetPayTransaction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Appid string `protobuf:"bytes,1,opt,name=appid,proto3" json:"appid,omitempty"` + Mchid string `protobuf:"bytes,2,opt,name=mchid,proto3" json:"mchid,omitempty"` +} + +func (x *GetPayTransaction) Reset() { + *x = GetPayTransaction{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetPayTransaction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPayTransaction) ProtoMessage() {} + +func (x *GetPayTransaction) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPayTransaction.ProtoReflect.Descriptor instead. +func (*GetPayTransaction) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{14} +} + +func (x *GetPayTransaction) GetAppid() string { + if x != nil { + return x.Appid + } + return "" +} + +func (x *GetPayTransaction) GetMchid() string { + if x != nil { + return x.Mchid + } + return "" +} + +type CloseBillRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` +} + +func (x *CloseBillRequest) Reset() { + *x = CloseBillRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_greeter_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CloseBillRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseBillRequest) ProtoMessage() {} + +func (x *CloseBillRequest) ProtoReflect() protoreflect.Message { + mi := &file_greeter_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CloseBillRequest.ProtoReflect.Descriptor instead. +func (*CloseBillRequest) Descriptor() ([]byte, []int) { + return file_greeter_proto_rawDescGZIP(), []int{15} +} + +func (x *CloseBillRequest) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +var File_greeter_proto protoreflect.FileDescriptor + +var file_greeter_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x67, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x03, 0x61, 0x70, 0x69, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x25, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2d, 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x30, 0x0a, 0x0c, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x20, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x44, 0x69, 0x73, + 0x74, 0x72, 0x69, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x7f, 0x0a, 0x08, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x64, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x64, 0x63, 0x6f, 0x64, 0x65, + 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x08, + 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x52, 0x08, 0x63, + 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x22, 0x32, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x74, 0x72, + 0x69, 0x63, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x21, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x69, 0x73, + 0x74, 0x72, 0x69, 0x63, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0xa9, 0x02, 0x0a, 0x0f, + 0x50, 0x61, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x61, 0x70, 0x70, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x63, 0x68, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x63, 0x68, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x6f, + 0x75, 0x74, 0x5f, 0x74, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x6e, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x54, 0x72, 0x61, 0x64, 0x65, 0x4e, 0x6f, 0x12, 0x16, 0x0a, + 0x06, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, + 0x74, 0x74, 0x61, 0x63, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, + 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, + 0x79, 0x55, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x79, 0x5f, + 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, + 0x61, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x55, 0x72, 0x6c, 0x22, 0x6b, 0x0a, 0x10, 0x50, 0x61, 0x79, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x22, 0x6d, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x55, 0x72, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x63, 0x68, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x63, 0x68, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, + 0x61, 0x79, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x70, 0x61, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x25, 0x0a, 0x0e, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x22, 0x86, 0x01, 0x0a, 0x0e, 0x50, 0x61, 0x79, 0x55, 0x72, 0x6c, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x79, 0x5f, 0x63, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x79, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x15, 0x0a, 0x06, 0x70, 0x61, 0x79, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x79, 0x49, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x70, 0x61, 0x79, 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x79, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x12, 0x1d, 0x0a, + 0x0a, 0x70, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x70, 0x61, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x7d, 0x0a, 0x0e, + 0x50, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, + 0x0a, 0x05, 0x6d, 0x63, 0x68, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, + 0x63, 0x68, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x79, 0x5f, 0x63, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x79, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x15, 0x0a, 0x06, 0x70, 0x61, 0x79, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x79, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x6a, 0x0a, 0x0b, 0x50, + 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x20, 0x0a, 0x0c, 0x6f, 0x75, + 0x74, 0x5f, 0x74, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x54, 0x72, 0x61, 0x64, 0x65, 0x4e, 0x6f, 0x12, 0x1f, 0x0a, 0x0b, + 0x74, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x74, 0x72, 0x61, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x6c, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x50, 0x61, + 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x4f, 0x75, 0x74, 0x54, 0x72, 0x61, 0x64, 0x65, 0x4e, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x69, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x6d, 0x63, 0x68, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x63, + 0x68, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x5f, 0x74, 0x72, 0x61, 0x64, 0x65, + 0x5f, 0x6e, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x54, 0x72, + 0x61, 0x64, 0x65, 0x4e, 0x6f, 0x22, 0x43, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2a, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3f, 0x0a, 0x11, 0x47, 0x65, + 0x74, 0x50, 0x61, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x61, 0x70, 0x70, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x63, 0x68, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x63, 0x68, 0x69, 0x64, 0x22, 0x39, 0x0a, 0x10, 0x43, + 0x6c, 0x6f, 0x73, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x32, 0xf1, 0x04, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, 0x74, + 0x65, 0x72, 0x12, 0x30, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x4c, + 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, + 0x12, 0x3d, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x43, 0x61, 0x73, 0x63, + 0x61, 0x64, 0x65, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, + 0x42, 0x0a, 0x11, 0x50, 0x61, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x70, 0x70, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, 0x79, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x50, 0x61, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x55, 0x72, 0x6c, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, 0x79, 0x55, 0x72, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, + 0x61, 0x79, 0x55, 0x72, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x43, 0x0a, 0x14, 0x50, 0x61, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x70, 0x70, 0x55, 0x72, 0x6c, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, + 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, 0x79, 0x55, 0x72, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x0e, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x50, + 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, 0x79, + 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x50, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, + 0x38, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x50, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, + 0x12, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, 0x79, 0x62, + 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x11, 0x47, 0x65, 0x74, + 0x50, 0x61, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, + 0x50, 0x61, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x09, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x42, 0x69, 0x6c, + 0x6c, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x42, 0x69, 0x6c, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, + 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x11, 0x5a, 0x0f, 0x62, 0x6b, + 0x62, 0x2d, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_greeter_proto_rawDescOnce sync.Once + file_greeter_proto_rawDescData = file_greeter_proto_rawDesc +) + +func file_greeter_proto_rawDescGZIP() []byte { + file_greeter_proto_rawDescOnce.Do(func() { + file_greeter_proto_rawDescData = protoimpl.X.CompressGZIP(file_greeter_proto_rawDescData) + }) + return file_greeter_proto_rawDescData +} + +var file_greeter_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_greeter_proto_goTypes = []interface{}{ + (*PingReply)(nil), // 0: api.PingReply + (*Country)(nil), // 1: api.Country + (*CountryReply)(nil), // 2: api.CountryReply + (*DistrictRequest)(nil), // 3: api.DistrictRequest + (*District)(nil), // 4: api.District + (*DistrictReply)(nil), // 5: api.DistrictReply + (*PayTransRequest)(nil), // 6: api.PayTransRequest + (*PayTransResponse)(nil), // 7: api.PayTransResponse + (*PayUrlRequest)(nil), // 8: api.PayUrlRequest + (*PayUrlResponse)(nil), // 9: api.PayUrlResponse + (*PaybackRequest)(nil), // 10: api.PaybackRequest + (*PaybackResp)(nil), // 11: api.PaybackResp + (*GetPayTransOutTradeNoRequest)(nil), // 12: api.GetPayTransOutTradeNoRequest + (*GetPayTransactionResp)(nil), // 13: api.GetPayTransactionResp + (*GetPayTransaction)(nil), // 14: api.GetPayTransaction + (*CloseBillRequest)(nil), // 15: api.CloseBillRequest + (*emptypb.Empty)(nil), // 16: google.protobuf.Empty +} +var file_greeter_proto_depIdxs = []int32{ + 1, // 0: api.CountryReply.list:type_name -> api.Country + 4, // 1: api.District.children:type_name -> api.District + 4, // 2: api.DistrictReply.list:type_name -> api.District + 14, // 3: api.GetPayTransactionResp.data:type_name -> api.GetPayTransaction + 16, // 4: api.Greeter.Ping:input_type -> google.protobuf.Empty + 16, // 5: api.Greeter.CountryList:input_type -> google.protobuf.Empty + 3, // 6: api.Greeter.DistrictCascade:input_type -> api.DistrictRequest + 6, // 7: api.Greeter.PayTransactionApp:input_type -> api.PayTransRequest + 8, // 8: api.Greeter.GetPaymentUrl:input_type -> api.PayUrlRequest + 6, // 9: api.Greeter.PayTransactionAppUrl:input_type -> api.PayTransRequest + 10, // 10: api.Greeter.SuccessPayback:input_type -> api.PaybackRequest + 10, // 11: api.Greeter.PaypalPayback:input_type -> api.PaybackRequest + 16, // 12: api.Greeter.GetPayTransaction:input_type -> google.protobuf.Empty + 15, // 13: api.Greeter.CloseBill:input_type -> api.CloseBillRequest + 0, // 14: api.Greeter.Ping:output_type -> api.PingReply + 2, // 15: api.Greeter.CountryList:output_type -> api.CountryReply + 5, // 16: api.Greeter.DistrictCascade:output_type -> api.DistrictReply + 7, // 17: api.Greeter.PayTransactionApp:output_type -> api.PayTransResponse + 9, // 18: api.Greeter.GetPaymentUrl:output_type -> api.PayUrlResponse + 9, // 19: api.Greeter.PayTransactionAppUrl:output_type -> api.PayUrlResponse + 11, // 20: api.Greeter.SuccessPayback:output_type -> api.PaybackResp + 11, // 21: api.Greeter.PaypalPayback:output_type -> api.PaybackResp + 13, // 22: api.Greeter.GetPayTransaction:output_type -> api.GetPayTransactionResp + 0, // 23: api.Greeter.CloseBill:output_type -> api.PingReply + 14, // [14:24] is the sub-list for method output_type + 4, // [4:14] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_greeter_proto_init() } +func file_greeter_proto_init() { + if File_greeter_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_greeter_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Country); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CountryReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DistrictRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*District); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DistrictReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PayTransRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PayTransResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PayUrlRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PayUrlResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PaybackRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PaybackResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetPayTransOutTradeNoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetPayTransactionResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetPayTransaction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_greeter_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CloseBillRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_greeter_proto_rawDesc, + NumEnums: 0, + NumMessages: 16, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_greeter_proto_goTypes, + DependencyIndexes: file_greeter_proto_depIdxs, + MessageInfos: file_greeter_proto_msgTypes, + }.Build() + File_greeter_proto = out.File + file_greeter_proto_rawDesc = nil + file_greeter_proto_goTypes = nil + file_greeter_proto_depIdxs = nil +} diff --git a/initialize/api/greeter.proto b/initialize/api/greeter.proto new file mode 100644 index 0000000..d69ca0b --- /dev/null +++ b/initialize/api/greeter.proto @@ -0,0 +1,126 @@ +syntax = "proto3"; + +package api; + +import "google/protobuf/empty.proto"; +//import "common.proto"; +option go_package = "bkb-payment/api"; + + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc Ping (google.protobuf.Empty) returns (PingReply) { + + } + rpc CountryList (google.protobuf.Empty) returns (CountryReply) { + + } + rpc DistrictCascade (DistrictRequest) returns (DistrictReply) { + + } + rpc PayTransactionApp(PayTransRequest) returns (PayTransResponse) { + + } + rpc GetPaymentUrl(PayUrlRequest) returns (PayUrlResponse) { + + } + rpc PayTransactionAppUrl(PayTransRequest) returns (PayUrlResponse) { + + } + rpc SuccessPayback(PaybackRequest) returns (PaybackResp) { + + } + rpc PaypalPayback(PaybackRequest) returns (PaybackResp) { + + } + rpc GetPayTransaction(google.protobuf.Empty) returns (GetPayTransactionResp) { + + } + rpc CloseBill(CloseBillRequest) returns (PingReply) { + + } + // rpc ClosePayTransaction(google.protobuf.Empty) returns (PingReply) { + // option (google.api.http) = { + // post: "/pay/transaction/outTradeNo/close" + // }; + // } +} + +// The response message containing the greetings +message PingReply { + string message = 1; +} +message Country{ + int32 id = 1; + string name = 2; +} +message CountryReply{ + repeated Country list = 1; +} +message DistrictRequest { + int32 country = 1; +} +message District { + string label = 1; + string adcode = 2; + int32 parentId = 3; + repeated District children = 4; +} +message DistrictReply{ + repeated District list = 1; +} +message PayTransRequest{ + string appid = 1; + string mchid = 2; + string out_trade_no = 3; + string attach = 4; + string notify_url = 5; + double amount = 6; + string currency = 7; + string pay_channel = 8; + string return_url = 9; + string cancel_url = 10; +} +message PayTransResponse{ + string transaction_id = 1; + string status = 2; + string message = 3; +} +message PayUrlRequest{ + string mchid = 1; + string pay_channel = 2; + string transaction_id = 3; +} +message PayUrlResponse{ + string pay_channel = 1; + string pay_id = 2; + string pay_return = 3; + string pay_status = 4; +} +message PaybackRequest{ + string mchid = 1; + string pay_channel = 2; + string pay_id = 3; + string event_type = 4; +} +message PaybackResp{ + string out_trade_no = 1; + string trade_state = 2; + string message = 3; +} +message GetPayTransOutTradeNoRequest{ + string appid = 1; + string mchid = 2; + string out_trade_no = 3; +} +message GetPayTransactionResp{ + GetPayTransaction data = 1; +} +message GetPayTransaction{ + string appid = 1; + string mchid = 2; +} +message CloseBillRequest{ + string transaction_id = 1; +} \ No newline at end of file diff --git a/initialize/api/greeter_grpc.pb.go b/initialize/api/greeter_grpc.pb.go new file mode 100644 index 0000000..8dd7faa --- /dev/null +++ b/initialize/api/greeter_grpc.pb.go @@ -0,0 +1,432 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.23.4 +// source: greeter.proto + +package api + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + emptypb "google.golang.org/protobuf/types/known/emptypb" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// GreeterClient is the client API for Greeter service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type GreeterClient interface { + // Sends a greeting + Ping(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*PingReply, error) + CountryList(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CountryReply, error) + DistrictCascade(ctx context.Context, in *DistrictRequest, opts ...grpc.CallOption) (*DistrictReply, error) + PayTransactionApp(ctx context.Context, in *PayTransRequest, opts ...grpc.CallOption) (*PayTransResponse, error) + GetPaymentUrl(ctx context.Context, in *PayUrlRequest, opts ...grpc.CallOption) (*PayUrlResponse, error) + PayTransactionAppUrl(ctx context.Context, in *PayTransRequest, opts ...grpc.CallOption) (*PayUrlResponse, error) + SuccessPayback(ctx context.Context, in *PaybackRequest, opts ...grpc.CallOption) (*PaybackResp, error) + PaypalPayback(ctx context.Context, in *PaybackRequest, opts ...grpc.CallOption) (*PaybackResp, error) + GetPayTransaction(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetPayTransactionResp, error) + CloseBill(ctx context.Context, in *CloseBillRequest, opts ...grpc.CallOption) (*PingReply, error) +} + +type greeterClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { + return &greeterClient{cc} +} + +func (c *greeterClient) Ping(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*PingReply, error) { + out := new(PingReply) + err := c.cc.Invoke(ctx, "/api.Greeter/Ping", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greeterClient) CountryList(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CountryReply, error) { + out := new(CountryReply) + err := c.cc.Invoke(ctx, "/api.Greeter/CountryList", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greeterClient) DistrictCascade(ctx context.Context, in *DistrictRequest, opts ...grpc.CallOption) (*DistrictReply, error) { + out := new(DistrictReply) + err := c.cc.Invoke(ctx, "/api.Greeter/DistrictCascade", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greeterClient) PayTransactionApp(ctx context.Context, in *PayTransRequest, opts ...grpc.CallOption) (*PayTransResponse, error) { + out := new(PayTransResponse) + err := c.cc.Invoke(ctx, "/api.Greeter/PayTransactionApp", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greeterClient) GetPaymentUrl(ctx context.Context, in *PayUrlRequest, opts ...grpc.CallOption) (*PayUrlResponse, error) { + out := new(PayUrlResponse) + err := c.cc.Invoke(ctx, "/api.Greeter/GetPaymentUrl", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greeterClient) PayTransactionAppUrl(ctx context.Context, in *PayTransRequest, opts ...grpc.CallOption) (*PayUrlResponse, error) { + out := new(PayUrlResponse) + err := c.cc.Invoke(ctx, "/api.Greeter/PayTransactionAppUrl", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greeterClient) SuccessPayback(ctx context.Context, in *PaybackRequest, opts ...grpc.CallOption) (*PaybackResp, error) { + out := new(PaybackResp) + err := c.cc.Invoke(ctx, "/api.Greeter/SuccessPayback", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greeterClient) PaypalPayback(ctx context.Context, in *PaybackRequest, opts ...grpc.CallOption) (*PaybackResp, error) { + out := new(PaybackResp) + err := c.cc.Invoke(ctx, "/api.Greeter/PaypalPayback", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greeterClient) GetPayTransaction(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetPayTransactionResp, error) { + out := new(GetPayTransactionResp) + err := c.cc.Invoke(ctx, "/api.Greeter/GetPayTransaction", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greeterClient) CloseBill(ctx context.Context, in *CloseBillRequest, opts ...grpc.CallOption) (*PingReply, error) { + out := new(PingReply) + err := c.cc.Invoke(ctx, "/api.Greeter/CloseBill", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GreeterServer is the server API for Greeter service. +// All implementations must embed UnimplementedGreeterServer +// for forward compatibility +type GreeterServer interface { + // Sends a greeting + Ping(context.Context, *emptypb.Empty) (*PingReply, error) + CountryList(context.Context, *emptypb.Empty) (*CountryReply, error) + DistrictCascade(context.Context, *DistrictRequest) (*DistrictReply, error) + PayTransactionApp(context.Context, *PayTransRequest) (*PayTransResponse, error) + GetPaymentUrl(context.Context, *PayUrlRequest) (*PayUrlResponse, error) + PayTransactionAppUrl(context.Context, *PayTransRequest) (*PayUrlResponse, error) + SuccessPayback(context.Context, *PaybackRequest) (*PaybackResp, error) + PaypalPayback(context.Context, *PaybackRequest) (*PaybackResp, error) + GetPayTransaction(context.Context, *emptypb.Empty) (*GetPayTransactionResp, error) + CloseBill(context.Context, *CloseBillRequest) (*PingReply, error) + mustEmbedUnimplementedGreeterServer() +} + +// UnimplementedGreeterServer must be embedded to have forward compatible implementations. +type UnimplementedGreeterServer struct { +} + +func (UnimplementedGreeterServer) Ping(context.Context, *emptypb.Empty) (*PingReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedGreeterServer) CountryList(context.Context, *emptypb.Empty) (*CountryReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method CountryList not implemented") +} +func (UnimplementedGreeterServer) DistrictCascade(context.Context, *DistrictRequest) (*DistrictReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method DistrictCascade not implemented") +} +func (UnimplementedGreeterServer) PayTransactionApp(context.Context, *PayTransRequest) (*PayTransResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PayTransactionApp not implemented") +} +func (UnimplementedGreeterServer) GetPaymentUrl(context.Context, *PayUrlRequest) (*PayUrlResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetPaymentUrl not implemented") +} +func (UnimplementedGreeterServer) PayTransactionAppUrl(context.Context, *PayTransRequest) (*PayUrlResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PayTransactionAppUrl not implemented") +} +func (UnimplementedGreeterServer) SuccessPayback(context.Context, *PaybackRequest) (*PaybackResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method SuccessPayback not implemented") +} +func (UnimplementedGreeterServer) PaypalPayback(context.Context, *PaybackRequest) (*PaybackResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method PaypalPayback not implemented") +} +func (UnimplementedGreeterServer) GetPayTransaction(context.Context, *emptypb.Empty) (*GetPayTransactionResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetPayTransaction not implemented") +} +func (UnimplementedGreeterServer) CloseBill(context.Context, *CloseBillRequest) (*PingReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method CloseBill not implemented") +} +func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {} + +// UnsafeGreeterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GreeterServer will +// result in compilation errors. +type UnsafeGreeterServer interface { + mustEmbedUnimplementedGreeterServer() +} + +func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) { + s.RegisterService(&Greeter_ServiceDesc, srv) +} + +func _Greeter_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Greeter/Ping", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).Ping(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Greeter_CountryList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).CountryList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Greeter/CountryList", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).CountryList(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Greeter_DistrictCascade_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DistrictRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).DistrictCascade(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Greeter/DistrictCascade", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).DistrictCascade(ctx, req.(*DistrictRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Greeter_PayTransactionApp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PayTransRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).PayTransactionApp(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Greeter/PayTransactionApp", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).PayTransactionApp(ctx, req.(*PayTransRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Greeter_GetPaymentUrl_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PayUrlRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).GetPaymentUrl(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Greeter/GetPaymentUrl", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).GetPaymentUrl(ctx, req.(*PayUrlRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Greeter_PayTransactionAppUrl_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PayTransRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).PayTransactionAppUrl(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Greeter/PayTransactionAppUrl", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).PayTransactionAppUrl(ctx, req.(*PayTransRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Greeter_SuccessPayback_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PaybackRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).SuccessPayback(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Greeter/SuccessPayback", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).SuccessPayback(ctx, req.(*PaybackRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Greeter_PaypalPayback_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PaybackRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).PaypalPayback(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Greeter/PaypalPayback", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).PaypalPayback(ctx, req.(*PaybackRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Greeter_GetPayTransaction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).GetPayTransaction(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Greeter/GetPayTransaction", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).GetPayTransaction(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Greeter_CloseBill_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CloseBillRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).CloseBill(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Greeter/CloseBill", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).CloseBill(ctx, req.(*CloseBillRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Greeter_ServiceDesc is the grpc.ServiceDesc for Greeter service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Greeter_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "api.Greeter", + HandlerType: (*GreeterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _Greeter_Ping_Handler, + }, + { + MethodName: "CountryList", + Handler: _Greeter_CountryList_Handler, + }, + { + MethodName: "DistrictCascade", + Handler: _Greeter_DistrictCascade_Handler, + }, + { + MethodName: "PayTransactionApp", + Handler: _Greeter_PayTransactionApp_Handler, + }, + { + MethodName: "GetPaymentUrl", + Handler: _Greeter_GetPaymentUrl_Handler, + }, + { + MethodName: "PayTransactionAppUrl", + Handler: _Greeter_PayTransactionAppUrl_Handler, + }, + { + MethodName: "SuccessPayback", + Handler: _Greeter_SuccessPayback_Handler, + }, + { + MethodName: "PaypalPayback", + Handler: _Greeter_PaypalPayback_Handler, + }, + { + MethodName: "GetPayTransaction", + Handler: _Greeter_GetPayTransaction_Handler, + }, + { + MethodName: "CloseBill", + Handler: _Greeter_CloseBill_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "greeter.proto", +} diff --git a/initialize/api/sms.pb.go b/initialize/api/sms.pb.go new file mode 100644 index 0000000..ec1a800 --- /dev/null +++ b/initialize/api/sms.pb.go @@ -0,0 +1,329 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.12 +// source: sms.proto + +package api + +import ( + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type SendSmsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // 手机号码,必填 + Phone string `protobuf:"bytes,1,opt,name=phone,proto3" json:"phone,omitempty"` + // 短信场景值 1,2,3,4 + SmsType int32 `protobuf:"varint,2,opt,name=smsType,proto3" json:"smsType,omitempty"` + // 国际区号 86 中国 1美国 + AreaCode string `protobuf:"bytes,3,opt,name=areaCode,proto3" json:"areaCode,omitempty"` +} + +func (x *SendSmsRequest) Reset() { + *x = SendSmsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_sms_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendSmsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendSmsRequest) ProtoMessage() {} + +func (x *SendSmsRequest) ProtoReflect() protoreflect.Message { + mi := &file_sms_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendSmsRequest.ProtoReflect.Descriptor instead. +func (*SendSmsRequest) Descriptor() ([]byte, []int) { + return file_sms_proto_rawDescGZIP(), []int{0} +} + +func (x *SendSmsRequest) GetPhone() string { + if x != nil { + return x.Phone + } + return "" +} + +func (x *SendSmsRequest) GetSmsType() int32 { + if x != nil { + return x.SmsType + } + return 0 +} + +func (x *SendSmsRequest) GetAreaCode() string { + if x != nil { + return x.AreaCode + } + return "" +} + +// 短信发送回复 +type SendSmsReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *SendSmsReply) Reset() { + *x = SendSmsReply{} + if protoimpl.UnsafeEnabled { + mi := &file_sms_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendSmsReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendSmsReply) ProtoMessage() {} + +func (x *SendSmsReply) ProtoReflect() protoreflect.Message { + mi := &file_sms_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendSmsReply.ProtoReflect.Descriptor instead. +func (*SendSmsReply) Descriptor() ([]byte, []int) { + return file_sms_proto_rawDescGZIP(), []int{1} +} + +func (x *SendSmsReply) GetCode() int32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *SendSmsReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type SmsCodeVerifyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // 手机号码,必填 + Phone string `protobuf:"bytes,1,opt,name=phone,proto3" json:"phone,omitempty"` + // 短信验证码 + Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"` +} + +func (x *SmsCodeVerifyRequest) Reset() { + *x = SmsCodeVerifyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_sms_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SmsCodeVerifyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SmsCodeVerifyRequest) ProtoMessage() {} + +func (x *SmsCodeVerifyRequest) ProtoReflect() protoreflect.Message { + mi := &file_sms_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SmsCodeVerifyRequest.ProtoReflect.Descriptor instead. +func (*SmsCodeVerifyRequest) Descriptor() ([]byte, []int) { + return file_sms_proto_rawDescGZIP(), []int{2} +} + +func (x *SmsCodeVerifyRequest) GetPhone() string { + if x != nil { + return x.Phone + } + return "" +} + +func (x *SmsCodeVerifyRequest) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +var File_sms_proto protoreflect.FileDescriptor + +var file_sms_proto_rawDesc = []byte{ + 0x0a, 0x09, 0x73, 0x6d, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x61, 0x70, 0x69, + 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, + 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5c, + 0x0a, 0x0e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6d, 0x73, 0x54, 0x79, 0x70, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x73, 0x6d, 0x73, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x61, 0x72, 0x65, 0x61, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3c, 0x0a, 0x0c, + 0x53, 0x65, 0x6e, 0x64, 0x53, 0x6d, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x40, 0x0a, 0x14, 0x53, 0x6d, + 0x73, 0x43, 0x6f, 0x64, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x32, 0xa9, 0x01, 0x0a, + 0x03, 0x53, 0x6d, 0x73, 0x12, 0x4a, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x6d, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, + 0x65, 0x6e, 0x64, 0x53, 0x6d, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x13, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x0d, 0x3a, 0x01, 0x2a, 0x22, 0x08, 0x73, 0x6d, 0x73, 0x2f, 0x73, 0x65, 0x6e, 0x64, + 0x12, 0x56, 0x0a, 0x0a, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x19, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x6d, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x65, 0x6e, 0x64, 0x53, 0x6d, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1a, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x14, 0x3a, 0x01, 0x2a, 0x22, 0x0f, 0x73, 0x6d, 0x73, 0x2f, 0x63, 0x6f, 0x64, + 0x65, 0x2d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x42, 0x10, 0x5a, 0x0e, 0x62, 0x6b, 0x62, 0x2d, + 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_sms_proto_rawDescOnce sync.Once + file_sms_proto_rawDescData = file_sms_proto_rawDesc +) + +func file_sms_proto_rawDescGZIP() []byte { + file_sms_proto_rawDescOnce.Do(func() { + file_sms_proto_rawDescData = protoimpl.X.CompressGZIP(file_sms_proto_rawDescData) + }) + return file_sms_proto_rawDescData +} + +var file_sms_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_sms_proto_goTypes = []interface{}{ + (*SendSmsRequest)(nil), // 0: api.SendSmsRequest + (*SendSmsReply)(nil), // 1: api.SendSmsReply + (*SmsCodeVerifyRequest)(nil), // 2: api.SmsCodeVerifyRequest +} +var file_sms_proto_depIdxs = []int32{ + 0, // 0: api.Sms.SendMessage:input_type -> api.SendSmsRequest + 2, // 1: api.Sms.VerifyCode:input_type -> api.SmsCodeVerifyRequest + 1, // 2: api.Sms.SendMessage:output_type -> api.SendSmsReply + 1, // 3: api.Sms.VerifyCode:output_type -> api.SendSmsReply + 2, // [2:4] is the sub-list for method output_type + 0, // [0:2] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_sms_proto_init() } +func file_sms_proto_init() { + if File_sms_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_sms_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SendSmsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_sms_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SendSmsReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_sms_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SmsCodeVerifyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_sms_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_sms_proto_goTypes, + DependencyIndexes: file_sms_proto_depIdxs, + MessageInfos: file_sms_proto_msgTypes, + }.Build() + File_sms_proto = out.File + file_sms_proto_rawDesc = nil + file_sms_proto_goTypes = nil + file_sms_proto_depIdxs = nil +} diff --git a/initialize/api/sms.proto b/initialize/api/sms.proto new file mode 100644 index 0000000..7313b96 --- /dev/null +++ b/initialize/api/sms.proto @@ -0,0 +1,47 @@ +syntax = "proto3"; + +package api; + +import "google/api/annotations.proto"; +option go_package = "bkb-notify/api"; + + +// The Email service definition. +service Sms { + // 发送一条短信 + rpc SendMessage (SendSmsRequest) returns (SendSmsReply) { + option (google.api.http) = { + post: "sms/send" + body: "*" + }; + } + // 校验短信code + rpc VerifyCode (SmsCodeVerifyRequest) returns (SendSmsReply) { + option (google.api.http) = { + post: "sms/code-verify" + body: "*" + }; + } +} + +message SendSmsRequest { + //手机号码,必填 + string phone=1; + //短信场景值 1,2,3,4 + int32 smsType=2; + //国际区号 86 中国 1美国 + string areaCode = 3; +} + +// 短信发送回复 +message SendSmsReply { + int32 code = 1; + string message = 2; +} + +message SmsCodeVerifyRequest { + //手机号码,必填 + string phone=1; + //短信验证码 + string code=2; +} \ No newline at end of file diff --git a/initialize/api/sms_grpc.pb.go b/initialize/api/sms_grpc.pb.go new file mode 100644 index 0000000..680ccba --- /dev/null +++ b/initialize/api/sms_grpc.pb.go @@ -0,0 +1,150 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v3.21.12 +// source: sms.proto + +package api + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + Sms_SendMessage_FullMethodName = "/api.Sms/SendMessage" + Sms_VerifyCode_FullMethodName = "/api.Sms/VerifyCode" +) + +// SmsClient is the client API for Sms service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type SmsClient interface { + // 发送一条短信 + SendMessage(ctx context.Context, in *SendSmsRequest, opts ...grpc.CallOption) (*SendSmsReply, error) + // 校验短信code + VerifyCode(ctx context.Context, in *SmsCodeVerifyRequest, opts ...grpc.CallOption) (*SendSmsReply, error) +} + +type smsClient struct { + cc grpc.ClientConnInterface +} + +func NewSmsClient(cc grpc.ClientConnInterface) SmsClient { + return &smsClient{cc} +} + +func (c *smsClient) SendMessage(ctx context.Context, in *SendSmsRequest, opts ...grpc.CallOption) (*SendSmsReply, error) { + out := new(SendSmsReply) + err := c.cc.Invoke(ctx, Sms_SendMessage_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *smsClient) VerifyCode(ctx context.Context, in *SmsCodeVerifyRequest, opts ...grpc.CallOption) (*SendSmsReply, error) { + out := new(SendSmsReply) + err := c.cc.Invoke(ctx, Sms_VerifyCode_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// SmsServer is the server API for Sms service. +// All implementations must embed UnimplementedSmsServer +// for forward compatibility +type SmsServer interface { + // 发送一条短信 + SendMessage(context.Context, *SendSmsRequest) (*SendSmsReply, error) + // 校验短信code + VerifyCode(context.Context, *SmsCodeVerifyRequest) (*SendSmsReply, error) + mustEmbedUnimplementedSmsServer() +} + +// UnimplementedSmsServer must be embedded to have forward compatible implementations. +type UnimplementedSmsServer struct { +} + +func (UnimplementedSmsServer) SendMessage(context.Context, *SendSmsRequest) (*SendSmsReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SendMessage not implemented") +} +func (UnimplementedSmsServer) VerifyCode(context.Context, *SmsCodeVerifyRequest) (*SendSmsReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method VerifyCode not implemented") +} +func (UnimplementedSmsServer) mustEmbedUnimplementedSmsServer() {} + +// UnsafeSmsServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SmsServer will +// result in compilation errors. +type UnsafeSmsServer interface { + mustEmbedUnimplementedSmsServer() +} + +func RegisterSmsServer(s grpc.ServiceRegistrar, srv SmsServer) { + s.RegisterService(&Sms_ServiceDesc, srv) +} + +func _Sms_SendMessage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SendSmsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SmsServer).SendMessage(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sms_SendMessage_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SmsServer).SendMessage(ctx, req.(*SendSmsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sms_VerifyCode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SmsCodeVerifyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SmsServer).VerifyCode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Sms_VerifyCode_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SmsServer).VerifyCode(ctx, req.(*SmsCodeVerifyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Sms_ServiceDesc is the grpc.ServiceDesc for Sms service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Sms_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "api.Sms", + HandlerType: (*SmsServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SendMessage", + Handler: _Sms_SendMessage_Handler, + }, + { + MethodName: "VerifyCode", + Handler: _Sms_VerifyCode_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "sms.proto", +} diff --git a/initialize/gorm.go b/initialize/gorm.go new file mode 100644 index 0000000..923c5e7 --- /dev/null +++ b/initialize/gorm.go @@ -0,0 +1,110 @@ +package initialize + +import ( + "fmt" + "os" + "pure/global" + "pure/initialize/internal" + "pure/model" + + "go.uber.org/zap" + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +//@function: Gorm +//@description: 初始化数据库并产生数据库全局变量 +//@return: *gorm.DB + +func Gorm() *gorm.DB { + switch global.MG_CONFIG.System.DbType { + case "mysql": + return GormMysql() + default: + return GormMysql() + } +} + +// MysqlTables +//@function: MysqlTables +//@description: 注册数据库表专用 +//@param: db *gorm.DB + +func MysqlTables(db *gorm.DB) { + err := db.AutoMigrate( + model.Account{}, + model.Address{}, + model.Bill{}, + model.Order{}, + model.OrderAddress{}, + model.TbGoods{}, + model.TbGoodsSpecs{}, + model.Wallet{}, + model.JwtBlacklist{}, + //model.SysDictionary{}, + //model.SysDictionaryDetail{}, + //model.ExaFileUploadAndDownload{}, + //model.ExaFile{}, + //model.ExaFileChunk{}, + //model.ExaCustomer{}, + //model.ExaSimpleUploader{}, + + // Code generated by pure Begin; DO NOT EDIT. + // Code generated by pure End; DO NOT EDIT. + model.Mission{}, + model.MissionClaimAddress{}, + model.CollectionMission{}, + model.CollectionGoods{}, + model.PaypalWebhook{}, + model.MissionClaimWorks{}, + model.MissionClaimOrder{}, + model.MissionClaimOrderGoods{}, + model.Internationalization{}, + model.MissionClaim{}, + model.MissionClaimVideo{}, + model.PlatformAuth{}, + model.SysMissionReward{}, //平台任务奖励 + model.DtStatisticOrder{}, + model.Withdrawal{}, // 提现 + model.User{}, + model.Notify{}, + model.Version{}, + ) + if err != nil { + global.MG_LOG.Error("register table failed", zap.Any("err", err)) + os.Exit(0) + } + + global.MG_LOG.Info("register table success") +} + +// @function: GormMysql +// @description: 初始化Mysql数据库 +// @return: *gorm.DB +func GormMysql() *gorm.DB { + m := global.MG_CONFIG.Mysql + if m.Dbname == "" { + return nil + } + dsn := m.Username + ":" + m.Password + "@tcp(" + m.Path + ")/" + m.Dbname + "?" + m.Config + mysqlConfig := mysql.Config{ + DSN: dsn, // DSN data source name + DefaultStringSize: 191, // string 类型字段的默认长度 + DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持 + DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引 + DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列 + SkipInitializeWithVersion: false, // 根据版本自动配置 + } + fmt.Println(m.LogMode) + if db, err := gorm.Open(mysql.New(mysqlConfig), internal.Gorm.Config()); err != nil { + //global.GVA_LOG.Error("MySQL启动异常", zap.Any("err", err)) + //os.Exit(0) + //return nil + return nil + } else { + sqlDB, _ := db.DB() + sqlDB.SetMaxIdleConns(m.MaxIdleConns) + sqlDB.SetMaxOpenConns(m.MaxOpenConns) + return db + } +} diff --git a/initialize/grpc.go b/initialize/grpc.go new file mode 100644 index 0000000..6764cbc --- /dev/null +++ b/initialize/grpc.go @@ -0,0 +1,89 @@ +package initialize + +import ( + "context" + "fmt" + "pure/global" + "pure/initialize/api" + "time" + + "github.com/go-kratos/kratos/contrib/registry/nacos/v2" + "github.com/go-kratos/kratos/v2/middleware/recovery" + "github.com/go-kratos/kratos/v2/transport/grpc" + "github.com/nacos-group/nacos-sdk-go/clients" + "github.com/nacos-group/nacos-sdk-go/common/constant" + "github.com/nacos-group/nacos-sdk-go/vo" +) + +func PaymentClient() api.GreeterClient { + sc := []constant.ServerConfig{ + *constant.NewServerConfig("72535c70-8d6d-400f-9893-4bb3e634f682.nacos.cn-north-4.cse.myhuaweicloud.com", 8848), + } + cc := constant.ClientConfig{ + NamespaceId: "dev", + TimeoutMs: 5000, + Username: "nacos", + Password: "nacos", + } + client, err := clients.NewNamingClient( + vo.NacosClientParam{ + ServerConfigs: sc, + ClientConfig: &cc, + }, + ) + if err != nil { + fmt.Println(err) + panic(err) + } + + r := nacos.New(client) + conn, err := grpc.DialInsecure( + context.Background(), + grpc.WithEndpoint("discovery:///bkb.payment.grpc"), + grpc.WithDiscovery(r), + grpc.WithMiddleware( + recovery.Recovery())) + if err != nil { + panic(err) + } + return api.NewGreeterClient(conn) +} + +func InitNacosClient() { + sc := []constant.ServerConfig{ + *constant.NewServerConfig("72535c70-8d6d-400f-9893-4bb3e634f682.nacos.cn-north-4.cse.myhuaweicloud.com", 8848), + } + cc := constant.ClientConfig{ + NamespaceId: "dev", + TimeoutMs: 5000, + Username: "nacos", + Password: "nacos", + } + func() { + client, err := clients.NewNamingClient( + vo.NacosClientParam{ + ServerConfigs: sc, + ClientConfig: &cc, + }, + ) + if err != nil { + fmt.Println(err) + panic(err) + } + r := nacos.New(client) + ctx, cel := context.WithTimeout(context.Background(), time.Second*5) + defer cel() + conn, err := grpc.DialInsecure( + ctx, + grpc.WithEndpoint("discovery:///bkb.notify.grpc"), + grpc.WithDiscovery(r), + grpc.WithMiddleware( + recovery.Recovery())) + if err != nil { + panic(err) + } + global.EMAIL_CLIENT = api.NewEmailClient(conn) + global.SMS_CLIENT = api.NewSmsClient(conn) + }() + +} diff --git a/initialize/internal/gorm.go b/initialize/internal/gorm.go new file mode 100644 index 0000000..4941696 --- /dev/null +++ b/initialize/internal/gorm.go @@ -0,0 +1,52 @@ +package internal + +import ( + "log" + "os" + "pure/global" + "time" + + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +type DBBASE interface { + GetLogMode() string +} + +var Gorm = new(_gorm) + +type _gorm struct{} + +// Config gorm 自定义配置 +// Author [SliverHorn](https://github.com/SliverHorn) +func (g *_gorm) Config() *gorm.Config { + config := &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true} + _default := logger.New(NewWriter(log.New(os.Stdout, "\r\n", log.LstdFlags)), logger.Config{ + SlowThreshold: 200 * time.Millisecond, + LogLevel: logger.Warn, + Colorful: true, + }) + var logMode DBBASE + switch global.MG_CONFIG.System.DbType { + case "mysql": + logMode = &global.MG_CONFIG.Mysql + break + default: + logMode = &global.MG_CONFIG.Mysql + } + + switch logMode.GetLogMode() { + case "silent", "Silent": + config.Logger = _default.LogMode(logger.Silent) + case "error", "Error": + config.Logger = _default.LogMode(logger.Error) + case "warn", "Warn": + config.Logger = _default.LogMode(logger.Warn) + case "info", "Info": + config.Logger = _default.LogMode(logger.Info) + default: + config.Logger = _default.LogMode(logger.Info) + } + return config +} diff --git a/initialize/internal/logger.go b/initialize/internal/logger.go new file mode 100644 index 0000000..0fc8723 --- /dev/null +++ b/initialize/internal/logger.go @@ -0,0 +1,33 @@ +package internal + +import ( + "fmt" + "pure/global" + + "gorm.io/gorm/logger" +) + +type writer struct { + logger.Writer +} + +// NewWriter writer 构造函数 +// Author [SliverHorn](https://github.com/SliverHorn) +func NewWriter(w logger.Writer) *writer { + return &writer{Writer: w} +} + +// Printf 格式化打印日志 +// Author [SliverHorn](https://github.com/SliverHorn) +func (w *writer) Printf(message string, data ...interface{}) { + var logZap bool + switch global.MG_CONFIG.System.DbType { + case "mysql": + logZap = global.MG_CONFIG.Mysql.LogZap + } + if logZap { + global.MG_LOG.Info(fmt.Sprintf(message+"\n", data...)) + } else { + w.Writer.Printf(message, data...) + } +} diff --git a/initialize/international.go b/initialize/international.go new file mode 100644 index 0000000..5774797 --- /dev/null +++ b/initialize/international.go @@ -0,0 +1,24 @@ +package initialize + +import ( + "fmt" + "pure/global" + "pure/model" +) + +func InternationalizationInit() interface{} { + var ( + err error + data []model.Internationalization + language = make(map[string]model.Internationalization) + ) + err = global.MG_DB.Model(&model.Internationalization{}).Find(&data).Error + if err != nil { + fmt.Println("多语言模块加载失败") + return nil + } + for v := range data { + language[data[v].Ch] = data[v] + } + return language +} diff --git a/initialize/redis.go b/initialize/redis.go new file mode 100644 index 0000000..6aa44df --- /dev/null +++ b/initialize/redis.go @@ -0,0 +1,44 @@ +package initialize + +import ( + "github.com/go-redis/redis" + "go.uber.org/zap" + "pure/global" + "strconv" + "strings" +) + +func Redis() { + redisCfg := global.MG_CONFIG.Redis + client := redis.NewClient(&redis.Options{ + Addr: redisCfg.Addr, + Password: redisCfg.Password, // no password set + DB: redisCfg.DB, // use default DB + }) + pong, err := client.Ping().Result() + if err != nil { + global.MG_LOG.Error("redis connect ping failed, err:", zap.Any("err", err)) + } else { + global.MG_LOG.Info("redis connect ping response:", zap.String("pong", pong)) + global.MG_REDIS = client + } + //开启过期消息订阅 + go PubsunChannel(client) +} + +func PubsunChannel(client *redis.Client) { + pubsub := client.Subscribe("__keyevent@" + strconv.Itoa(global.MG_CONFIG.Redis.DB) + "__:expired") + //fmt.Println("__keyevent@" + strconv.Itoa(global.MG_CONFIG.Redis.DB) + "__:expired") + defer pubsub.Close() + for msg := range pubsub.Channel() { + key := strings.Split(msg.Payload, "-") + if len(key) > 1 { + switch key[0] { + case "test": + println(msg.Payload) + default: + //默认处理 + } + } + } +} diff --git a/initialize/router.go b/initialize/router.go new file mode 100644 index 0000000..16f146e --- /dev/null +++ b/initialize/router.go @@ -0,0 +1,53 @@ +package initialize + +import ( + "net/http" + + _ "pure/docs" + "pure/global" + "pure/middleware" + globalr "pure/router/global" + "pure/router/influencer" + + "github.com/gin-gonic/gin" + swaggerFiles "github.com/swaggo/files" + ginSwagger "github.com/swaggo/gin-swagger" + //"github.com/swaggo/gin-swagger/swaggerFiles" +) + +// 初始化总路由 + +func Routers() *gin.Engine { + Router := gin.Default() + Router.StaticFS(global.MG_CONFIG.Local.Path, http.Dir(global.MG_CONFIG.Local.Path)) // 为用户头像和文件提供静态地址 + // Router.Use(middleware.LoadTls()) // 打开就能玩https了 + // 跨域 + Router.Use(middleware.Cors()) // 如需跨域可以打开 + Router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) + + Router.Use(middleware.ParamsMiddleware()) + //网红端 + PrivateGroup2 := Router.Group("influencer") + PrivateGroup4 := Router.Group("") + { + influencer.InitInfluencerOtherRouter(PrivateGroup2) // 基础路由 + } + PrivateGroup2.Use(middleware.JWTAuth()) + //PrivateGroup4.Use(middleware.JWTAuth()) + { + influencer.InitInfluencerUserRouter(PrivateGroup2) // 用户 + influencer.InitInfluencerWalletRouter(PrivateGroup2) // 钱包 + influencer.InitInfluencerMissionRouter(PrivateGroup2) // 任务 + influencer.InitInfluencerGoodsRouter(PrivateGroup2) // 商品 + influencer.InitInfluencerOrderRouter(PrivateGroup2) // 订单 + globalr.InitGlobalRouter(PrivateGroup2) // 地址 + globalr.InitDictRouter(PrivateGroup4) // 字典 + influencer.InitBanner(PrivateGroup2) //banner + } + PrivateGroup3 := Router.Group("") + PrivateGroup3.Use(middleware.JWTAuth2()) + { + globalr.InitGlobalRouter(PrivateGroup3) // 用户 + } + return Router +} diff --git a/initialize/timer.go b/initialize/timer.go new file mode 100644 index 0000000..4b99ff2 --- /dev/null +++ b/initialize/timer.go @@ -0,0 +1,23 @@ +package initialize + +import ( + "fmt" + "pure/config" + "pure/global" + "pure/utils" +) + +func Timer() { + if global.MG_CONFIG.Timer.Start { + for _, detail := range global.MG_CONFIG.Timer.Detail { + go func(detail config.Detail) { + global.MG_Timer.AddTaskByFunc("ClearDB", global.MG_CONFIG.Timer.Spec, func() { + err := utils.ClearTable(global.MG_DB, detail.TableName, detail.CompareField, detail.Interval) + if err != nil { + fmt.Println("timer error:", err) + } + }) + }(detail) + } + } +} diff --git a/initialize/validator.go b/initialize/validator.go new file mode 100644 index 0000000..d9f80d9 --- /dev/null +++ b/initialize/validator.go @@ -0,0 +1,22 @@ +package initialize + +import "pure/utils" + +func init() { + _ = utils.RegisterRule("PageVerify", + utils.Rules{ + "Page": {utils.NotEmpty()}, + "PageSize": {utils.NotEmpty()}, + }, + ) + _ = utils.RegisterRule("IdVerify", + utils.Rules{ + "Id": {utils.NotEmpty()}, + }, + ) + _ = utils.RegisterRule("AuthorityIdVerify", + utils.Rules{ + "AuthorityId": {utils.NotEmpty()}, + }, + ) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..c7a25c5 --- /dev/null +++ b/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "pure/core" + "pure/global" + "pure/initialize" +) + +//go:generate go env -w GO111MODULE=on +//go:generate go env -w GOPROXY=https://goproxy.cn,direct +//go:generate go mod tidy +//go:generate go mod download + +// @title Swagger Example API +// @version 0.0.1 +// @description 接口文档 +// @securityDefinitions.apikey ApiKeyAuth +// @in header +// @name x-token +// @BasePath / +func main() { + global.MG_VP = core.Viper() // 初始化Viper + global.MG_LOG = core.Zap() // 初始化zap日志库 + global.MG_DB = initialize.Gorm() // gorm连接数据库 + // initialize.Minio() + initialize.InitNacosClient() //初始化微服务连接 + initialize.Timer() + global.MG_Language = initialize.InternationalizationInit() + if global.MG_DB != nil { + initialize.MysqlTables(global.MG_DB) //初始化表 + // 程序结束前关闭数据库链接 + db, _ := global.MG_DB.DB() + defer db.Close() + } + core.RunWindowsServer() +} diff --git a/middleware/Ijwt.go b/middleware/Ijwt.go new file mode 100644 index 0000000..70d4eb6 --- /dev/null +++ b/middleware/Ijwt.go @@ -0,0 +1,132 @@ +package middleware + +import ( + "strconv" + "time" + + "pure/global" + "pure/model" + "pure/model/request" + "pure/model/response" + "pure/service" + + "github.com/dgrijalva/jwt-go" + "github.com/gin-gonic/gin" + "go.uber.org/zap" +) + +func InfluencerJWTAuth() gin.HandlerFunc { + return func(c *gin.Context) { + // 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localStorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录 + + token := c.Request.Header.Get("x-token") + if token == "" { + response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c) + c.Abort() + return + } + if service.IsBlacklist(token) { + response.FailWithDetailed(gin.H{"reload": true}, "您的帐户异地登陆或令牌失效", c) + c.Abort() + return + } + j := NewInfluencerJWT() + // parseToken 解析token包含的信息 + claims, err := j.ParseInfluencerToken(token) + if err != nil { + if err == TokenExpired { + response.FailWithDetailed(gin.H{"reload": true}, "授权已过期", c) + c.Abort() + return + } + response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c) + c.Abort() + return + } + // if err, _ = service.FindUserByUuid(claims.UUID.String()); err != nil { + // _ = service.JsonInBlacklist(model.JwtBlacklist{Jwt: token}) + // response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c) + // c.Abort() + // } + if claims.ExpiresAt-time.Now().Unix() < claims.BufferTime { + claims.ExpiresAt = time.Now().Unix() + global.MG_CONFIG.JWT.ExpiresTime + newToken, _ := j.CreateInfluencerToken(*claims) + newClaims, _ := j.ParseInfluencerToken(newToken) + c.Header("new-token", newToken) + c.Header("new-expires-at", strconv.FormatInt(newClaims.ExpiresAt, 10)) + if global.MG_CONFIG.System.UseMultipoint { + err, RedisJwtToken := service.GetRedisJWT(newClaims.Username) + if err != nil { + global.MG_LOG.Error("get redis jwt failed", zap.Any("err", err)) + } else { // 当之前的取成功时才进行拉黑操作 + _ = service.JsonInBlacklist(model.JwtBlacklist{Jwt: RedisJwtToken}) + } + // 无论如何都要记录当前的活跃状态 + _ = service.SetRedisJWT(newToken, newClaims.Username) + } + } + c.Set("claims", claims) + c.Next() + } +} + +func NewInfluencerJWT() *JWT { + return &JWT{ + []byte(global.MG_CONFIG.JWT.SigningKey), + } +} + +// 创建一个token +func (j *JWT) CreateInfluencerToken(claims request.UserClaims) (string, error) { + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(j.SigningKey) +} + +// 解析 token +func (j *JWT) ParseInfluencerToken(tokenString string) (*request.UserClaims, error) { + token, err := jwt.ParseWithClaims(tokenString, &request.UserClaims{}, func(token *jwt.Token) (i interface{}, e error) { + return j.SigningKey, nil + }) + if err != nil { + if ve, ok := err.(*jwt.ValidationError); ok { + if ve.Errors&jwt.ValidationErrorMalformed != 0 { + return nil, TokenMalformed + } else if ve.Errors&jwt.ValidationErrorExpired != 0 { + // Token is expired + return nil, TokenExpired + } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 { + return nil, TokenNotValidYet + } else { + return nil, TokenInvalid + } + } + } + if token != nil { + if claims, ok := token.Claims.(*request.UserClaims); ok && token.Valid { + return claims, nil + } + return nil, TokenInvalid + + } else { + return nil, TokenInvalid + } +} + +// 更新token +//func (j *JWT) RefreshToken(tokenString string) (string, error) { +// jwt.TimeFunc = func() time.Time { +// return time.Unix(0, 0) +// } +// token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (interface{}, error) { +// return j.SigningKey, nil +// }) +// if err != nil { +// return "", err +// } +// if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid { +// jwt.TimeFunc = time.Now +// claims.StandardClaims.ExpiresAt = time.Now().Unix() + 60*60*24*7 +// return j.CreateToken(*claims) +// } +// return "", TokenInvalid +//} diff --git a/middleware/cors.go b/middleware/cors.go new file mode 100644 index 0000000..4f262bc --- /dev/null +++ b/middleware/cors.go @@ -0,0 +1,26 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "net/http" +) + +// 处理跨域请求,支持options访问 +func Cors() gin.HandlerFunc { + return func(c *gin.Context) { + method := c.Request.Method + origin := c.Request.Header.Get("Origin") + c.Header("Access-Control-Allow-Origin", origin) + c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id,X-Requested-With,X_Requested_With") + c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT") + c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type") + c.Header("Access-Control-Allow-Credentials", "true") + + // 放行所有OPTIONS方法 + if method == "OPTIONS" { + c.AbortWithStatus(http.StatusNoContent) + } + // 处理请求 + c.Next() + } +} diff --git a/middleware/error.go b/middleware/error.go new file mode 100644 index 0000000..31feb1f --- /dev/null +++ b/middleware/error.go @@ -0,0 +1,61 @@ +package middleware + +import ( + "net" + "net/http" + "net/http/httputil" + "os" + "pure/global" + "runtime/debug" + "strings" + + "github.com/gin-gonic/gin" + "go.uber.org/zap" +) + +// GinRecovery recover掉项目可能出现的panic,并使用zap记录相关日志 +func GinRecovery(stack bool) gin.HandlerFunc { + return func(c *gin.Context) { + defer func() { + if err := recover(); err != nil { + // Check for a broken connection, as it is not really a + // condition that warrants a panic stack trace. + var brokenPipe bool + if ne, ok := err.(*net.OpError); ok { + if se, ok := ne.Err.(*os.SyscallError); ok { + if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") { + brokenPipe = true + } + } + } + + httpRequest, _ := httputil.DumpRequest(c.Request, false) + if brokenPipe { + global.MG_LOG.Error(c.Request.URL.Path, + zap.Any("error", err), + zap.String("request", string(httpRequest)), + ) + // If the connection is dead, we can't write a status to it. + _ = c.Error(err.(error)) // nolint: errcheck + c.Abort() + return + } + + if stack { + global.MG_LOG.Error("[Recovery from panic]", + zap.Any("error", err), + zap.String("request", string(httpRequest)), + zap.String("stack", string(debug.Stack())), + ) + } else { + global.MG_LOG.Error("[Recovery from panic]", + zap.Any("error", err), + zap.String("request", string(httpRequest)), + ) + } + c.AbortWithStatus(http.StatusInternalServerError) + } + }() + c.Next() + } +} diff --git a/middleware/jwt.go b/middleware/jwt.go new file mode 100644 index 0000000..9319a69 --- /dev/null +++ b/middleware/jwt.go @@ -0,0 +1,203 @@ +package middleware + +import ( + "errors" + "pure/global" + "pure/model" + "pure/model/request" + "pure/model/response" + "pure/service" + "strconv" + "time" + + "github.com/dgrijalva/jwt-go" + "github.com/gin-gonic/gin" + "go.uber.org/zap" +) + +func JWTAuth() gin.HandlerFunc { + return func(c *gin.Context) { + // 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localStorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录 + token := c.Request.Header.Get("x-token") + if token == "" { + response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c) + c.Abort() + return + } + if service.IsBlacklist(token) { + response.FailWithDetailed(gin.H{"reload": true}, "您的帐户异地登陆或令牌失效", c) + c.Abort() + return + } + j := NewJWT() + // parseToken 解析token包含的信息 + claims, err := j.ParseToken(token) + if err != nil { + if err == TokenExpired { + response.FailWithDetailed(gin.H{"reload": true}, "授权已过期", c) + c.Abort() + return + } + response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c) + c.Abort() + return + } + // if err, _ = service.FindUserByUuid(claims.UUID.String()); err != nil { + // _ = service.JsonInBlacklist(model.JwtBlacklist{Jwt: token}) + // response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c) + // c.Abort() + // } + if claims.ExpiresAt-time.Now().Unix() < claims.BufferTime { + claims.ExpiresAt = time.Now().Unix() + global.MG_CONFIG.JWT.ExpiresTime + newToken, _ := j.CreateToken(*claims) + newClaims, _ := j.ParseToken(newToken) + c.Header("new-token", newToken) + c.Header("new-expires-at", strconv.FormatInt(newClaims.ExpiresAt, 10)) + if global.MG_CONFIG.System.UseMultipoint { + err, RedisJwtToken := service.GetRedisJWT(newClaims.Username) + if err != nil { + global.MG_LOG.Error("get redis jwt failed", zap.Any("err", err)) + } else { // 当之前的取成功时才进行拉黑操作 + _ = service.JsonInBlacklist(model.JwtBlacklist{Jwt: RedisJwtToken}) + } + // 无论如何都要记录当前的活跃状态 + _ = service.SetRedisJWT(newToken, newClaims.Username) + } + } + c.Set("claims", claims) + c.Next() + } +} + +func JWTAuth2() gin.HandlerFunc { + return func(c *gin.Context) { + // 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localStorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录 + token := c.Request.Header.Get("x-token") + if token == "" { + response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c) + c.Abort() + return + } + if service.IsBlacklist(token) { + response.FailWithDetailed(gin.H{"reload": true}, "您的帐户异地登陆或令牌失效", c) + c.Abort() + return + } + + j := NewJWT() + // parseToken 解析token包含的信息 + claims, err := j.ParseToken(token) + if err != nil { + j = NewInfluencerJWT() + claims, err = j.ParseInfluencerToken(token) + if err != nil { + if err == TokenExpired { + response.FailWithDetailed(gin.H{"reload": true}, "授权已过期", c) + c.Abort() + return + } + response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c) + c.Abort() + return + } + } + // if err, _ = service.FindUserByUuid(claims.UUID.String()); err != nil { + // _ = service.JsonInBlacklist(model.JwtBlacklist{Jwt: token}) + // response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c) + // c.Abort() + // } + if claims.ExpiresAt-time.Now().Unix() < claims.BufferTime { + claims.ExpiresAt = time.Now().Unix() + global.MG_CONFIG.JWT.ExpiresTime + newToken, _ := j.CreateToken(*claims) + newClaims, _ := j.ParseToken(newToken) + c.Header("new-token", newToken) + c.Header("new-expires-at", strconv.FormatInt(newClaims.ExpiresAt, 10)) + if global.MG_CONFIG.System.UseMultipoint { + err, RedisJwtToken := service.GetRedisJWT(newClaims.Username) + if err != nil { + global.MG_LOG.Error("get redis jwt failed", zap.Any("err", err)) + } else { // 当之前的取成功时才进行拉黑操作 + _ = service.JsonInBlacklist(model.JwtBlacklist{Jwt: RedisJwtToken}) + } + // 无论如何都要记录当前的活跃状态 + _ = service.SetRedisJWT(newToken, newClaims.Username) + } + } + c.Set("claims", claims) + c.Next() + } +} + +type JWT struct { + SigningKey []byte +} + +var ( + TokenExpired = errors.New("Token is expired") + TokenNotValidYet = errors.New("Token not active yet") + TokenMalformed = errors.New("That's not even a token") + TokenInvalid = errors.New("Couldn't handle this token:") +) + +func NewJWT() *JWT { + return &JWT{ + []byte(global.MG_CONFIG.JWT.SigningKey), + } +} + +// 创建一个token +func (j *JWT) CreateToken(claims request.UserClaims) (string, error) { + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(j.SigningKey) +} + +// 解析 token +func (j *JWT) ParseToken(tokenString string) (*request.UserClaims, error) { + token, err := jwt.ParseWithClaims(tokenString, &request.UserClaims{}, func(token *jwt.Token) (i interface{}, e error) { + return j.SigningKey, nil + }) + if err != nil { + if ve, ok := err.(*jwt.ValidationError); ok { + if ve.Errors&jwt.ValidationErrorMalformed != 0 { + return nil, TokenMalformed + } else if ve.Errors&jwt.ValidationErrorExpired != 0 { + // Token is expired + return nil, TokenExpired + } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 { + return nil, TokenNotValidYet + } else { + return nil, TokenInvalid + } + } + } + if token != nil { + if claims, ok := token.Claims.(*request.UserClaims); ok && token.Valid { + return claims, nil + } + return nil, TokenInvalid + + } else { + return nil, TokenInvalid + + } + +} + +// 更新token +//func (j *JWT) RefreshToken(tokenString string) (string, error) { +// jwt.TimeFunc = func() time.Time { +// return time.Unix(0, 0) +// } +// token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (interface{}, error) { +// return j.SigningKey, nil +// }) +// if err != nil { +// return "", err +// } +// if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid { +// jwt.TimeFunc = time.Now +// claims.StandardClaims.ExpiresAt = time.Now().Unix() + 60*60*24*7 +// return j.CreateToken(*claims) +// } +// return "", TokenInvalid +//} diff --git a/middleware/loadtls.go b/middleware/loadtls.go new file mode 100644 index 0000000..69efe95 --- /dev/null +++ b/middleware/loadtls.go @@ -0,0 +1,26 @@ +package middleware + +import ( + "fmt" + "github.com/gin-gonic/gin" + "github.com/unrolled/secure" +) + +// 用https把这个中间件在router里面use一下就好 + +func LoadTls() gin.HandlerFunc { + return func(c *gin.Context) { + middleware := secure.New(secure.Options{ + SSLRedirect: true, + SSLHost: "localhost:443", + }) + err := middleware.Process(c.Writer, c.Request) + if err != nil { + // 如果出现错误,请不要继续 + fmt.Println(err) + return + } + // 继续往下处理 + c.Next() + } +} diff --git a/middleware/need_init.go b/middleware/need_init.go new file mode 100644 index 0000000..74da6e5 --- /dev/null +++ b/middleware/need_init.go @@ -0,0 +1,23 @@ +package middleware + +import ( + "pure/global" + "pure/model/response" + + "github.com/gin-gonic/gin" +) + +// 处理跨域请求,支持options访问 +func NeedInit() gin.HandlerFunc { + return func(c *gin.Context) { + if global.MG_DB == nil { + response.OkWithDetailed(gin.H{ + "needInit": true, + }, "前往初始化数据库", c) + c.Abort() + } else { + c.Next() + } + // 处理请求 + } +} diff --git a/middleware/params.go b/middleware/params.go new file mode 100644 index 0000000..4402c0c --- /dev/null +++ b/middleware/params.go @@ -0,0 +1,50 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "pure/model" + "pure/model/response" + "pure/service" + "strings" +) + +func ParamsMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + var err error + defer func() { + if err != nil { + c.Abort() + } else { + c.Next() + } + }() + type params struct { + Version string `json:"version"` + } + var p params + if err = c.ShouldBindHeader(&p); err != nil { + response.FailWithMessage("缺少必要参数", c) + return + } + var platform string + tmp := strings.ToUpper(c.Request.UserAgent()) + if strings.Contains(tmp, "IPHONE") || strings.Contains(tmp, "IOS") { // + platform = "2" + } else { + platform = "1" + } + c.Set("platform", platform) + if p.Version != "" { + //校验版本号可用性 + var version model.VersionV + version, err = service.GetVersion(platform, p.Version) + if err != nil { + response.FailWithMessage("版本号不可取", c) + return + } else { + c.Set("version", version.Version) + c.Set("version_status", version.Status) + } + } + } +} diff --git a/model/account.go b/model/account.go new file mode 100644 index 0000000..522b661 --- /dev/null +++ b/model/account.go @@ -0,0 +1,29 @@ +package model + +import "pure/global" + +type BankCard struct { + AccountName string `gorm:"size:50" json:"account_name"` // 户名 + BankCode string `gorm:"size:50" json:"bank_code"` // 收款行 + SwiftCode string `gorm:"size:20" json:"swift_code"` // 银行国际代码 + CardNumber string `gorm:"size:50" json:"card_number"` // 银行卡号 + Address string `gorm:"size:255" json:"address"` // 收款人地址 + Country string `gorm:"size:255" json:"country"` // 国家/地区 + Currency string `gorm:"size:10" json:"currency"` // 币种 USD:美元 +} + +type Account struct { + global.MG_MODEL + Platform string `gorm:"size:50" json:"platform"` //平台 saller(买家端) / customer(客户端) / influencer(网红端) + UserID string `gorm:"size:50;index" json:"userID"` //用户id + Type int `gorm:"type:int(1)" json:"type"` // 类型 1:paypal 2:银行卡 + BankCard // + IDCard string `gorm:"size:30" json:"idCard"` // + Phone string `gorm:"size:20" json:"phone"` // + Sort int `gorm:"type:int" json:"sort"` // 排序值 + IsDefault bool `gorm:"type:tinyint" json:"is_default"` // 是否为默认 0:非默认 1:默认 +} + +func (Account) TableName() string { + return "account" +} diff --git a/model/address.go b/model/address.go new file mode 100644 index 0000000..8db6a5e --- /dev/null +++ b/model/address.go @@ -0,0 +1,22 @@ +package model + +import "pure/global" + +type Address struct { + global.MG_MODEL + UserID string `gorm:"size:255" json:"userId"` + FirstName string `gorm:"size:255" json:"firstName"` //first name + LastName string `gorm:"size:255" json:"lastName"` //last name + Street string `gorm:"size:255" json:"street"` //street + Phone string `gorm:"size:20" json:"phone"` //手机号 + Bldg string `gorm:"size:255" json:"bldg"` //apt,ste,bldg + City string `gorm:"size:255" json:"city"` //city + State string `gorm:"size:255" json:"state"` //state + ZipCode string `gorm:"size:255" json:"zipCode"` //zip code + Default int `gorm:"tinyint(1)" json:"default"` //是否默认地址 1-是 2-否 + Platform string `gorm:"size:50" json:"platform"` //平台 saller(买家端) / customer(客户端) / influencer(网红端) +} + +func (Address) TableName() string { + return "address" +} diff --git a/model/application.go b/model/application.go new file mode 100755 index 0000000..b110946 --- /dev/null +++ b/model/application.go @@ -0,0 +1,21 @@ +// 自动生成模板Application +package model + +import "pure/global" + +// 如果含有time.Time 请自行import time包 +type Application struct { + global.MG_MODEL + Owner string `gorm:"size:50;comment:用户所属" json:"owner" ` // 用户所属 + Name string `gorm:"size:50;comment:应用名称" json:"name" ` // 应用名称 + Appid string `gorm:"size:50;comment:应用ID" json:"appid" ` // 应用ID + Logo string `gorm:"size:255;comment:应用logo" json:"logo" ` // 应用logo + Organization string `gorm:"size:50;comment:组织" json:"organization" ` // 组织 + Provider string `gorm:"type:text;comment:提供者" json:"provider" ` // 提供者 + ClientID string `gorm:"size:50;comment:客户端ID" json:"clientID" ` // 客户端ID + ClientSecret string `gorm:"size:50;comment:客户端密钥" json:"clientSecret" ` // 客户端密钥 +} + +func (Application) TableName() string { + return "application" +} diff --git a/model/banner.go b/model/banner.go new file mode 100644 index 0000000..1573f27 --- /dev/null +++ b/model/banner.go @@ -0,0 +1,22 @@ +package model + +import "pure/global" + +type Banner struct { + RelationId string `gorm:"size:50" json:"relationId"` //关联项目id + RelationType string `gorm:"size:4" json:"relationType"` //关联类型 01-任务 + Title string `gorm:"size:80" json:"title"` //标题 + CoverUrl string `gorm:"size:500" json:"coverUrl"` //封面图 + LinkType string `gorm:"size:2" json:"linkType" form:"linkType"` //链接类型 0:内链 1:外链 + Link string `gorm:"size:500" json:"link"` //链接地址 + Type string `gorm:"size:4" json:"type"` //任务-0101 平台奖励页-0102 + Sort int `gorm:"" json:"sort"` //排序 + Status string `gorm:"size:4" json:"status"` //状态 0=下架 1=上架 + CreateBy string `gorm:"size:64" json:"createBy"` //创建人 + UpdateBy string `gorm:"size:64" json:"updateBy"` //更新人 + global.MG_MODEL +} + +func (Banner) TableName() string { + return "banner" +} diff --git a/model/base.go b/model/base.go new file mode 100644 index 0000000..ceaff03 --- /dev/null +++ b/model/base.go @@ -0,0 +1,9 @@ +package model + +type Breadcrumb struct { //面包屑 + ID uint `json:"id"` + Name string `json:"name"` + Pid uint `json:"pid"` //父id + IsLeaf bool `json:"is_leaf"` //是否叶子分类 + Parent *Breadcrumb `gorm:"-" json:"-"` //上级/下级 +} diff --git a/model/bill.go b/model/bill.go new file mode 100644 index 0000000..58333d4 --- /dev/null +++ b/model/bill.go @@ -0,0 +1,51 @@ +package model + +import ( + "pure/global" +) + +type Bill struct { + global.MG_MODEL + UserID string `gorm:"size:50;index" json:"userID"` //用户id + Type string `gorm:"size:1;default:1" json:"type"` //类型 1-佣金 2-订单 3-提现 4-平台奖励 + Title string `gorm:"size:255" json:"title"` // 账单标题 + ClaimNo string `json:"claim_no"` //领取任务编号 + Account string `gorm:"size:50" json:"account"` //收款账户(提现) + OrderID string `gorm:"size:50" json:"order_id"` //关联订单id + WithdID string `gorm:"size:50" json:"withd_id"` //提现id + Price float64 `gorm:"type:decimal(10,2)" json:"price"` //金额 + Balance float64 `gorm:"type:decimal(10,2)" json:"balance"` //余额 + Amount int `gorm:"type:int(2);default:1" json:"amount"` //数量 + Status int `gorm:"type:int(1);default:0" json:"status"` //类型 1-支出 2-收入 + Receipt int `gorm:"type:tinyint(1)" json:"receipt"` //是否已到账 1-是 2-否 3-已取消付款 + WithdrawalStatus int `gorm:"type:tinyint(1)" json:"withdrawalStatus"` //提现状态 0-提现中 1-提现完成 2-提现失败 + CheckStatus string `gorm:"size:1" json:"check_status"` // 审核状态 0:待审核 1:审核通过 2:审核未通过 + Remark string `gorm:"size:50" json:"remark"` //备注 + Platform string `gorm:"size:50" json:"platform"` //平台 seller(买家端) / customer(客户端) / influencer(网红端) + TransactionId string `gorm:"size:50" json:"transaction_id"` // 交易编号 +} + +type BillView struct { + ID uint `json:"id"` // id + OrderID string `json:"order_id"` // 订单编号 + TransactionId string `json:"transaction_id"` // 交易编号 +} + +type BillNotify struct { + Title string `json:"title"` // 标题 + RelationType string `json:"relation_type"` // 关联类型 + RelationId string `json:"relation_id"` // 关联id +} + +type BillFlowData struct { + Status int `json:"status"` + Price float64 `json:"price"` +} + +func (Bill) TableName() string { + return "bill" +} + +func (BillView) TableName() string { + return "bill" +} diff --git a/model/bill_fund.go b/model/bill_fund.go new file mode 100644 index 0000000..012718a --- /dev/null +++ b/model/bill_fund.go @@ -0,0 +1,22 @@ +package model + +import "pure/global" + +type BillFund struct { // 账户 + global.MG_MODEL + UserID string `gorm:"size:50;index" json:"userID"` // 用户id + TransactionType int `gorm:"type:int(1);default:1" json:"transaction_type"` // 类型 1-支出 2-收入 + TransactionId string `gorm:"size:50;unique" json:"transaction_id"` // 交易编号 + Title string `gorm:"size:255" json:"title"` // 账单标题 + Price float64 `gorm:"type:decimal(10,2)" json:"price"` // 价格 + Balance float64 `gorm:"type:decimal(10,2)" json:"balance"` // 余额 + Platform string `gorm:"size:20" json:"platform"` // 平台 seller + Remark string `gorm:"size:50" json:"remark"` // 备注 + RelatedId string `gorm:"size:50" json:"related_id"` // 关联id 任务id + PayId string `gorm:"size:50" json:"pay_id"` // 支付id + Status int `gorm:"size:1" json:"status"` // 状态 1:进行中 2:已完成 3:已失败 +} + +func (BillFund) TableName() string { + return "bill_fund" +} diff --git a/model/collectiom_goods.go b/model/collectiom_goods.go new file mode 100644 index 0000000..635efe2 --- /dev/null +++ b/model/collectiom_goods.go @@ -0,0 +1,13 @@ +package model + +import "pure/global" + +type CollectionGoods struct { //买家端收藏商品 + SpuNo string `gorm:"size:60" json:"spu_no"` //spu_no + CreateBy string `gorm:"size:64" json:"create_by"` //创建人 + global.MG_MODEL +} + +func (CollectionGoods) TableName() string { + return "collection_goods" +} diff --git a/model/collection_mission.go b/model/collection_mission.go new file mode 100644 index 0000000..7129ca6 --- /dev/null +++ b/model/collection_mission.go @@ -0,0 +1,13 @@ +package model + +import "pure/global" + +type CollectionMission struct { //网红端收藏任务 + MissionId uint `gorm:"type:int(11)" json:"mission_id"` //任务id + CreateBy string `gorm:"size:64" json:"create_by"` //创建人 + global.MG_MODEL +} + +func (CollectionMission) TableName() string { + return "collection_mission" +} diff --git a/model/dict.go b/model/dict.go new file mode 100644 index 0000000..4211a33 --- /dev/null +++ b/model/dict.go @@ -0,0 +1,49 @@ +package model + +import "pure/global" + +const ( + ReleaseCountryCode = "release_country" + ReleaseChannelCode = "release_channel" +) + +type SysDictType struct { //数据字典分类 + global.BASE_ID + PID int `gorm:"" json:"pid"` //父ID + Code string `gorm:"UNIQUE;size:20" json:"code"` //编码 + Name string `gorm:"size:20" json:"name"` //名称 + Type string `gorm:"size:10" json:"type"` //类型 + Status string `gorm:"size:1" json:"status"` //可用状态 1正常 0删除 + Desc string `gorm:"size:30" json:"desc"` //描述 + IsFixed int `gorm:"type:tinyint(1)" json:"isFixed"` //0默认为不固定 1固定 + //DynamicField string `gorm:"type:varchar(255)" json:"dynamic_field"` //动态字段编码 + + global.TIME_MODEL +} + +type SysDictData struct { //数据字典取值 + global.BASE_ID + TypeCode string `gorm:"size:20" json:"typeCode"` //编码 + Sort int `gorm:"" json:"sort"` //排序 + Label string `gorm:"size:30" json:"label"` //标签 + Value string `gorm:"size:10" json:"value"` //值 + IsDefault int `gorm:"type:tinyint(1)" json:"isDefault"` //是否为默认值 1是 0否 + Desc string `gorm:"size:50" json:"desc"` //描述 + Status string `gorm:"size:1" json:"status"` //可用状态 1正常 0删除 + + global.TIME_MODEL +} + +type SysDictDataView struct { + Label string `json:"label"` //标签 + Value string `json:"value"` //值 + IsDefault int `json:"isDefault"` //是否为默认值 1是 0否 +} + +func (SysDictType) TableName() string { + return "sys_dict_type" +} + +func (SysDictData) TableName() string { + return "sys_dict_data" +} diff --git a/model/dt_statistic_order.go b/model/dt_statistic_order.go new file mode 100644 index 0000000..104d468 --- /dev/null +++ b/model/dt_statistic_order.go @@ -0,0 +1,26 @@ +package model + +import "pure/global" + +type DtStatisticOrder struct { // 数据统计-订单 + global.MG_MODEL + Value string `gorm:"size:20" json:"value"` // 统计对象 eg:20231020(按天统计) + Unit string `gorm:"size:10" json:"unit"` // 单位 hour/day/month/all + Type int `gorm:"type:tinyint(1)" json:"type"` // 关联类型 0:无 1:用户 2:任务领取id 3:店铺id 4:spu_no + RelationId string `gorm:"size:60" json:"relation_id"` // 关联id 用户id/任务领取id/店铺id + NewOrderNum int64 `gorm:"type:int" json:"new_order_num"` // 创建订单数 + NewOrderMoney float64 `gorm:"type:decimal(10,2)" json:"new_order_money"` // 创建订单金额 + OrderNum int64 `gorm:"type:int" json:"order_num"` // 订单数 + OrderMoney float64 `gorm:"type:decimal(10,2)" json:"order_money"` // 订单金额 + OrderDoneNum int64 `gorm:"type:int" json:"order_done_num"` // 订单完成数 + SaleVolume int64 `gorm:"type:int" json:"sale_volume"` // 销售量 + SettleReward float64 `gorm:"type:decimal(10,2)" json:"settle_reward"` // 结算佣金 + TransitReward float64 `gorm:"type:decimal(10,2)" json:"transit_reward"` // 在途佣金 + OrderCancelNum int64 `gorm:"type:int" json:"order_cancel_num"` // 订单取消数 + OrderCancelMoney float64 `gorm:"type:decimal(10,2)" json:"order_cancel_money"` // 订单取消金额 + //Income float64 `gorm:"type:decimal(10,2)" json:"income"` // 收入 +} + +func (DtStatisticOrder) TableName() string { + return "dt_statistic_order" +} diff --git a/model/goods_visit.go b/model/goods_visit.go new file mode 100644 index 0000000..72cf97f --- /dev/null +++ b/model/goods_visit.go @@ -0,0 +1,14 @@ +package model + +import "pure/global" + +type GoodsVisit struct { + global.MG_MODEL + UserID string `gorm:"size:50;index" json:"user_id"` // 用户id + GoodsID uint `gorm:"size:50" json:"goods_id"` + ClaimNo string `json:"claim_no"` // 领取任务id +} + +func (GoodsVisit) TableName() string { + return "goods_visit" +} diff --git a/model/internationalization.go b/model/internationalization.go new file mode 100644 index 0000000..bd943b3 --- /dev/null +++ b/model/internationalization.go @@ -0,0 +1,13 @@ +package model + +import "pure/global" + +type Internationalization struct { + global.MG_MODEL + Ch string `gorm:"size:200" json:"ch"` + En string `gorm:"size:200" json:"en"` +} + +func (Internationalization) TableName() string { + return "internationalization" +} diff --git a/model/mission.go b/model/mission.go new file mode 100644 index 0000000..b8d77a8 --- /dev/null +++ b/model/mission.go @@ -0,0 +1,98 @@ +package model + +import ( + "time" + + "pure/global" +) + +type Mission struct { // 任务 + Title string `gorm:"type:mediumtext" json:"title"` // 标题 + GoodsId uint `gorm:"type:int(11)" json:"goods_id"` // 关联商品 + GoodsStatus int `gorm:"type:tinyint(1);" json:"goods_status"` // 关联商品状态 1:正常 2:已下架 + Num int64 `gorm:"type:int(11)" json:"num"` // 商品数量 + HireType int `gorm:"type:tinyint(1)" json:"hire_type"` // 佣金类型 1:固定佣金 2:比例抽成 + HireMoney float64 `gorm:"type:decimal(10,2);" json:"hire_money"` // hire_type==1 佣金金额 + HireRatio float64 `gorm:"type:decimal(10,2);" json:"hire_ratio"` // hire_type==2 抽成比例 + StartTime *time.Time `gorm:"column:start_time" json:"start_time"` // 任务起始时间 + EndTime *time.Time `gorm:"column:end_time" json:"end_time"` // 任务结束时间 + ClaimNum int64 `gorm:"type:int(11)" json:"claim_num"` // 接任务人数 + CollectionNum int64 `gorm:"type:int(11)" json:"collection_num"` // 收藏人数 + CreateBy string `gorm:"size:64" json:"create_by"` // 创建人 + Status int `gorm:"type:tinyint(1);" json:"status"` // 状态 1:未开始 2:进行中 3:已结束 + ClaimStock int64 `json:"claim_stock"` // 可接任务库存 + Sample + VideoMaterial + ClaimDays int `gorm:"type:tinyint(11)" json:"claim_days"` // 任务完成天数 + ClaimDemands string `gorm:"type:varchar(500);" json:"claim_demands"` // 任务拍摄要求 + Description string `gorm:"type:varchar(2000);" json:"description"` // 描述/卖点 + + global.MG_MODEL +} + +type MissionDetail struct { + Title string `json:"title"` // 标题 + GoodsId uint `json:"-"` + GoodsStatus int `json:"goods_status"` // 关联商品状态 1:正常 2:已下架 + Goods TbGoodsSpecsView `gorm:"ForeignKey:GoodsId;AssociationForeignKey:ID" json:"goods"` // 商品信息 + Num int64 `json:"num"` // 商品数量 + HireType int `json:"hire_type"` // 佣金类型 1:固定佣金 2:比例抽成 + HireMoney float64 `json:"hire_money"` // hire_type==1 佣金金额 + HireRatio float64 `json:"hire_ratio"` // hire_type==2 抽成比例 + HireMoneyExpect string `json:"hire_money_expect"` // 预计佣金描述 + StartTime *time.Time `json:"start_time"` // 任务起始时间 + EndTime *time.Time `json:"end_time"` // 任务结束时间 + ClaimNum int64 `gorm:"type:int(11)" json:"claim_num"` // 接任务人数 + CreateBy string `json:"-"` // + CollectStatus bool `gorm:"-" json:"collect_status"` // 收藏状态 true:已收藏 false:未收藏 + Store SellerStoreInfo `gorm:"-" json:"store"` // 商家信息 + Status int `json:"status"` // 状态 1:未开始 2:进行中 3:已结束 + + // OrderNum int64 `gorm:"-" json:"order_num"` //订单数 + Sample + + VideoMaterial + ClaimStock int64 `json:"claim_stock"` // 可接任务库存 + ClaimDays int `gorm:"type:tinyint(11)" json:"claim_days"` // 任务完成天数 + ClaimDemands string `gorm:"type:varchar(500);" json:"claim_demands"` // 任务拍摄要求 + Description string `gorm:"type:varchar(2000);" json:"description"` // 描述/卖点 + ReleaseChannels string `gorm:"-" json:"release_channels"` // 发布渠道 + ReleaseCountry string `gorm:"-" json:"release_country"` // 发布国家 + ClaimStatusExcept string `json:"claim_status_except"` // 可接任务状态描述 + ClaimStatusExceptEng string `json:"claim_status_except_eng"` // 英文版状态描述 + GoodsUrl string `json:"goods_url"` // 商品链接 + global.MG_MODEL +} + +type Sample struct { + HasSample int `gorm:"type:tinyint(1);default:0" json:"has_sample"` // 是否有样品 0:没有 1:有 + SampleNum int `gorm:"type:tinyint(11);" json:"sample_num"` // 样品数量 +} + +type VideoMaterial struct { + HasVideo int `gorm:"type:tinyint(1);default:0" json:"has_video"` // 是否有视频素材 0:没有 1:有 + VideoUrl string `json:"video_url"` + VideoChannelIds string `json:"video_channel_ids"` // 视频发布渠道,多个渠道英文逗号连接 + VideoCountryId string `json:"video_country_id"` // 视频发布国家 +} + +type MissionClaimInfo struct { + MissionId uint `json:"mission_id"` // 任务id + ClaimNo string `json:"claim_no"` // 领取任务编号 + HireType int `gorm:"type:tinyint(1)" json:"hire_type"` // 佣金类型 1:固定佣金 2:比例抽成 + HireMoney float64 `gorm:"type:decimal(10,2);" json:"hire_money"` // hire_type==1 佣金金额 + HireRatio float64 `gorm:"type:decimal(10,2);" json:"hire_ratio"` // hire_type==2 抽成比例 +} + +type MissionBonus struct { + Total float64 `json:"total"` + UserTotal float64 `json:"user_total"` +} + +func (Mission) TableName() string { + return "mission" +} + +func (MissionDetail) TableName() string { + return "mission" +} diff --git a/model/mission_claim.go b/model/mission_claim.go new file mode 100644 index 0000000..5ce741c --- /dev/null +++ b/model/mission_claim.go @@ -0,0 +1,49 @@ +package model + +import ( + "pure/global" + "time" +) + +type MissionClaim struct { //领取任务记录 + MissionId uint `gorm:"type:int(11)" json:"mission_id"` //任务id + ClaimNo string `gorm:"unique;type:varchar(60);" json:"claim_no"` //领取任务编号 + AchieveNum int64 `gorm:"type:int(11)" json:"achieve_num"` //已完成商品数量 + CreateBy string `gorm:"size:64" json:"create_by"` //创建人 + Status int `gorm:"type:tinyint(1);" json:"status"` //状态 1:已领取待发货 2:已发货 3:已收货推广中 + ExpireAt time.Time `json:"expire_at"` //任务推广过期时间 + Finished int `gorm:"type:tinyint(1);" json:"finished"` // 任务完成状态 0:未完成 1:已完成 + OrderNum int64 `gorm:"type:int" json:"orderNum"` // 订单数 + OrderMoney float64 `gorm:"type:decimal(10,2)" json:"orderMoney"` // 订单金额 + RewardFinished float64 `gorm:"type:decimal(10,2)" json:"rewardFinished"` // 佣金结算 + RewardUnfinished float64 `gorm:"type:decimal(10,2)" json:"rewardUnfinished"` // 在途佣金 + Email string `gorm:"size:255" json:"email"` //发送邮箱 + SendFinished int `gorm:"type:tinyint(1);" json:"send_finished"` //状态 1:已发送 2:发送失败 + global.MG_MODEL +} + +type MissionClaimDetail struct { + global.MG_MODEL + ClaimNo string `json:"claim_no"` //领取任务编号 + MissionId uint `json:"mission_id"` //任务id + AchieveNum int64 `json:"achieve_num"` //已完成商品数量 + Status int `json:"status"` //状态 1:已领取待发货 2:已发货 3:已收货推广中 + SpreadUrl string `json:"spread_url"` //推广链接 + TotalBonus int64 `json:"total_bonus"` //累计佣金 + StatusExcept string `json:"status_except" gorm:"-"` //状态描述 + ExpireAt time.Time `json:"expire_at"` //任务推广过期时间 + Email string `json:"email"` //发送邮箱 + Finished int `json:"finished"` // 任务完成状态 0:未完成 1:已完成 + Order MissionClaimOrderInfo `gorm:"ForeignKey:MissionClaimId;AssociationForeignKey:ID" json:"order"` //任务订单 + Mission MissionDetail `gorm:"ForeignKey:MissionId;AssociationForeignKey:ID" json:"mission"` //关联任务 + Works []MissionClaimWorks `gorm:"ForeignKey:MissionClaimId;AssociationForeignKey:ID" json:"works"` //发布作品 + Video MissionClaimVideo `gorm:"ForeignKey:MissionClaimId;AssociationForeignKey:ID" json:"video"` //上传视频 +} + +func (MissionClaim) TableName() string { + return "mission_claim" +} + +func (MissionClaimDetail) TableName() string { + return "mission_claim" +} diff --git a/model/mission_claim_address.go b/model/mission_claim_address.go new file mode 100644 index 0000000..a406497 --- /dev/null +++ b/model/mission_claim_address.go @@ -0,0 +1,12 @@ +package model + +type MissionClaimAddress struct { //领取任务地址 + Address + AddressId uint `gorm:"type:int(11)" json:"address_id"` //地址id + MissionClaimId uint `gorm:"type:int(11)" json:"mission_claim_id"` //领取任务id + OrderID string `gorm:"size:50;index" json:"order_id"` //订单号 +} + +func (MissionClaimAddress) TableName() string { + return "mission_claim_address" +} diff --git a/model/mission_claim_order.go b/model/mission_claim_order.go new file mode 100644 index 0000000..700a229 --- /dev/null +++ b/model/mission_claim_order.go @@ -0,0 +1,43 @@ +package model + +import ( + "pure/global" + "time" +) + +type MissionClaimOrder struct { //任务领取sku订单 + global.MG_MODEL + OrderID string `gorm:"size:50;index" json:"order_id"` //订单号 + MissionClaimId uint `gorm:"type:int(11)" json:"mission_claim_id"` //领取任务id + SpuNo string `gorm:"type:varchar(60);" json:"spu_no"` //spu编号 + SkuNo string `gorm:"type:varchar(60);" json:"sku_no"` //sku编号 + Number int `gorm:"type:int(10)" json:"number"` //数量 + CreateBy string `gorm:"size:64" json:"create_by"` //创建人 + Status int `gorm:"type:int(1)" json:"status"` //订单状态 2:待发货 3:已发货 + SendTime *time.Time `gorm:"send_time" json:"sendTime"` //发货时间 + Courier string `gorm:"size:50" json:"courier"` //快递公司 + CourierUrl string `gorm:"size:255" json:"courier_url"` //快递查询地址 + CourierNumber string `gorm:"size:50" json:"courierNumber"` //快递单号 + TrackId uint `json:"track_id"` // track表id + ConfirmTime *time.Time `gorm:"" json:"confirmTime"` //收货时间 +} + +type MissionClaimOrderInfo struct { + OrderID string `json:"order_id"` //订单号 + MissionClaimId uint `json:"mission_claim_id"` //领取任务id + Status int `json:"status"` //订单状态 2:待发货 3:已发货 + Courier string `json:"courier"` //快递公司 + CourierUrl string `json:"courier_url"` //快递查询地址 + CourierNumber string `json:"courier_number"` //快递单号 + SendTime *time.Time `gorm:"send_time" json:"send_time"` //发货时间 + OrderGoods MissionClaimOrderGoods `gorm:"ForeignKey:OrderID;references:OrderID;" json:"order_goods"` //订单商品信息 + Deliver OrderDeliver `gorm:"-" json:"deliver"` //发货信息 +} + +func (MissionClaimOrder) TableName() string { + return "mission_claim_order" +} + +func (MissionClaimOrderInfo) TableName() string { + return "mission_claim_order" +} diff --git a/model/mission_claim_order_goods.go b/model/mission_claim_order_goods.go new file mode 100644 index 0000000..19273d6 --- /dev/null +++ b/model/mission_claim_order_goods.go @@ -0,0 +1,17 @@ +package model + +import "pure/global" + +type MissionClaimOrderGoods struct { //任务订单关联商品 + global.MG_MODEL + OrderID string `gorm:"size:50;index" json:"order_id"` //订单号 + SkuNo string `gorm:"type:varchar(60);" json:"sku_no"` //sku编号 + Title string `gorm:"type:varchar(255);" json:"title"` //名称 + Image string `gorm:"size:255" json:"image"` //规格图片url + Specs string `gorm:"type:text;" json:"specs"` //规格 + Price float64 `gorm:"type:decimal(10,2);" json:"price"` //价格 +} + +func (MissionClaimOrderGoods) TableName() string { + return "mission_claim_order_goods" +} diff --git a/model/mission_claim_video.go b/model/mission_claim_video.go new file mode 100644 index 0000000..f17230e --- /dev/null +++ b/model/mission_claim_video.go @@ -0,0 +1,37 @@ +package model + +import ( + "pure/global" + "time" +) + +type MissionClaimVideo struct { //固定费用上传视频 + global.MG_MODEL + MissionClaimId uint `gorm:"type:int(11)" json:"mission_claim_id"` //领取任务id + VideoUrl string `gorm:"size:255" json:"video_url"` //视频上传地址 + Cover string `json:"cover" gorm:"size:255"` //视频封面 + Remark string `json:"remark"` + Status int `json:"status"` //状态 1:待审核 2:审核通过 3:审核不通过 + RewardStatus int `gorm:"type:tinyint(1)" json:"reward_status"` // 奖励发放状态 1:未发放 2:已发放 + SourceType int `json:"source_type" gorm:"type:tinyint(1);default:1"` //类型:1:固定费用上传 2:奖励任务上传 3:后台上传 + MissionId uint `json:"mission_id"` //任务ID + CreateBy string `gorm:"size:64" json:"create_by"` //创建人 + CreateTime time.Time `gorm:"-" json:"created_at"` // 创建时间 + Width int `json:"width"` //宽度 + Height int `json:"height"` //高度 + +} + +type MissionClaimVideoDetail struct { + MissionClaimVideo + Mission MissionDetail `gorm:"ForeignKey:ID;References:MissionId" json:"mission"` //任务信息 + Influencer UserSimple `gorm:"ForeignKey:UUID;References:CreateBy" json:"influencer"` //网红信息 +} + +func (MissionClaimVideo) TableName() string { + return "mission_claim_video" +} + +func (MissionClaimVideoDetail) TableName() string { + return "mission_claim_video" +} diff --git a/model/mission_claim_works.go b/model/mission_claim_works.go new file mode 100644 index 0000000..e1d6ce2 --- /dev/null +++ b/model/mission_claim_works.go @@ -0,0 +1,17 @@ +package model + +import "pure/global" + +type MissionClaimWorks struct { //领取任务发布的作品 + global.MG_MODEL + MissionClaimId uint `gorm:"type:int(11)" json:"mission_claim_id"` //领取任务id + Type int `gorm:"type:tinyint(1)" json:"type"` //平台 1:ins 2:YouTube 3:tiktok 4:Facebook 5:Twitter + Homepage string `gorm:"size:255" json:"homepage"` //作品主页地址 + Image string `json:"image"` //作品凭证截图 + VideoUrl string `gorm:"size:255" json:"video_url"` //视频上传地址 + +} + +func (MissionClaimWorks) TableName() string { + return "mission_claim_works" +} diff --git a/model/mission_recommend.go b/model/mission_recommend.go new file mode 100644 index 0000000..3b47da1 --- /dev/null +++ b/model/mission_recommend.go @@ -0,0 +1,27 @@ +package model + +import ( + "pure/global" +) + +type MissionRecommend struct { //任务推荐 + RelationId uint `gorm:"type:int(11);" json:"relation_id"` //关联ID,任务视频ID + CreateBy string `gorm:"size:64" json:"create_by"` //创建人 + Status int `gorm:"type:tinyint(1);" json:"status"` //状态 1:上架 2:下架 + Sort int `gorm:"type:tinyint(2)" json:"sort"` //倒序 //排序 + UpdateBy string `gorm:"size:64" json:"-"` //更新人 + global.MG_MODEL +} + +type MissionRecommendDetail struct { //任务推荐 + MissionRecommend //更新人 + MissionVideo MissionClaimVideoDetail `gorm:"ForeignKey:ID;References:RelationId" json:"mission_video"` //任务视频信息 +} + +func (MissionRecommend) TableName() string { + return "mission_recommend" +} + +func (MissionRecommendDetail) TableName() string { + return "mission_recommend" +} diff --git a/model/notify.go b/model/notify.go new file mode 100644 index 0000000..405aa97 --- /dev/null +++ b/model/notify.go @@ -0,0 +1,16 @@ +package model + +import "pure/global" + +type Notify struct { // 通知 + global.MG_MODEL + UserId string `gorm:"size:64" json:"userId"` // 用户id + RelationType string `gorm:"size:1" json:"relation_type"` // 关联类型 1-提现 + RelationId string `gorm:"size:64" json:"relation_id"` // 关联id + Title string `gorm:"size:255" json:"title"` // 通知标题 + Content string `gorm:"size:255" json:"content"` // 通知内容 +} + +func (Notify) TableName() string { + return "notify" +} diff --git a/model/order.go b/model/order.go new file mode 100644 index 0000000..ffa6a0c --- /dev/null +++ b/model/order.go @@ -0,0 +1,69 @@ +package model + +import ( + "pure/global" + "time" +) + +type Order struct { + global.MG_MODEL + Platform string `gorm:"size:10" json:"platform"` // 购买平台 + StoreNo string `gorm:"size:60" json:"store_no"` // 店铺编号 + OrderID string `gorm:"size:50;index" json:"orderID"` //订单号 + PaypalID string `gorm:"size:50" json:"paypalID"` //paypal订单号 + CaptureID string `gorm:"size:50" json:"captureID"` //paypal收款确认id + Code string `gorm:"size:20" json:"code"` //网红码? + UserID string `gorm:"size:50;index" json:"userID"` //用户id + CommodID uint `gorm:"size:50;index" json:"commodID"` //商品id + SkuNo string `gorm:"type:varchar(60);" json:"sku_no"` //商品规格编号 + SkuID int `gorm:"type:int(10);" json:"sku_id"` //商品规格编号 + Type int `gorm:"type:int(1);default:1" json:"type"` //类型 1-普通订单 2-预售订单 + Price float64 `gorm:"type:decimal(10,2)" json:"price"` //商品价格 + Number int `gorm:"type:int(10)" json:"number"` //数量 + PaidPrice float64 `gorm:"type:decimal(10,2)" json:"paidPrice"` //实付价格 + Status int `gorm:"type:int(1)" json:"status"` //订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消 + PayTime *time.Time `gorm:"" json:"payTime"` //付款时间 + SendTime *time.Time `gorm:"" json:"sendTime"` //发货时间 + ConfirmTime *time.Time `gorm:"" json:"confirmTime"` //收货时间 +} + +type OrderList struct { + Order + Goods OrderGoodsDetail `json:"goods"` // 商品信息 + User UserSimple `gorm:"-" json:"user"` //买家信息 + InfluencerAmount string `gorm:"-" json:"IAmount"` //网红佣金 +} + +type OrderDetail struct { + Order + Goods OrderGoodsDetail `gorm:"-" json:"goods"` // 商品信息 + Address OrderAddress `gorm:"-" json:"address"` //地址 + Deliver OrderDeliver `gorm:"-" json:"deliver"` //发货信息 + Store SellerStoreInfo `gorm:"-" json:"store"` // 店铺信息 + PostSale PostSale `gorm:"-" json:"postSale"` // 售后信息 + Bill BillView `gorm:"-" json:"bill"` // 交易信息 + Chain Chain `gorm:"-" json:"chain"` // 区块链 + InfluencerAmount string `gorm:"-" json:"IAmount"` //网红佣金 +} + +type OrderTotal struct { + Status2 int `json:"status2"` //待发货 + Status3 int `json:"status3"` //已发货 + Status4 int `json:"status4"` //已收货 +} + +type Chain struct { + Address string `json:"address"` // 合约地址 +} + +func (Order) TableName() string { + return "order" +} + +func (OrderList) TableName() string { + return "order" +} + +func (OrderDetail) TableName() string { + return "order" +} diff --git a/model/order_address.go b/model/order_address.go new file mode 100644 index 0000000..9c24918 --- /dev/null +++ b/model/order_address.go @@ -0,0 +1,12 @@ +package model + +//记录订单中的收货地址 +type OrderAddress struct { + Address + OrderID string `gorm:"size:50" json:"orderID"` + Platform string `gorm:"size:50" json:"platform"` //平台 saller(买家端) / customer(客户端) / influencer(网红端) +} + +func (OrderAddress) TableName() string { + return "order_address" +} diff --git a/model/order_deliver.go b/model/order_deliver.go new file mode 100644 index 0000000..b936b11 --- /dev/null +++ b/model/order_deliver.go @@ -0,0 +1,27 @@ +package model + +import "pure/global" + +type OrderDeliver struct { + global.MG_MODEL + OrderID string `gorm:"size:50" json:"orderID"` //订单号 + CourierNumber string `gorm:"size:50" json:"courierNumber"` //快递单号 + Courier string `gorm:"size:50" json:"courier"` //快递公司 + CourierLink string `gorm:"size:255" json:"courierLink"` //快递链接 + TrackId uint `json:"track_id"` // track表id +} + +type OrderDeliverDesc struct { + OrderID string `gorm:"size:50" json:"orderID"` //订单号 + CourierNumber string `gorm:"size:50" json:"courierNumber"` //快递单号 + Courier string `gorm:"size:50" json:"courier"` //快递公司 + CourierLink string `gorm:"size:255" json:"courierLink"` //快递链接 +} + +type PutDeliver struct { + Data []OrderDeliverDesc `json:"data"` +} + +func (OrderDeliver) TableName() string { + return "order_deliver" +} diff --git a/model/order_goods.go b/model/order_goods.go new file mode 100644 index 0000000..c8c4544 --- /dev/null +++ b/model/order_goods.go @@ -0,0 +1,26 @@ +package model + +import "pure/global" + +type OrderGoods struct { + global.MG_MODEL + OrderID string `gorm:"size:50" json:"orderID"` // 订单id + SpuNo string `gorm:"type:varchar(60);" json:"spu_no"` // 商品编号 + SkuNo string `gorm:"type:varchar(60);" json:"sku_no"` // 商品规格编号 + Specs string `gorm:"type:text;" json:"specs"` // 规格 + TbGoodsBase +} + +type OrderGoodsDetail struct { + OrderGoods + Attributes []TbAttributeWithValues `gorm:"-" json:"attributes"` // 规格详情 + GoodsSpecs []TbOrderGoodsSpecsDetail `gorm:"-" json:"goods_specs"` // 规格 +} + +func (OrderGoods) TableName() string { + return "order_goods" +} + +func (OrderGoodsDetail) TableName() string { + return "order_goods" +} diff --git a/model/order_goods_specs.go b/model/order_goods_specs.go new file mode 100644 index 0000000..5282abd --- /dev/null +++ b/model/order_goods_specs.go @@ -0,0 +1,30 @@ +package model + +import "pure/global" + +type OrderGoodsSpecs struct { + global.MG_MODEL + TbGoodsSpecsBase + OrderID string `gorm:"size:50" json:"orderID"` // 订单id + OrderGoodsId uint `json:"orderGoodsId"` // +} + +type TbOrderGoodsSpecsDetail struct { + GoodsId uint `json:"goods_id"` + Specs string `json:"specs"` // 规格 + //Attributes []TbAttributeDetail `gorm:"-" json:"-"` // 规格详情 + SkuNo string `json:"sku_no"` // 商品编码 + Price float64 `json:"price"` // 价格 + Image string `json:"image"` // 规格图片url + GoodsNo string `json:"goods_no"` // 商品编号 + Code string `json:"code"` // attribute定位标识 + OrderGoodsId uint `json:"orderGoodsId"` // +} + +func (OrderGoodsSpecs) TableName() string { + return "order_goods_specs" +} + +func (TbOrderGoodsSpecsDetail) TableName() string { + return "order_goods_specs" +} diff --git a/model/order_post_sale.go b/model/order_post_sale.go new file mode 100644 index 0000000..ccbaa17 --- /dev/null +++ b/model/order_post_sale.go @@ -0,0 +1,42 @@ +package model + +import ( + "pure/global" + "time" +) + +type OrderPostSale struct { // 订单售后记录 + global.MG_MODEL + Type int `gorm:"type:tinyint(1)" json:"type"` // 售后类型 1:仅退款 + OrderID string `gorm:"size:50" json:"orderId"` // 订单号 + StoreNo string `gorm:"size:60" json:"store_no"` // 店铺编号 + UserID string `gorm:"size:50" json:"userId"` // 用户id + Amount float64 `gorm:"type:decimal(10,2)" json:"amount"` // 退款金额 + Reason string `gorm:"size:1" json:"reason"` // 退款原因 + Images string `gorm:"size:255" json:"images"` // 图片 + Videos string `gorm:"size:255" json:"videos"` // 视频 + Status int `gorm:"type:tinyint(1)" json:"status"` // 处理状态 1:已提交 2:已处理 3:已拒绝 4:已撤回 + Remark string `gorm:"size:255" json:"remark"` // 原因 + ExamineTime *time.Time `gorm:"" json:"examine_time"` // 审核时间 + RefundStatus int `gorm:"type:tinyint(1)" json:"refundStatus"` // 退款状态 1:退款中 2:退款成功 3:退款失败 + RefundTime *time.Time `gorm:"" json:"refund_time"` // 退款时间 +} + +type PostSale struct { + ID uint `json:"id"` // id + OrderID string `json:"orderId"` // 订单id + Status int `json:"status"` // 处理状态 1:已提交 2:已处理 3:已拒绝 4:已撤回 + Remark string `json:"remark"` // 审核原因 + ExamineTime *time.Time `json:"examine_time"` // 审核时间 + RefundStatus int `json:"refundStatus"` // 退款状态 1:退款中 2:退款成功 3:退款失败 + RefundTime *time.Time `json:"refund_time"` // 退款时间 + CreatedAt *time.Time `json:"created_at"` // 创建时间 +} + +func (OrderPostSale) TableName() string { + return "order_post_sale" +} + +func (PostSale) TableName() string { + return "order_post_sale" +} diff --git a/model/paypalWebhook.go b/model/paypalWebhook.go new file mode 100644 index 0000000..2fbd41d --- /dev/null +++ b/model/paypalWebhook.go @@ -0,0 +1,21 @@ +package model + +type PaypalWebhookDetail struct { + ID string `json:"id"` + EventVersion string `json:"event_version"` + CreateTime string `json:"create_time"` + ResourceType string `json:"resource_type"` //checkout-order-订单付款 capture-付款确认 payouts-提现 refund-退款 + EventType string `json:"event_type"` + Summary string `json:"summary"` + Resource struct { + BatchHeader struct { + BatchStatus string `json:"batch_status"` //SUCCESS-成功 DENIED-拒绝 FAILED-失败 + SenderBatchHeader struct { + SenderBatchID string `json:"sender_batch_id"` + } `json:"sender_batch_header"` + } `json:"batch_header"` + CreateTime string `json:"create_time"` + ID string `json:"id"` + Status string `json:"status"` //COMPLETED-完成 APPROVED-用户已付款? PENDING-等待 + } `json:"resource"` +} diff --git a/model/platform_auth.go b/model/platform_auth.go new file mode 100644 index 0000000..152497f --- /dev/null +++ b/model/platform_auth.go @@ -0,0 +1,22 @@ +package model + +import ( + "pure/global" + "pure/model/request" +) + +type PlatformAuth struct { + global.MG_MODEL + UserID string `json:"user_id" gorm:"type:varchar(60);comment:用户ID"` + request.Platform + Status string `json:"status" gorm:"size:1;comment:认证状态 0:未认证 1:已认证 2:认证失败"` //认证状态 0:未认证 1:已认证 2:认证失败 +} + +type PlatformAuthSimple struct { + PlatformAuth + User UserSimple `json:"user"` +} + +func (PlatformAuth) TableName() string { + return "platform_auth" +} diff --git a/model/provider.go b/model/provider.go new file mode 100755 index 0000000..32f97f8 --- /dev/null +++ b/model/provider.go @@ -0,0 +1,60 @@ +// 自动生成模板Provider +package model + +import "pure/global" + +// 如果含有time.Time 请自行import time包 +type Provider struct { + global.MG_MODEL + Owner string `gorm:"size:50;comment:用户所属" json:"owner" ` // 用户所属 + Name string `gorm:"size:50;comment:提供者名称" json:"name" ` // 提供者名称 + Category string `gorm:"size:50;comment:提供者分类" json:"category" ` // 提供者分类 1-社交 2-支付 3-媒体 4-其他 + Code string `gorm:"size:50;comment:提供者代码" json:"code" ` // 提供者代码 google facebook twitter tiktok + ClientID string `gorm:"size:50;comment:客户端ID" json:"client_id" ` // 客户端ID + ClientSecret string `gorm:"size:50;comment:客户端密钥" json:"client_secret" ` // 客户端密钥 + Scope string `gorm:"size:50;comment:作用域" json:"scope" ` // 作用域 + TokenType string `gorm:"size:50;comment:令牌类型" json:"token_type" ` // 令牌类型 Bearer urlencoded + RedirectURI string `gorm:"size:50;comment:重定向URI" json:"redirect_uri" ` // 重定向URI + RedirectURIByAnd string `gorm:"size:50;comment:重定向URI" json:"redirect_uri_by_and" ` // 重定向URI(安卓) + RedirectURIByIos string `gorm:"size:50;comment:重定向URI" json:"redirect_uri_by_ios" ` // 重定向URI(IOS) + AuthURI string `gorm:"size:50;comment:认证URI" json:"auth_uri" ` // 认证URI + TokenURI string `gorm:"size:50;comment:令牌URI" json:"token_uri" ` // 令牌URI + TokenCheckURI string `gorm:"size:50;comment:令牌校验URI" json:"token_check_uri" ` // 令牌校验URI + UserInfoURI string `gorm:"size:50;comment:用户信息URI" json:"user_info_uri" ` // 用户信息URI +} + +type ClentProvider struct { + Web []Provider `json:"web"` + Android []Provider `json:"android"` + Ios []Provider `json:"ios"` +} + +type ProviderUser struct { + UserID string `gorm:"size:50;comment:用户ID" json:"user_id" ` // 用户ID + NickName string `gorm:"size:50;comment:昵称" json:"nick_name" ` // 昵称 + Avatar string `gorm:"size:50;comment:头像" json:"avatar" ` // 头像 + Email string `gorm:"size:50;comment:邮箱" json:"email" ` // 邮箱 + Phone string `gorm:"size:50;comment:手机号" json:"phone" ` // 手机号 +} + +type FacebookUserInfo struct { + UnionId string `json:"id"` + UserName string `json:"name"` + Email string `json:"email"` + Picture struct { + Data struct { + URL string `json:"url"` + } `json:"data"` + } `json:"picture"` +} + +type TiktokUser struct { + OpenID string `json:"open_id"` + UnionID string `json:"union_id"` + AvatarURL string `json:"avatar_url"` + DisplayName string `json:"display_name"` +} + +func (Provider) TableName() string { + return "provider" +} diff --git a/model/request/account.go b/model/request/account.go new file mode 100644 index 0000000..56d856d --- /dev/null +++ b/model/request/account.go @@ -0,0 +1,21 @@ +package request + +type AddAccount0 struct { + UserID string `gorm:"size:50;index" json:"userID"` //用户id + AccountName string `gorm:"size:50" json:"accountName"` //户名 + IDCard string `gorm:"size:30" json:"idCard"` //身份证 + Phone string `gorm:"size:20" json:"phone"` //手机号 + PayPalName string `gorm:"size:50" json:"payPalName"` //paypal账号 + Code string `json:"code"` + Platform string `gorm:"size:50" json:"platform"` //平台 saller(买家端) / customer(客户端) / influencer(网红端) +} + +type SearchCommission struct { + Receipt int `json:"receipt" form:"receipt"` //是否已到账 1-是 2-否 + PageInfo +} + +type SearchWithdrawal struct { + Status int `json:"status"` //类型 1-支出 2-收入 + PageInfo +} diff --git a/model/request/address.go b/model/request/address.go new file mode 100644 index 0000000..f5a405b --- /dev/null +++ b/model/request/address.go @@ -0,0 +1,7 @@ +package request + +import "pure/global" + +type ReqAddress struct { + global.BASE_ID +} diff --git a/model/request/bill.go b/model/request/bill.go new file mode 100644 index 0000000..064bfe3 --- /dev/null +++ b/model/request/bill.go @@ -0,0 +1,16 @@ +package request + +type GetBillDataParams struct { + Uint string `json:"uint" form:"uint"` // 1:全部 2:昨天 3:近30天 +} + +type SearchBillParams struct { + Uint string `json:"uint" form:"uint"` // 1:全部 2:昨天 3:近30天 + Status string `json:"status" form:"status"` // 空:全部 1-支出 2-收入 + Scene string `json:"scene" form:"scene"` // 空:默认 1:bill-center + PageInfo +} + +type FlowNoParam struct { + FlowNo string `json:"flow_no" form:"flow_no"` // 流水号 +} diff --git a/model/request/chain.go b/model/request/chain.go new file mode 100644 index 0000000..f4d4718 --- /dev/null +++ b/model/request/chain.go @@ -0,0 +1,5 @@ +package request + +type ChainParams struct { + Hash string `json:"hash" form:"hash"` // 区块/合约hash +} diff --git a/model/request/collection_mission.go b/model/request/collection_mission.go new file mode 100644 index 0000000..d506091 --- /dev/null +++ b/model/request/collection_mission.go @@ -0,0 +1,9 @@ +package request + +type SearchCollectionMission struct { + PageInfo +} + +type SearchRecommendMission struct { + PageInfo +} diff --git a/model/request/common.go b/model/request/common.go new file mode 100644 index 0000000..ecf5d7e --- /dev/null +++ b/model/request/common.go @@ -0,0 +1,56 @@ +package request + +// Paging common input parameter structure +type PageInfo struct { + Page int `json:"page" form:"page"` // 页码 + PageSize int `json:"pageSize" form:"pageSize"` // 每页大小 +} + +// Find by id structure +type GetById struct { + ID float64 `json:"id" form:"id"` // 主键ID +} + +type IdsReq struct { + Ids []int `json:"ids" form:"ids"` +} + +type IdsStrReq struct { + Ids []string `json:"ids" form:"ids"` +} + +type IdReq struct { + ID uint `json:"id" form:"id"` //id +} + +type IdStrReq struct { + ID string `json:"id" form:"id"` +} + +type StatusParam struct { + Status string `json:"status" form:"id"` + ID string `json:"id" form:"id"` +} + +type StatusParams struct { + Status string `json:"status"` + IdsStrReq +} + +type StatusParamsInt struct { + Status int `json:"status"` + IdsStrReq +} + +type ChannelId struct { + ChannelId string `json:"channelId" form:"channelId"` +} + +type StructParams map[string]interface{} + +// Get role by id structure +type GetAuthorityId struct { + AuthorityId string // 角色ID +} + +type Empty struct{} diff --git a/model/request/dict.go b/model/request/dict.go new file mode 100644 index 0000000..3950b1d --- /dev/null +++ b/model/request/dict.go @@ -0,0 +1,5 @@ +package request + +type SearchDictDataParams struct { + TypeCode string `json:"typeCode" form:"typeCode"` //取值 release_country=发布国家 release_channel=发布渠道 tag_type=标签类型 +} diff --git a/model/request/jwt.go b/model/request/jwt.go new file mode 100644 index 0000000..b876f9f --- /dev/null +++ b/model/request/jwt.go @@ -0,0 +1,19 @@ +package request + +import ( + "github.com/dgrijalva/jwt-go" +) + +// Custom claims structure +type UserClaims struct { + UUID string + ID uint + Username string + NickName string + Email string + Appid string + Type string + IDForbidden bool + BufferTime int64 + jwt.StandardClaims +} diff --git a/model/request/mission.go b/model/request/mission.go new file mode 100644 index 0000000..6e0c1e9 --- /dev/null +++ b/model/request/mission.go @@ -0,0 +1,67 @@ +package request + +type SearchMission struct { + PageInfo +} + +type SearchMissionClaim struct { + MissionStatus int `json:"-"` + HireType int `json:"hire_type" form:"hire_type"` // 佣金类型 1:固定佣金 2:比例抽成 + VideoUpload int `json:"video_upload" form:"video_upload"` //是否筛选上传视频 1是 + ExcludeIds []uint `json:"-"` //排除ID + PageInfo +} + +type ClaimMission struct { + MissionId uint `json:"mission_id"` //任务id + AddressId uint `json:"address_id"` //收货地址id + SpuNo string `json:"spu_no"` //商品spu_no + SkuNo string `json:"sku_no"` //商品sku_no + Email string `json:"email"` //邮箱地址 +} + +type MissionId struct { + MissionId uint `json:"mission_id"` //任务 +} + +type MissionCode struct { + Code string `json:"code" form:"code"` //任务编码 +} + +type ClaimMissionWorks struct { + ID uint `json:"id"` //id + Type int `json:"type"` //平台 1:ins 2:Pinterest 3:tk 4:Twitter 5:Facebook 6:Reddit + Homepage string `json:"homepage"` //作品主页地址 + Image string `json:"image"` //作品凭证截图 + VideoUrl string `json:"video_url"` //视频上传地址 +} + +type ClaimMissionWorksList struct { + MissionClaimId uint `json:"mission_claim_id"` //领取任务id + Works []ClaimMissionWorks `json:"works"` //作品列表 +} + +type ClaimMissionVideo struct { + MissionClaimId uint `json:"mission_claim_id"` //领取任务id + VideoUrl string `json:"video_url"` //视频上传地址 + Cover string `json:"cover"` + SourceType int `json:"source_type"` //类型:1:固定费用上传 2:奖励任务上传 3:后台上传 + Width int `json:"width"` //宽度 + Height int `json:"height"` //高度 +} + +type AddSysMissionReward struct { + Type int `json:"type"` //奖励类型 1.视频上传 2.信息完善 3.商家任务 + RelationId string `json:"relationId"` //关联项目id + AchieveNum int64 `json:"achieve_num"` //已完成任务次数 + CreateBy string `json:"create_by"` //创建人 +} + +type SearchSysReward struct { + Status int `form:"status" json:"status"` //状态 1待发放 2已发放 3已领取 + PageInfo +} + +type SearchSysRewardSummary struct { + Status int `form:"status" json:"status"` //状态 1待发放 2已发放 3已领取 +} diff --git a/model/request/notify.go b/model/request/notify.go new file mode 100644 index 0000000..08d55a5 --- /dev/null +++ b/model/request/notify.go @@ -0,0 +1,6 @@ +package request + +type SearchNotify struct { + PageInfo + RelationType string `json:"relation_type" form:"relation_type"` +} diff --git a/model/request/order.go b/model/request/order.go new file mode 100644 index 0000000..ac58f6a --- /dev/null +++ b/model/request/order.go @@ -0,0 +1,42 @@ +package request + +type SearchOrderList struct { + OrderID string `json:"orderID" form:"orderID"` //订单号 + Code string `json:"code" form:"code"` //网红码? + Status int `json:"status" form:"status"` //订单状态 //订单状态 1-待付款 2-待发货 3-已发货 4-已完成 5-已取消 + Group string // 数据库分组 + PageInfo +} + +type GetOrderParams struct { + OrderID string `json:"orderID" form:"orderID"` //订单号 +} + +type SceneParams struct { + Scene string `json:"scene" form:"scene"` // 场景 my:我的 order-list:订单列表 +} + +type AddOrder struct { + Code string `json:"code"` //网红码? + SkuID int `json:"skuID"` //商品规格id + Number int `json:"number"` //数量 + AddressID int `json:"addressID"` //收货地址id + PayMode int `json:"payMode"` //支付方式 1-paypal +} + +type UpdateUserOrderStatus struct { + OrderID string `json:"orderID"` //订单号 + Status int `json:"status"` //订单状态 4-已完成 5-已取消 +} + +type CheckOrderParams struct { + Token string `json:"token" form:"token"` +} + +type DeleteUserORder struct { + OrderID string `json:"orderID"` //订单号 +} + +type OrderMessage struct { + OrderID string `json:"orderID"` //订单号 +} diff --git a/model/request/othor.go b/model/request/othor.go new file mode 100644 index 0000000..96d3e03 --- /dev/null +++ b/model/request/othor.go @@ -0,0 +1,11 @@ +package request + +type SendMessage struct { + Phone string `form:"phone"` + Type int `form:"type"` //1:登录验证码 2-解绑 3-绑定 4-提现 + CountryCode string `json:"country_code" form:"country_code" gorm:"size:255"` //用户手机号国家代码 国际区号 86 中国 1美国 +} + +type SendEmail struct { + Email string `form:"email"` +} diff --git a/model/request/sys_brochure.go b/model/request/sys_brochure.go new file mode 100644 index 0000000..cad7675 --- /dev/null +++ b/model/request/sys_brochure.go @@ -0,0 +1,5 @@ +package request + +type SysBrochureType struct { + Type string `json:"type" form:"type"` +} diff --git a/model/request/tb_goods.go b/model/request/tb_goods.go new file mode 100644 index 0000000..5be0274 --- /dev/null +++ b/model/request/tb_goods.go @@ -0,0 +1,15 @@ +package request + +type Goods struct { + ID uint `json:"id" form:"id"` //商品id + SkuNo string `json:"sku_no" form:"sku_no"` //sku_no + ClaimNo string `json:"claim_no" form:"claim_no"` //领取任务id +} + +type SpuNo struct { + SpuNo string `json:"spu_no"` //spu_no +} + +type SearchCollectionGoods struct { + PageInfo +} diff --git a/model/request/user.go b/model/request/user.go new file mode 100644 index 0000000..4ffea59 --- /dev/null +++ b/model/request/user.go @@ -0,0 +1,57 @@ +package request + +import "time" + +// User login structure +type UserDetail struct { + Type string `json:"type"` // 修改字段 platform-平台 tags-个人标签 + Platform string `json:"platform"` // 平台及地址逗号隔开 eg:(ins:https://baidu.com/user/1,qq:12345678) + Tags string `json:"tags"` // 个人标签 +} + +type UserLogin struct { + Email string `json:"email"` //邮箱 + Phone string `json:"phone"` //手机号 + Code string `json:"code"` //验证码 + Password string `json:"password"` //密码 + Type string `json:"type"` // 1-手机号 2-邮箱 + Appid string `json:"appid"` //应用id + CountryCode string `json:"country_code" form:"country_code" gorm:"size:255"` //用户手机号国家代码 国际区号 86 中国 1美国 +} + +type UserRegister struct { + Email string `json:"email"` // 邮箱 + Code string `json:"code"` // 验证码 + Nickname string `json:"nickname"` //昵称 + Avatar string `json:"avatar"` //头像 + Appid string `json:"appid"` //应用id + CountryCode string `json:"country_code" form:"country_code" gorm:"size:255"` //用户手机号国家代码 国际区号 86 中国 1美国 +} + +type UserBandPhone struct { + Phone string `json:"phone"` //手机号 + Code string `json:"code"` //验证码 +} + +type UserPlatformAuth struct { + Platform Platform `json:"platform"` //平台 + Tags string `json:"tags"` //个人标签 +} + +type Platform struct { + Platform string `json:"platform"` //平台 字典表获取 + Label string `gorm:"-" json:"label"` + Url string `json:"url"` //主页地址 + Image string `json:"image"` //图片 + IsAuth bool `json:"is_auth"` //是否认证 + CreatedAt *time.Time `json:"-" gorm:"-"` //创建时间 +} + +type UserAuthorized struct { + Appid string `json:"appid"` //应用id + Client string `json:"client"` //客户端 ios android web + Platform string `json:"platform"` //平台 google facebook twitter tiktok + Code string `json:"code"` //授权码 + Token string `json:"token"` //token + Uuid string `json:"uuid"` //设备唯一标识 +} diff --git a/model/request/wallet.go b/model/request/wallet.go new file mode 100644 index 0000000..558d5fa --- /dev/null +++ b/model/request/wallet.go @@ -0,0 +1,24 @@ +package request + +type AddAccount struct { + AccountName string `json:"account_name"` // 户名 + BankCode string `json:"bank_code"` // 银行编码 + SwiftCode string `json:"swift_code"` // swift编码 + BankCard string `json:"bank_card"` // 银行卡号 + Address string `json:"address"` // 收款人地址 + Country string `json:"country"` // 国家/地区 + Currency string `json:"currency"` // 币种 USD: 美元 + IsDefault bool `json:"is_default"` // 是否默认 +} + +type DeleteAccount struct { + ID uint `json:"id"` //主键 + Phone string `json:"phone"` //手机号 + Code string `json:"code"` //验证码 +} + +type WithdrawalParams struct { + //Code string `json:"code"` // 验证码 + Amount float64 `json:"amount"` // 提现金额 + AccountID int `json:"accountID"` // 提现账户id +} diff --git a/model/response/banner.go b/model/response/banner.go new file mode 100644 index 0000000..ed0180d --- /dev/null +++ b/model/response/banner.go @@ -0,0 +1,16 @@ +package response + +import "pure/global" + +type BannerListResponse struct { + global.BASE_ID + RelationId string `json:"relationId"` //关联项目id + RelationType string `json:"relationType"` //关联类型 01-任务 + Title string `json:"title"` //标题 + CoverUrl string `json:"coverUrl"` //封面图 + LinkType string `json:"linkType"` //链接类型 0:内链 1:外链 + Link string `json:"link"` //链接地址 + Type string `json:"type"` //任务-0101 平台奖励页-0102 + Status string ` json:"status"` //状态 0=下架 1=上架 + SortIndex int `json:"sort_index"` //序号索引 +} diff --git a/model/response/chain.go b/model/response/chain.go new file mode 100644 index 0000000..488a138 --- /dev/null +++ b/model/response/chain.go @@ -0,0 +1,10 @@ +package response + +import "time" + +type ChainResp struct { + Time *time.Time `json:"time"` // 上链时间 + BlockHeight int64 `json:"block_height"` // 块高度 + BlockAddress string `json:"block_adress"` // 所在区块 + Hash string `json:"hash"` // 交易哈希 +} diff --git a/model/response/common.go b/model/response/common.go new file mode 100644 index 0000000..f6550c5 --- /dev/null +++ b/model/response/common.go @@ -0,0 +1,19 @@ +package response + +type PageResult struct { + List any `json:"list"` + Total int64 `json:"total"` + Page int `json:"page"` + PageSize int `json:"pageSize"` +} + +type SelectListResult struct { + List any `json:"list"` +} + +type TrackItem struct { + CheckpointDate string `json:"checkpoint_date"` + TrackingDetail string `json:"tracking_detail"` + DeliveryStatus string `json:"delivery_status"` + DeliveryStatusCn string `json:"delivery_status_cn"` +} diff --git a/model/response/mission.go b/model/response/mission.go new file mode 100644 index 0000000..2c31118 --- /dev/null +++ b/model/response/mission.go @@ -0,0 +1,116 @@ +package response + +import ( + "pure/model" + "time" +) + +type MissionClaimView struct { + ID uint `json:"id"` //ID + ClaimNo string `json:"claim_no"` //领取任务编号 + MissionId uint `json:"mission_id"` //任务id + AchieveNum int64 `json:"achieve_num"` //已完成商品数量 + Status int `json:"status"` //状态 1:已领取待发货 2:已发货 3:已收货推广中 + SpreadUrl string `json:"spread_url"` //推广链接 + HireType int `json:"hire_type"` //佣金类型 1:固定佣金 2:比例抽成 + HireMoneyExpect string `json:"hire_money_expect"` //预计佣金描述 + EndTime *time.Time `json:"end_time"` //任务结束时间 + ExpireAt time.Time `json:"expire_at"` //任务推广过期时间 + CollectStatus bool `gorm:"-" json:"collect_status"` //收藏状态 true:已收藏 false:未收藏 + Goods MissionGoodsView `json:"goods"` +} + +type MissionCollectView struct { + ID uint `json:"id"` //ID + MissionId uint `json:"mission_id"` //任务id + AchieveNum int64 `json:"achieve_num"` //已完成商品数量 + TotalBonus float64 `json:"total_bonus"` + Status int `json:"status"` + HireType int `json:"hire_type"` //佣金类型 1:固定佣金 2:比例抽成 + HireMoneyExpect string `json:"hire_money_expect"` //预计佣金描述 + Goods MissionGoodsView `json:"goods"` +} + +type MissionGoodsView struct { + GoodsId uint `json:"goods_id"` + SpuNo string `json:"spu_no"` //编号 + Title string `json:"title"` //标题 + TitleEng string `json:"title_eng"` //英文标题 + Images string `json:"images"` //图片 + Price float64 `gorm:"type:decimal(10,2);" json:"price_min"` //最低规格价格 + SkuNo string `json:"sku_no"` //sku编号 + +} + +type MissionRecommendView struct { + ID uint `json:"id"` //ID + MissionId uint `json:"mission_id"` //任务id + AchieveNum int64 `json:"achieve_num"` //已完成商品数量 + TotalBonus float64 `json:"total_bonus"` + Status int `json:"status"` + HireType int `json:"hire_type"` //佣金类型 1:固定佣金 2:比例抽成 + HireMoneyExpect string `json:"hire_money_expect"` //预计佣金描述 + Goods MissionGoodsView `json:"goods"` + Tags string `json:"tags"` +} + +type MissionRecommendResponse struct { + model.MissionRecommend + MissionVideoCommonData +} + +type MissionVideoResponse struct { + ID uint `json:"id"` + MissionVideoCommonData +} + +type MissionVideoCommonData struct { + MissionId uint `json:"mission_id"` //任务ID + VideoUrl string `json:"video_url"` //视频地址 + Cover string `json:"cover"` //封面 + Title string `json:"title"` //任务标题 + GoodsTitle string `json:"goods_title"` //商品标题 + GoodsTitleEng string `json:"goods_title_eng"` //商品英文标题 + Influencer model.UserSimple `json:"influencer"` + //todo 标签系统 + Tag string `json:"tag"` + MissionStatus int `json:"mission_status"` //任务状态 + StartTime *time.Time `json:"start_time"` //任务起始时间 + EndTime *time.Time `json:"end_time"` //任务结束时间 + HireType int `json:"hire_type"` //佣金类型 1:固定佣金 2:比例抽成 + HireMoney float64 `json:"hire_money"` //hire_type==1 佣金金额 + HireRatio float64 `json:"hire_ratio"` //hire_type==2 抽成比例 + HireMoneyExpect string `gorm:"-" json:"hire_money_expect"` //预计佣金描述 + ReleaseCountry string `gorm:"-" json:"release_country"` //发布国家 + ReleaseChannels string `gorm:"-" json:"release_channels"` //发布渠道 + AchieveNum int64 `json:"achieve_num"` //已完成商品数量 + TotalBonus float64 `json:"total_bonus"` //累计奖励 + BoughtNum float64 `json:"bought_num"` //购买人数 + Width int `json:"width"` //宽度 + Height int `json:"height"` //高度 + ClaimNum int64 `json:"claim_num"` //任务领取人数 +} + +type SysMissionBonus struct { + VideoBonus SysBonusDetail `json:"video_bonus"` //视频上传 + TotalBonus float64 `json:"total_bonus"` //奖励汇总金额 + Total int64 `json:"total"` //奖励总笔数 +} + +type SysBonusDetail struct { + model.SysMissionBonus + Title string `json:"title"` //标题 + AchieveMax int64 `json:"achieve_max"` //最大完成次数 + MissionList []SysMissionDesc `json:"mission_list"` //任务列表 +} + +type SysMissionDesc struct { + Title string `json:"title"` //任务标题 + Bonus float64 `json:"bonus"` //奖励金额 + Description string `json:"description"` //描述 + AchieveNum int `json:"achieve_num"` + Status int `json:"status"` //状态 1待发放 2已发放 3已领取 0未完成 + TitleEng string `json:"title_eng"` //任务标题英文 + DescriptionEng string `json:"description_eng"` //描述英文 + +} diff --git a/model/response/paypalOrder.go b/model/response/paypalOrder.go new file mode 100644 index 0000000..17bc99f --- /dev/null +++ b/model/response/paypalOrder.go @@ -0,0 +1,843 @@ +package response + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "sync" + "time" +) + +const ( + // APIBaseSandBox points to the sandbox (for testing) version of the API + APIBaseSandBox = "https://api.sandbox.paypal.com" + + // APIBaseLive points to the live version of the API + APIBaseLive = "https://api.paypal.com" + + // RequestNewTokenBeforeExpiresIn is used by SendWithAuth and try to get new Token when it's about to expire + RequestNewTokenBeforeExpiresIn = time.Duration(60) * time.Second +) + +// Possible values for `no_shipping` in InputFields +// +// https://developer.paypal.com/docs/api/payment-experience/#definition-input_fields +const ( + NoShippingDisplay uint = 0 + NoShippingHide uint = 1 + NoShippingBuyerAccount uint = 2 +) + +// Possible values for `address_override` in InputFields +// +// https://developer.paypal.com/docs/api/payment-experience/#definition-input_fields +const ( + AddrOverrideFromFile uint = 0 + AddrOverrideFromCall uint = 1 +) + +// Possible values for `landing_page_type` in FlowConfig +// +// https://developer.paypal.com/docs/api/payment-experience/#definition-flow_config +const ( + LandingPageTypeBilling string = "Billing" + LandingPageTypeLogin string = "Login" +) + +// Possible value for `allowed_payment_method` in PaymentOptions +// +// https://developer.paypal.com/docs/api/payments/#definition-payment_options +const ( + AllowedPaymentUnrestricted string = "UNRESTRICTED" + AllowedPaymentInstantFundingSource string = "INSTANT_FUNDING_SOURCE" + AllowedPaymentImmediatePay string = "IMMEDIATE_PAY" +) + +// Possible value for `intent` in CreateOrder +// +// https://developer.paypal.com/docs/api/orders/v2/#orders_create +const ( + OrderIntentCapture string = "CAPTURE" + OrderIntentAuthorize string = "AUTHORIZE" +) + +// Possible values for `category` in Item +// +// https://developer.paypal.com/docs/api/orders/v2/#definition-item +const ( + ItemCategoryDigitalGood string = "DIGITAL_GOODS" + ItemCategoryPhysicalGood string = "PHYSICAL_GOODS" +) + +// Possible values for `shipping_preference` in ApplicationContext +// +// https://developer.paypal.com/docs/api/orders/v2/#definition-application_context +const ( + ShippingPreferenceGetFromFile string = "GET_FROM_FILE" + ShippingPreferenceNoShipping string = "NO_SHIPPING" + ShippingPreferenceSetProvidedAddress string = "SET_PROVIDED_ADDRESS" +) + +type ( + // JSONTime overrides MarshalJson method to format in ISO8601 + JSONTime time.Time + + // Address struct + Address struct { + Line1 string `json:"line1"` + Line2 string `json:"line2,omitempty"` + City string `json:"city"` + CountryCode string `json:"country_code"` + PostalCode string `json:"postal_code,omitempty"` + State string `json:"state,omitempty"` + Phone string `json:"phone,omitempty"` + } + + // AgreementDetails struct + AgreementDetails struct { + OutstandingBalance AmountPayout `json:"outstanding_balance"` + CyclesRemaining int `json:"cycles_remaining,string"` + CyclesCompleted int `json:"cycles_completed,string"` + NextBillingDate time.Time `json:"next_billing_date"` + LastPaymentDate time.Time `json:"last_payment_date"` + LastPaymentAmount AmountPayout `json:"last_payment_amount"` + FinalPaymentDate time.Time `json:"final_payment_date"` + FailedPaymentCount int `json:"failed_payment_count,string"` + } + + // Amount struct + Amount struct { + Currency string `json:"currency"` + Total string `json:"total"` + Details Details `json:"details,omitempty"` + } + + // AmountPayout struct + AmountPayout struct { + Currency string `json:"currency"` + Value string `json:"value"` + } + + // ApplicationContext struct + ApplicationContext struct { + BrandName string `json:"brand_name,omitempty"` + Locale string `json:"locale,omitempty"` + LandingPage string `json:"landing_page,omitempty"` + ShippingPreference string `json:"shipping_preference,omitempty"` + UserAction string `json:"user_action,omitempty"` + ReturnURL string `json:"return_url,omitempty"` + CancelURL string `json:"cancel_url,omitempty"` + } + + // Authorization struct + Authorization struct { + Amount *Amount `json:"amount,omitempty"` + CreateTime *time.Time `json:"create_time,omitempty"` + UpdateTime *time.Time `json:"update_time,omitempty"` + State string `json:"state,omitempty"` + ParentPayment string `json:"parent_payment,omitempty"` + ID string `json:"id,omitempty"` + ValidUntil *time.Time `json:"valid_until,omitempty"` + Links []Link `json:"links,omitempty"` + ClearingTime string `json:"clearing_time,omitempty"` + ProtectionEligibility string `json:"protection_eligibility,omitempty"` + ProtectionEligibilityType string `json:"protection_eligibility_type,omitempty"` + } + + // AuthorizeOrderResponse . + AuthorizeOrderResponse struct { + CreateTime *time.Time `json:"create_time,omitempty"` + UpdateTime *time.Time `json:"update_time,omitempty"` + ID string `json:"id,omitempty"` + Status string `json:"status,omitempty"` + Intent string `json:"intent,omitempty"` + PurchaseUnits []PurchaseUnitRequest `json:"purchase_units,omitempty"` + Payer *PayerWithNameAndPhone `json:"payer,omitempty"` + } + + // AuthorizeOrderRequest - https://developer.paypal.com/docs/api/orders/v2/#orders_authorize + AuthorizeOrderRequest struct { + PaymentSource *PaymentSource `json:"payment_source,omitempty"` + ApplicationContext ApplicationContext `json:"application_context,omitempty"` + } + + // CaptureOrderRequest - https://developer.paypal.com/docs/api/orders/v2/#orders_capture + CaptureOrderRequest struct { + PaymentSource *PaymentSource `json:"payment_source"` + } + + // BatchHeader struct + BatchHeader struct { + Amount *AmountPayout `json:"amount,omitempty"` + Fees *AmountPayout `json:"fees,omitempty"` + PayoutBatchID string `json:"payout_batch_id,omitempty"` + BatchStatus string `json:"batch_status,omitempty"` + TimeCreated *time.Time `json:"time_created,omitempty"` + TimeCompleted *time.Time `json:"time_completed,omitempty"` + SenderBatchHeader *SenderBatchHeader `json:"sender_batch_header,omitempty"` + } + + // BillingAgreement struct + BillingAgreement struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + StartDate JSONTime `json:"start_date,omitempty"` + Plan BillingPlan `json:"plan,omitempty"` + Payer Payer `json:"payer,omitempty"` + ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"` + OverrideMerchantPreferences *MerchantPreferences `json:"override_merchant_preferences,omitempty"` + } + + // BillingPlan struct + BillingPlan struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Type string `json:"type,omitempty"` + PaymentDefinitions []PaymentDefinition `json:"payment_definitions,omitempty"` + MerchantPreferences *MerchantPreferences `json:"merchant_preferences,omitempty"` + } + + // Capture struct + Capture struct { + Amount *Amount `json:"amount,omitempty"` + IsFinalCapture bool `json:"is_final_capture"` + CreateTime *time.Time `json:"create_time,omitempty"` + UpdateTime *time.Time `json:"update_time,omitempty"` + State string `json:"state,omitempty"` + ParentPayment string `json:"parent_payment,omitempty"` + ID string `json:"id,omitempty"` + Links []Link `json:"links,omitempty"` + } + + // ChargeModel struct + ChargeModel struct { + Type string `json:"type,omitempty"` + Amount AmountPayout `json:"amount,omitempty"` + } + + // Client represents a Paypal REST API Client + Client struct { + sync.Mutex + Client *http.Client + ClientID string + Secret string + APIBase string + Log io.Writer // If user set log file name all requests will be logged there + Token *TokenResponse + tokenExpiresAt time.Time + } + + // CreditCard struct + CreditCard struct { + ID string `json:"id,omitempty"` + PayerID string `json:"payer_id,omitempty"` + ExternalCustomerID string `json:"external_customer_id,omitempty"` + Number string `json:"number"` + Type string `json:"type"` + ExpireMonth string `json:"expire_month"` + ExpireYear string `json:"expire_year"` + CVV2 string `json:"cvv2,omitempty"` + FirstName string `json:"first_name,omitempty"` + LastName string `json:"last_name,omitempty"` + BillingAddress *Address `json:"billing_address,omitempty"` + State string `json:"state,omitempty"` + ValidUntil string `json:"valid_until,omitempty"` + } + + // CreditCards GET /v1/vault/credit-cards + CreditCards struct { + Items []CreditCard `json:"items"` + Links []Link `json:"links"` + TotalItems int `json:"total_items"` + TotalPages int `json:"total_pages"` + } + + // CreditCardToken struct + CreditCardToken struct { + CreditCardID string `json:"credit_card_id"` + PayerID string `json:"payer_id,omitempty"` + Last4 string `json:"last4,omitempty"` + ExpireYear string `json:"expire_year,omitempty"` + ExpireMonth string `json:"expire_month,omitempty"` + } + + // CreditCardsFilter struct + CreditCardsFilter struct { + PageSize int + Page int + } + + // CreditCardField PATCH /v1/vault/credit-cards/credit_card_id + CreditCardField struct { + Operation string `json:"op"` + Path string `json:"path"` + Value string `json:"value"` + } + + // Currency struct + Currency struct { + Currency string `json:"currency,omitempty"` + Value string `json:"value,omitempty"` + } + + // Details structure used in Amount structures as optional value + Details struct { + Subtotal string `json:"subtotal,omitempty"` + Shipping string `json:"shipping,omitempty"` + Tax string `json:"tax,omitempty"` + HandlingFee string `json:"handling_fee,omitempty"` + ShippingDiscount string `json:"shipping_discount,omitempty"` + Insurance string `json:"insurance,omitempty"` + GiftWrap string `json:"gift_wrap,omitempty"` + } + + // ErrorResponseDetail struct + ErrorResponseDetail struct { + Field string `json:"field"` + Issue string `json:"issue"` + Links []Link `json:"link"` + } + + // ErrorResponse https://developer.paypal.com/docs/api/errors/ + ErrorResponse struct { + Response *http.Response `json:"-"` + Name string `json:"name"` + DebugID string `json:"debug_id"` + Message string `json:"message"` + InformationLink string `json:"information_link"` + Details []ErrorResponseDetail `json:"details"` + } + + // ExecuteAgreementResponse struct + ExecuteAgreementResponse struct { + ID string `json:"id"` + State string `json:"state"` + Description string `json:"description,omitempty"` + Payer Payer `json:"payer"` + Plan BillingPlan `json:"plan"` + StartDate time.Time `json:"start_date"` + ShippingAddress ShippingAddress `json:"shipping_address"` + AgreementDetails AgreementDetails `json:"agreement_details"` + Links []Link `json:"links"` + } + + // ExecuteResponse struct + ExecuteResponse struct { + ID string `json:"id"` + Links []Link `json:"links"` + State string `json:"state"` + Payer PaymentPayer `json:"payer"` + Transactions []Transaction `json:"transactions,omitempty"` + } + + // FundingInstrument struct + FundingInstrument struct { + CreditCard *CreditCard `json:"credit_card,omitempty"` + CreditCardToken *CreditCardToken `json:"credit_card_token,omitempty"` + } + + // Item struct + Item struct { + Quantity uint32 `json:"quantity"` + Name string `json:"name"` + Price string `json:"price"` + Currency string `json:"currency"` + SKU string `json:"sku,omitempty"` + Description string `json:"description,omitempty"` + Tax string `json:"tax,omitempty"` + UnitAmount *Money `json:"unit_amount,omitempty"` + Category string `json:"category,omitempty"` + } + + // ItemList struct + ItemList struct { + Items []Item `json:"items,omitempty"` + ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"` + } + + // Link struct + Link struct { + Href string `json:"href"` + Rel string `json:"rel,omitempty"` + Method string `json:"method,omitempty"` + Enctype string `json:"enctype,omitempty"` + } + + // PurchaseUnitAmount struct + PurchaseUnitAmount struct { + Currency string `json:"currency_code"` + Value string `json:"value"` + Breakdown *PurchaseUnitAmountBreakdown `json:"breakdown,omitempty"` + } + + // PurchaseUnitAmountBreakdown struct + PurchaseUnitAmountBreakdown struct { + ItemTotal *Money `json:"item_total,omitempty"` + Shipping *Money `json:"shipping,omitempty"` + Handling *Money `json:"handling,omitempty"` + TaxTotal *Money `json:"tax_total,omitempty"` + Insurance *Money `json:"insurance,omitempty"` + ShippingDiscount *Money `json:"shipping_discount,omitempty"` + Discount *Money `json:"discount,omitempty"` + } + + // Money struct + // + // https://developer.paypal.com/docs/api/orders/v2/#definition-money + Money struct { + Currency string `json:"currency_code"` + Value string `json:"value"` + } + + // PurchaseUnit struct + PurchaseUnit struct { + ReferenceID string `json:"reference_id"` + Amount *PurchaseUnitAmount `json:"amount,omitempty"` + } + + // TaxInfo used for orders. + TaxInfo struct { + TaxID string `json:"tax_id,omitempty"` + TaxIDType string `json:"tax_id_type,omitempty"` + } + + // PhoneWithTypeNumber struct for PhoneWithType + PhoneWithTypeNumber struct { + NationalNumber string `json:"national_number,omitempty"` + } + + // PhoneWithType struct used for orders + PhoneWithType struct { + PhoneType string `json:"phone_type,omitempty"` + PhoneNumber *PhoneWithTypeNumber `json:"phone_number,omitempty"` + } + + // CreateOrderPayerName create order payer name + CreateOrderPayerName struct { + GivenName string `json:"given_name,omitempty"` + Surname string `json:"surname,omitempty"` + } + + // CreateOrderPayer used with create order requests + CreateOrderPayer struct { + Name *CreateOrderPayerName `json:"name,omitempty"` + EmailAddress string `json:"email_address,omitempty"` + PayerID string `json:"payer_id,omitempty"` + Phone *PhoneWithType `json:"phone,omitempty"` + BirthDate string `json:"birth_date,omitempty"` + TaxInfo *TaxInfo `json:"tax_info,omitempty"` + Address *ShippingDetailAddressPortable `json:"address,omitempty"` + } + + // PurchaseUnitRequest struct + PurchaseUnitRequest struct { + ReferenceID string `json:"reference_id,omitempty"` + Amount *PurchaseUnitAmount `json:"amount"` + Payee *PayeeForOrders `json:"payee,omitempty"` + Description string `json:"description,omitempty"` + CustomID string `json:"custom_id,omitempty"` + InvoiceID string `json:"invoice_id,omitempty"` + SoftDescriptor string `json:"soft_descriptor,omitempty"` + Items []Item `json:"items,omitempty"` + Shipping *ShippingDetail `json:"shipping,omitempty"` + } + + // MerchantPreferences struct + MerchantPreferences struct { + SetupFee *AmountPayout `json:"setup_fee,omitempty"` + ReturnURL string `json:"return_url,omitempty"` + CancelURL string `json:"cancel_url,omitempty"` + AutoBillAmount string `json:"auto_bill_amount,omitempty"` + InitialFailAmountAction string `json:"initial_fail_amount_action,omitempty"` + MaxFailAttempts string `json:"max_fail_attempts,omitempty"` + } + + // Order struct + Order struct { + ID string `json:"id,omitempty"` + Status string `json:"status,omitempty"` + Intent string `json:"intent,omitempty"` + PurchaseUnits []PurchaseUnit `json:"purchase_units,omitempty"` + Links []Link `json:"links,omitempty"` + CreateTime *time.Time `json:"create_time,omitempty"` + UpdateTime *time.Time `json:"update_time,omitempty"` + } + + // CaptureAmount struct + CaptureAmount struct { + ID string `json:"id,omitempty"` + Amount *PurchaseUnitAmount `json:"amount,omitempty"` + } + + // CapturedPayments has the amounts for a captured order + CapturedPayments struct { + Captures []CaptureAmount `json:"captures,omitempty"` + } + + // CapturedPurchaseUnit are purchase units for a captured order + CapturedPurchaseUnit struct { + Payments *CapturedPayments `json:"payments,omitempty"` + } + + // PayerWithNameAndPhone struct + PayerWithNameAndPhone struct { + Name *CreateOrderPayerName `json:"name,omitempty"` + EmailAddress string `json:"email_address,omitempty"` + Phone *PhoneWithType `json:"phone,omitempty"` + PayerID string `json:"payer_id,omitempty"` + } + + // CaptureOrderResponse is the response for capture order + CaptureOrderResponse struct { + ID string `json:"id,omitempty"` + Status string `json:"status,omitempty"` + Payer *PayerWithNameAndPhone `json:"payer,omitempty"` + PurchaseUnits []CapturedPurchaseUnit `json:"purchase_units,omitempty"` + } + + // Payer struct + Payer struct { + PaymentMethod string `json:"payment_method"` + FundingInstruments []FundingInstrument `json:"funding_instruments,omitempty"` + PayerInfo *PayerInfo `json:"payer_info,omitempty"` + Status string `json:"payer_status,omitempty"` + } + + // PayerInfo struct + PayerInfo struct { + Email string `json:"email,omitempty"` + FirstName string `json:"first_name,omitempty"` + LastName string `json:"last_name,omitempty"` + PayerID string `json:"payer_id,omitempty"` + Phone string `json:"phone,omitempty"` + ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"` + TaxIDType string `json:"tax_id_type,omitempty"` + TaxID string `json:"tax_id,omitempty"` + CountryCode string `json:"country_code"` + } + + // PaymentDefinition struct + PaymentDefinition struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Frequency string `json:"frequency,omitempty"` + FrequencyInterval string `json:"frequency_interval,omitempty"` + Amount AmountPayout `json:"amount,omitempty"` + Cycles string `json:"cycles,omitempty"` + ChargeModels []ChargeModel `json:"charge_models,omitempty"` + } + + // PaymentOptions struct + PaymentOptions struct { + AllowedPaymentMethod string `json:"allowed_payment_method,omitempty"` + } + + // PaymentPatch PATCH /v2/payments/payment/{payment_id) + PaymentPatch struct { + Operation string `json:"op"` + Path string `json:"path"` + Value interface{} `json:"value"` + } + + // PaymentPayer struct + PaymentPayer struct { + PaymentMethod string `json:"payment_method"` + Status string `json:"status,omitempty"` + PayerInfo *PayerInfo `json:"payer_info,omitempty"` + } + + // PaymentResponse structure + PaymentResponse struct { + ID string `json:"id"` + State string `json:"state"` + Intent string `json:"intent"` + Payer Payer `json:"payer"` + Transactions []Transaction `json:"transactions"` + Links []Link `json:"links"` + } + + // PaymentSource structure + PaymentSource struct { + Card *PaymentSourceCard `json:"card"` + Token *PaymentSourceToken `json:"token"` + } + + // PaymentSourceCard structure + PaymentSourceCard struct { + ID string `json:"id"` + Name string `json:"name"` + Number string `json:"number"` + Expiry string `json:"expiry"` + SecurityCode string `json:"security_code"` + LastDigits string `json:"last_digits"` + CardType string `json:"card_type"` + BillingAddress *CardBillingAddress `json:"billing_address"` + } + + // CardBillingAddress structure + CardBillingAddress struct { + AddressLine1 string `json:"address_line_1"` + AddressLine2 string `json:"address_line_2"` + AdminArea2 string `json:"admin_area_2"` + AdminArea1 string `json:"admin_area_1"` + PostalCode string `json:"postal_code"` + CountryCode string `json:"country_code"` + } + + // PaymentSourceToken structure + PaymentSourceToken struct { + ID string `json:"id"` + Type string `json:"type"` + } + + // Payout struct + Payout struct { + SenderBatchHeader *SenderBatchHeader `json:"sender_batch_header"` + Items []PayoutItem `json:"items"` + } + + // PayoutItem struct + PayoutItem struct { + RecipientType string `json:"recipient_type"` + Receiver string `json:"receiver"` + Amount *AmountPayout `json:"amount"` + Note string `json:"note,omitempty"` + SenderItemID string `json:"sender_item_id,omitempty"` + } + + // PayoutItemResponse struct + PayoutItemResponse struct { + PayoutItemID string `json:"payout_item_id"` + TransactionID string `json:"transaction_id"` + TransactionStatus string `json:"transaction_status"` + PayoutBatchID string `json:"payout_batch_id,omitempty"` + PayoutItemFee *AmountPayout `json:"payout_item_fee,omitempty"` + PayoutItem *PayoutItem `json:"payout_item"` + TimeProcessed *time.Time `json:"time_processed,omitempty"` + Links []Link `json:"links"` + Error ErrorResponse `json:"errors,omitempty"` + } + + // PayoutResponse struct + PayoutResponse struct { + BatchHeader *BatchHeader `json:"batch_header"` + Items []PayoutItemResponse `json:"items"` + Links []Link `json:"links"` + } + + // RedirectURLs struct + RedirectURLs struct { + ReturnURL string `json:"return_url,omitempty"` + CancelURL string `json:"cancel_url,omitempty"` + } + + // Refund struct + Refund struct { + ID string `json:"id,omitempty"` + Amount *Amount `json:"amount,omitempty"` + CreateTime *time.Time `json:"create_time,omitempty"` + State string `json:"state,omitempty"` + CaptureID string `json:"capture_id,omitempty"` + ParentPayment string `json:"parent_payment,omitempty"` + UpdateTime *time.Time `json:"update_time,omitempty"` + } + + // RefundResponse . + RefundResponse struct { + ID string `json:"id,omitempty"` + Amount *PurchaseUnitAmount `json:"amount,omitempty"` + Status string `json:"status,omitempty"` + } + + // Related struct + Related struct { + Sale *Sale `json:"sale,omitempty"` + Authorization *Authorization `json:"authorization,omitempty"` + Order *Order `json:"order,omitempty"` + Capture *Capture `json:"capture,omitempty"` + Refund *Refund `json:"refund,omitempty"` + } + + // Sale struct + Sale struct { + ID string `json:"id,omitempty"` + Amount *Amount `json:"amount,omitempty"` + TransactionFee *Currency `json:"transaction_fee,omitempty"` + Description string `json:"description,omitempty"` + CreateTime *time.Time `json:"create_time,omitempty"` + State string `json:"state,omitempty"` + ParentPayment string `json:"parent_payment,omitempty"` + UpdateTime *time.Time `json:"update_time,omitempty"` + PaymentMode string `json:"payment_mode,omitempty"` + PendingReason string `json:"pending_reason,omitempty"` + ReasonCode string `json:"reason_code,omitempty"` + ClearingTime string `json:"clearing_time,omitempty"` + ProtectionEligibility string `json:"protection_eligibility,omitempty"` + ProtectionEligibilityType string `json:"protection_eligibility_type,omitempty"` + Links []Link `json:"links,omitempty"` + } + + // SenderBatchHeader struct + SenderBatchHeader struct { + EmailSubject string `json:"email_subject"` + SenderBatchID string `json:"sender_batch_id,omitempty"` + } + + // ShippingAddress struct + ShippingAddress struct { + RecipientName string `json:"recipient_name,omitempty"` + Type string `json:"type,omitempty"` + Line1 string `json:"line1"` + Line2 string `json:"line2,omitempty"` + City string `json:"city"` + CountryCode string `json:"country_code"` + PostalCode string `json:"postal_code,omitempty"` + State string `json:"state,omitempty"` + Phone string `json:"phone,omitempty"` + } + + // ShippingDetailAddressPortable used with create orders + ShippingDetailAddressPortable struct { + AddressLine1 string `json:"address_line_1,omitempty"` + AddressLine2 string `json:"address_line_2,omitempty"` + AdminArea1 string `json:"admin_area_1,omitempty"` + AdminArea2 string `json:"admin_area_2,omitempty"` + PostalCode string `json:"postal_code,omitempty"` + CountryCode string `json:"country_code,omitempty"` + } + + // Name struct + Name struct { + FullName string `json:"full_name,omitempty"` + } + + // ShippingDetail struct + ShippingDetail struct { + Name *Name `json:"name,omitempty"` + Address *ShippingDetailAddressPortable `json:"address,omitempty"` + } + + expirationTime int64 + + // TokenResponse is for API response for the /oauth2/token endpoint + TokenResponse struct { + RefreshToken string `json:"refresh_token"` + Token string `json:"access_token"` + Type string `json:"token_type"` + ExpiresIn expirationTime `json:"expires_in"` + } + + // Transaction struct + Transaction struct { + Amount *Amount `json:"amount"` + Description string `json:"description,omitempty"` + ItemList *ItemList `json:"item_list,omitempty"` + InvoiceNumber string `json:"invoice_number,omitempty"` + Custom string `json:"custom,omitempty"` + SoftDescriptor string `json:"soft_descriptor,omitempty"` + RelatedResources []Related `json:"related_resources,omitempty"` + PaymentOptions *PaymentOptions `json:"payment_options,omitempty"` + NotifyURL string `json:"notify_url,omitempty"` + OrderURL string `json:"order_url,omitempty"` + Payee *Payee `json:"payee,omitempty"` + } + + //Payee struct + Payee struct { + Email string `json:"email"` + } + + // PayeeForOrders struct + PayeeForOrders struct { + EmailAddress string `json:"email_address,omitempty"` + MerchantID string `json:"merchant_id,omitempty"` + } + + // UserInfo struct + UserInfo struct { + ID string `json:"user_id"` + Name string `json:"name"` + GivenName string `json:"given_name"` + FamilyName string `json:"family_name"` + Email string `json:"email"` + Verified bool `json:"verified,omitempty,string"` + Gender string `json:"gender,omitempty"` + BirthDate string `json:"birthdate,omitempty"` + ZoneInfo string `json:"zoneinfo,omitempty"` + Locale string `json:"locale,omitempty"` + Phone string `json:"phone_number,omitempty"` + Address *Address `json:"address,omitempty"` + VerifiedAccount bool `json:"verified_account,omitempty,string"` + AccountType string `json:"account_type,omitempty"` + AgeRange string `json:"age_range,omitempty"` + PayerID string `json:"payer_id,omitempty"` + } + + // WebProfile represents the configuration of the payment web payment experience + // + // https://developer.paypal.com/docs/api/payment-experience/ + WebProfile struct { + ID string `json:"id,omitempty"` + Name string `json:"name"` + Presentation Presentation `json:"presentation,omitempty"` + InputFields InputFields `json:"input_fields,omitempty"` + FlowConfig FlowConfig `json:"flow_config,omitempty"` + } + + // Presentation represents the branding and locale that a customer sees on + // redirect payments + // + // https://developer.paypal.com/docs/api/payment-experience/#definition-presentation + Presentation struct { + BrandName string `json:"brand_name,omitempty"` + LogoImage string `json:"logo_image,omitempty"` + LocaleCode string `json:"locale_code,omitempty"` + } + + // InputFields represents the fields that are displayed to a customer on + // redirect payments + // + // https://developer.paypal.com/docs/api/payment-experience/#definition-input_fields + InputFields struct { + AllowNote bool `json:"allow_note,omitempty"` + NoShipping uint `json:"no_shipping,omitempty"` + AddressOverride uint `json:"address_override,omitempty"` + } + + // FlowConfig represents the general behaviour of redirect payment pages + // + // https://developer.paypal.com/docs/api/payment-experience/#definition-flow_config + FlowConfig struct { + LandingPageType string `json:"landing_page_type,omitempty"` + BankTXNPendingURL string `json:"bank_txn_pending_url,omitempty"` + UserAction string `json:"user_action,omitempty"` + } +) + +// Error method implementation for ErrorResponse struct +func (r *ErrorResponse) Error() string { + return fmt.Sprintf("%v %v: %d %s", r.Response.Request.Method, r.Response.Request.URL, r.Response.StatusCode, r.Message) +} + +// MarshalJSON for JSONTime +func (t JSONTime) MarshalJSON() ([]byte, error) { + stamp := fmt.Sprintf(`"%s"`, time.Time(t).UTC().Format(time.RFC3339)) + return []byte(stamp), nil +} + +func (e *expirationTime) UnmarshalJSON(b []byte) error { + var n json.Number + err := json.Unmarshal(b, &n) + if err != nil { + return err + } + i, err := n.Int64() + if err != nil { + return err + } + *e = expirationTime(i) + return nil +} diff --git a/model/response/response.go b/model/response/response.go new file mode 100644 index 0000000..bd4d43d --- /dev/null +++ b/model/response/response.go @@ -0,0 +1,86 @@ +package response + +import ( + "net/http" + "pure/utils" + + "github.com/gin-gonic/gin" +) + +type Response struct { + Code int `json:"code"` + Data interface{} `json:"data"` + Msg string `json:"msg"` +} + +const ( + ERROR = 7 //token过期 + API_ERROR = 1 //接口返回错误 + SUCCESS = 0 +) + +func Result(code int, data interface{}, msg string, c *gin.Context) { + // 开始时间 + c.JSON(http.StatusOK, Response{ + code, + data, + msg, + }) +} + +func Ok(c *gin.Context) { + Result(SUCCESS, map[string]interface{}{}, "操作成功", c) +} + +func OkWithMessage(message string, c *gin.Context) { + trs := utils.InterTranslate(message, "zh", "en") + if trs != "" { + message = trs + } + Result(SUCCESS, map[string]interface{}{}, message, c) +} + +func OkWithDataMessage(data interface{}, message string, c *gin.Context) { + trs := utils.InterTranslate(message, "zh", "en") + if trs != "" { + message = trs + } + Result(SUCCESS, data, message, c) +} + +func OkWithData(data interface{}, c *gin.Context) { + message := "操作成功" + trs := utils.InterTranslate(message, "zh", "en") + if trs != "" { + message = trs + } + Result(SUCCESS, data, message, c) +} + +func OkWithDetailed(data interface{}, message string, c *gin.Context) { + trs := utils.InterTranslate(message, "zh", "en") + if trs != "" { + message = trs + } + Result(SUCCESS, data, message, c) +} + +func Fail(c *gin.Context) { + Result(ERROR, map[string]interface{}{}, "操作失败", c) +} + +func FailWithMessage(message string, c *gin.Context) { + trs := utils.InterTranslate(message, "zh", "en") + if trs != "" { + message = trs + } + Result(API_ERROR, map[string]interface{}{}, message, c) +} + +func FailWithDetailed(data interface{}, message string, c *gin.Context) { + trs := utils.InterTranslate(message, "zh", "en") + if trs != "" { + message = trs + } + Result(ERROR, data, message, c) +} diff --git a/model/response/tripartite.go b/model/response/tripartite.go new file mode 100644 index 0000000..92f02d9 --- /dev/null +++ b/model/response/tripartite.go @@ -0,0 +1,26 @@ +package response + +type TripartiteGoogle struct { + ID string `json:"id"` + Sub string `json:"sub"` + Email string `json:"email"` + VerifiedEmail bool `json:"verified_email"` + Name string `json:"name"` + GivenName string `json:"given_name"` + FamilyName string `json:"family_name"` + Picture string `json:"picture"` + Locale string `json:"locale"` +} + +type TripartiteTwitter struct { + Data struct { + ID string `json:"id"` + Name string `json:"name"` + UserName string `json:"username"` + } `json:"data"` +} + +type TripartiteInstagram struct { + ID string `json:"id"` + Username string `json:"username"` +} diff --git a/model/response/user.go b/model/response/user.go new file mode 100755 index 0000000..16fec0e --- /dev/null +++ b/model/response/user.go @@ -0,0 +1,25 @@ +package response + +import "pure/model" + +type LoginResponse struct { + User model.User `json:"user"` + Token string `json:"token"` + ExpiresAt int64 `json:"expiresAt"` +} + +type TiktokResponse struct { + Data struct { + User model.TiktokUser `json:"user"` + } `json:"data"` + Error struct { + Code string `json:"code"` + Message string `json:"message"` + } `json:"error"` +} + +type UserStatistics struct { + CollectionMissionNum int64 `json:"collection_mission_num"` //收藏任务数量 + ClaimMissionNum int64 `json:"claim_mission_num"` //领取任务数量 + PlatformNum int64 `json:"platform_num"` //认证平台数量 +} diff --git a/model/seller_store.go b/model/seller_store.go new file mode 100644 index 0000000..d8e4e39 --- /dev/null +++ b/model/seller_store.go @@ -0,0 +1,26 @@ +package model + +import "pure/global" + +type SellerStore struct { //店铺 + StoreNo string `gorm:"unique;type:varchar(60);" json:"store_no"` //店铺编号 + Type int `gorm:"type:tinyint(1)" json:"type"` //1:个人店铺 + CreateBy string `gorm:"type:varchar(60);" json:"create_by"` //创建人 + Email string `gorm:"type:varchar(100);" json:"email"` //店铺联系email(注册账号email) + global.MG_MODEL +} + +type SellerStoreInfo struct { + StoreNo string `json:"store_no"` //店铺编号 + Type int `json:"type"` //1:个人店铺 + CreateBy string `json:"-"` // + Email string `json:"email"` //店铺联系email(注册账号email) +} + +func (SellerStore) TableName() string { + return "seller_store" +} + +func (SellerStoreInfo) TableName() string { + return "seller_store" +} diff --git a/model/sys_brochure.go b/model/sys_brochure.go new file mode 100644 index 0000000..2aa0021 --- /dev/null +++ b/model/sys_brochure.go @@ -0,0 +1,16 @@ +package model + +import "pure/global" + +type SysBrochure struct { //单页 协议、条款等 + global.BASE_ID + Title string `gorm:"size:10" json:"title"` //标题 + Type string `gorm:"size:30" json:"type"` //类型 + Content string `gorm:"type:mediumtext" json:"content"` //内容 + Src string `gorm:"size:500" json:"src"` //静态页面html + global.TIME_MODEL +} + +func (SysBrochure) TableName() string { + return "sys_brochure" +} diff --git a/model/sys_jwt_blacklist.go b/model/sys_jwt_blacklist.go new file mode 100755 index 0000000..a9391c6 --- /dev/null +++ b/model/sys_jwt_blacklist.go @@ -0,0 +1,8 @@ +package model + +import "pure/global" + +type JwtBlacklist struct { + Jwt string `gorm:"type:text;comment:jwt"` + global.MG_MODEL +} diff --git a/model/sys_mission_reward.go b/model/sys_mission_reward.go new file mode 100644 index 0000000..25da40f --- /dev/null +++ b/model/sys_mission_reward.go @@ -0,0 +1,28 @@ +package model + +import "pure/global" + +// 平台任务奖励 +type SysMissionReward struct { + global.MG_MODEL + Title string `json:"title" gorm:"size:255"` //标题 + Type int `json:"type" gorm:"tinyint(1) comment:奖励类型 1.视频上传 2.信息完善 3.商家任务"` //奖励类型 1.视频上传 2.信息完善 3.商家任务 + RelationId string `gorm:"size:64" json:"relationId"` //关联项目id + Bonus float64 `json:"bonus" gorm:"type:decimal(10,2)"` //奖励金额 + Status int `gorm:"type:int(1)" json:"status"` //状态 1待发放 2已发放 3已领取 + AchieveNum int64 `gorm:"type:int(11)" json:"achieve_num"` //已完成任务次数 + CreateBy string `gorm:"size:64" json:"create_by"` //创建人 + UpdateBy string `gorm:"size:64" json:"update_by"` //更新人 + AuditBy string `gorm:"size:64" json:"audit_by"` //审核人 +} + +type SysMissionBonus struct { + Total int64 `json:"total"` //奖励次数 + Bonus float64 `json:"bonus"` //奖金 + Type int `json:"type"` //奖励类型 1.视频上传 2.信息完善 3.商家任务 + AchieveNum int64 `json:"achieve_num"` //已完成任务次数 +} + +func (SysMissionReward) TableName() string { + return "sys_mission_reward" +} diff --git a/model/tag_relation.go b/model/tag_relation.go new file mode 100644 index 0000000..344615a --- /dev/null +++ b/model/tag_relation.go @@ -0,0 +1,26 @@ +package model + +import "pure/global" + +// 组件内容 +type TagRelation struct { + global.MG_MODEL + TagId uint `json:"tagId"` //组件id + RelationId string `gorm:"size:50" json:"relationId"` //关联项目id + RelationType string `gorm:"size:4" json:"relationType"` //项目类型 01-任务 02-任务视频 03-网红 + CreateBy string `gorm:"size:64" json:"createBy"` //创建人 + UpdateBy string `gorm:"size:64" json:"updateBy"` //更新人 +} + +type TagRelationDesc struct { + global.BASE_ID_STR + Name string `gorm:"size:20" json:"name"` //标签名称 +} + +func (TagRelation) TableName() string { + return "tag_relation" +} + +func (TagRelationDesc) TableName() string { + return "tag_relation" +} diff --git a/model/tags.go b/model/tags.go new file mode 100644 index 0000000..41beb98 --- /dev/null +++ b/model/tags.go @@ -0,0 +1,26 @@ +package model + +import ( + "pure/global" +) + +type Tags struct { //标签 + Value string `gorm:"size:100" json:"value"` //值 + CreateBy string `gorm:"size:64" json:"createBy"` //创建人 + UpdateBy string `gorm:"size:64" json:"updateBy"` //修改人 + Type string `gorm:"size:10; comment:类型" json:"type"` //标签类型 01-任务 02-任务视频 03-网红 + global.MG_MODEL +} + +type TagsDesc struct { + global.BASE_ID + Value string `gorm:"size:100" json:"value"` //值 +} + +func (Tags) TableName() string { + return "tags" +} + +func (TagsDesc) TableName() string { + return "tags" +} diff --git a/model/tb_attribute.go b/model/tb_attribute.go new file mode 100644 index 0000000..858e40c --- /dev/null +++ b/model/tb_attribute.go @@ -0,0 +1,41 @@ +package model + +import "pure/global" + +type TbAttribute struct { //属性表 + Name string `gorm:"type:varchar(255);not null;" json:"name"` //规格名称 + Status int `gorm:"type:tinyint(1);not null;comment:状态 1:正常" json:"status"` + global.MG_MODEL +} + +type TbAttributeView struct { + ID uint `json:"id"` + Name string `json:"name"` +} + +type TbAttributeDetail struct { + AttributeId uint `json:"attribute_id"` //规格属性id + Value string `json:"value"` // + ValueId uint `json:"value_id"` // +} + +type TbAttributeWithValues struct { + TbAttributeView + Values []TbAttributeValueItem `gorm:"-" json:"values"` +} + +func (TbAttribute) TableName() string { + return "tb_attribute" +} + +func (TbAttributeView) TableName() string { + return "tb_attribute" +} + +func (TbAttributeWithValues) TableName() string { + return "tb_attribute" +} + +func (TbAttributeDetail) TableName() string { + return "tb_attribute" +} diff --git a/model/tb_attribute_value.go b/model/tb_attribute_value.go new file mode 100644 index 0000000..96e8fa5 --- /dev/null +++ b/model/tb_attribute_value.go @@ -0,0 +1,25 @@ +package model + +import "pure/global" + +type TbAttributeValue struct { //规格属性取值 + AttributeId uint `gorm:"type:int(11);not null;" json:"attribute_id"` //attribute_id + Name string `gorm:"type:varchar(255);not null;" json:"name"` //属性取值 + Status int `gorm:"type:tinyint(1);comment:状态 1:正常" json:"status"` + global.MG_MODEL +} + +type TbAttributeValueItem struct { + Id uint `json:"id"` + Name string `json:"name"` //规格属性值 + Image string `json:"image"` //图片 +} + +type TbAttributeValueJson struct { + Str string `json:"str"` + Items []TbAttributeValueItem `json:"names"` +} + +func (TbAttributeValue) TableName() string { + return "tb_attribute_value" +} diff --git a/model/tb_category.go b/model/tb_category.go new file mode 100644 index 0000000..b34bb4c --- /dev/null +++ b/model/tb_category.go @@ -0,0 +1,15 @@ +package model + +import "pure/global" + +type TbCategory struct { //商品分类 + Name string `gorm:"type:varchar(100);not null;comment:商品分类名称" json:"name"` + Pid uint `gorm:"type:int(11);comment:父id" json:"pid"` //父id + IsLeaf bool `gorm:"type:tinyint(1)" json:"is_leaf"` //是否叶子分类 + Status int `gorm:"type:tinyint(1);comment:状态 1:正常" json:"status"` + global.MG_MODEL +} + +func (TbCategory) TableName() string { + return "tb_category" +} diff --git a/model/tb_goods.go b/model/tb_goods.go new file mode 100644 index 0000000..bb55984 --- /dev/null +++ b/model/tb_goods.go @@ -0,0 +1,103 @@ +package model + +import "pure/global" + +type TbGoodsBase struct { + SpuNo string `gorm:"unique;type:varchar(60);" json:"spu_no"` // 编号 + Title string `gorm:"type:mediumtext" json:"title"` // 名称 + TitleEng string `gorm:"type:mediumtext" json:"title_eng"` // 英文名称 + Cover string `gorm:"type:varchar(255);" json:"cover"` // 封面图 + Images string `gorm:"type:mediumtext;" json:"images"` // 图片 + Content string `gorm:"type:mediumtext;" json:"content"` // 详情 + ContentText string `gorm:"type:mediumtext;" json:"content_text"` // 详情-文字 + RetailPrice float64 `gorm:"type:decimal(10,2);" json:"retail_price"` // 吊牌价(零售指导价) + PriceMin float64 `gorm:"type:decimal(10,2);" json:"price_min"` // 最低规格价格 + PriceMax float64 `gorm:"type:decimal(10,2);" json:"price_max"` // 最高规格价格 + StoreNo string `gorm:"type:varchar(60);" json:"store_no"` // 店铺编号 +} + +type TbGoods struct { // spu + TbGoodsBase + CategoryId uint `gorm:"type:int(11);not null;" json:"category_id"` // 分类id + ListPrice float64 `gorm:"type:decimal(10,2);" json:"list_price"` // 列表价格 + AttributeList string `gorm:"type:text;" json:"attribute_list"` // 规格列表 + Stock int64 `gorm:"type:int(11);comment:总库存" json:"stock"` // 总库存 + Sales int64 `gorm:"type:int(11);comment:总销售量" json:"sales"` // 总销售量 + Views int64 `gorm:"size:11;comment:商品浏览量" json:"views"` // 商品浏览量 + Favourites int64 `gorm:"size:11;comment:商品喜欢量" json:"favourites"` // 商品喜欢量 + CollectionNum int64 `gorm:"type:int(11)" json:"collection_num"` // 收藏人数 + Tags string `gorm:"type:varchar(255);" json:"tags"` // 标签 + Online string `gorm:"type:ENUM('on','off');comment:商品上下架状态" json:"online" form:"online"` // 上下架状态 on/off + CreateBy string `gorm:"size:64" json:"create_by"` // 创建人 + // SaleStatus int `gorm:"type:tinyint(1);" json:"sale_status"` //销售状态 1:正常 2:已售罄 + global.MG_MODEL +} + +type TbGoodsView struct { + SpuNo string `json:"spu_no"` // 编号 + Title string `json:"title"` // 标题 + TitleEng string `json:"title_eng"` // 英文标题 + Cover string `json:"cover"` // + Images string `json:"images"` // 图片 + RetailPrice float64 `json:"retail_price"` // 吊牌价(零售指导价) + Tags string `json:"tags"` // 标签 + PriceMin float64 `json:"price_min"` // 最低规格价格 + PriceMax float64 `json:"price_max"` // 最高规格价格 + global.MG_MODEL +} + +type TbGoodsSpecsView struct { + SpuNo string `json:"spu_no"` // 编号 + Title string `json:"title"` // 标题 + TitleEng string `json:"title_eng"` // 英文标题 + Cover string `json:"cover"` // + Images string `json:"images"` // 图片 + RetailPrice float64 `json:"retail_price"` // 吊牌价(零售指导价) + Tags string `json:"tags"` // 标签 + PriceMin float64 `json:"price_min"` // 最低规格价格 + PriceMax float64 `json:"price_max"` // 最高规格价格 + Specs []TbGoodsSpecsDetail `gorm:"ForeignKey:GoodsId;AssociationForeignKey:ID" json:"specs"` // 规格 + Attributes []TbAttributeWithValues `gorm:"-" json:"attributes"` // 规格详情 + Stock int64 `gorm:"type:int(11);comment:总库存" json:"stock"` // 总库存 + Sales int64 `gorm:"type:int(11);comment:总销售量" json:"sales"` // 总销售量 + global.MG_MODEL +} + +type TbGoodsDetail struct { + CategoryId uint `json:"category_id"` // 分类id + SpuNo string `json:"spu_no"` // 编号 + Title string `json:"title"` // 标题 + TitleEng string `json:"title_eng"` // 英文标题 + Cover string `json:"cover"` // + Images string `json:"images"` // 图片 + Content string `json:"content"` // 商品详情 + ContentText string `json:"content_text"` // 详情-文字 + ListPrice float64 `json:"list_price"` // 列表价格 + RetailPrice float64 `json:"retail_price"` // 吊牌价(零售指导价) + PriceMin float64 `json:"price_min"` // 最低规格价格 + PriceMax float64 `json:"price_max"` // 最高规格价格 + Tags string `json:"tags"` // 标签 + Online string `json:"online"` // 上下架状态 on/off + Attributes []TbAttributeWithValues `gorm:"-" json:"attributes"` // 规格详情 + Specs []TbGoodsSpecsDetail `gorm:"ForeignKey:GoodsId;AssociationForeignKey:ID" json:"specs"` // 规格 + CollectStatus bool `gorm:"-" json:"collect_status"` // 收藏状态 true:已收藏 false:未收藏 + Breadcrumb []Breadcrumb `gorm:"-" json:"breadcrumb"` // 分类面包屑 + + global.MG_MODEL +} + +func (TbGoods) TableName() string { + return "tb_goods" +} + +func (TbGoodsView) TableName() string { + return "tb_goods" +} + +func (TbGoodsDetail) TableName() string { + return "tb_goods" +} + +func (TbGoodsSpecsView) TableName() string { + return "tb_goods" +} diff --git a/model/tb_goods_specs.go b/model/tb_goods_specs.go new file mode 100644 index 0000000..940d232 --- /dev/null +++ b/model/tb_goods_specs.go @@ -0,0 +1,42 @@ +package model + +import "pure/global" + +type TbGoodsSpecsBase struct { + GoodsId uint `gorm:"type:int(11)" json:"goods_id"` // spu id + SpuNo string `gorm:"type:varchar(60);" json:"spu_no"` // 商品编号 + SkuNo string `gorm:"type:varchar(60);" json:"sku_no"` // 商品规格编号 + Specs string `gorm:"type:text;" json:"specs"` // 规格 + Price float64 `gorm:"type:decimal(10,2);" json:"price"` // 价格 + Image string `gorm:"size:255" json:"image"` // 规格图片url + GoodsNo string `gorm:"size:255" json:"goods_no"` // 商品编号 + Code string `gorm:"size:100" json:"code"` // 商品规格属性值定位码 +} + +type TbGoodsSpecs struct { // sku + global.MG_MODEL + TbGoodsSpecsBase + Stock int64 `gorm:"type:int(11);" json:"stock"` // 库存 + Status int `gorm:"type:tinyint(1);comment:状态 1:正常" json:"status"` // 状态 +} + +type TbGoodsSpecsDetail struct { + global.MG_MODEL + GoodsId uint `json:"goods_id"` + Specs string `json:"specs"` // 规格 + Attributes []TbAttributeDetail `gorm:"-" json:"attributes"` // 规格详情 + SkuNo string `json:"sku_no"` // 商品编码 + Stock int64 `json:"stock"` // 库存 + Price float64 `json:"price"` // 价格 + Image string `json:"image"` // 规格图片url + GoodsNo string `json:"goods_no"` // 商品编号 + Code string `json:"code"` // +} + +func (TbGoodsSpecs) TableName() string { + return "tb_goods_specs" +} + +func (TbGoodsSpecsDetail) TableName() string { + return "tb_goods_specs" +} diff --git a/model/track.go b/model/track.go new file mode 100644 index 0000000..74376dc --- /dev/null +++ b/model/track.go @@ -0,0 +1,28 @@ +package model + +import ( + "encoding/json" + "pure/global" +) + +type Track struct { + global.Pure_MODEL + Value json.RawMessage `gorm:"type:json" json:"value"` + TrackingNumber string `gorm:"type:varchar(100)" json:"tracking_number"` + CourierCode string `gorm:"type:varchar(50)" json:"courier_code"` + RelationId string `gorm:"type:varchar(100)" json:"relation_id"` +} + +func (Track) TableName() string { + return "track" +} + +type TrackValue struct { + + CheckpointDate string `json:"checkpoint_date,omitempty"` + TrackingDetail string `json:"tracking_detail,omitempty"` + CheckpointDeliveryStatus string `json:"checkpoint_delivery_status"` + CheckpointDeliveryStatusV2 string `json:"checkpoint_delivery_status_v2,omitempty"` + CheckpointDeliverySubstatus string `json:"checkpoint_delivery_substatus"` + CheckpointDeliverySubstatusV2 string `json:"checkpoint_delivery_substatus_v2,omitempty"` +} diff --git a/model/track_webhook.go b/model/track_webhook.go new file mode 100644 index 0000000..6bdb9af --- /dev/null +++ b/model/track_webhook.go @@ -0,0 +1,12 @@ +package model + +import "pure/global" + +type TrackWebhook struct { + global.MG_MODEL + Value string `gorm:"type:text" json:"value"` +} + +func (TrackWebhook) TableName() string { + return "track_webhook" +} diff --git a/model/us_citys.go b/model/us_citys.go new file mode 100644 index 0000000..a6ad48a --- /dev/null +++ b/model/us_citys.go @@ -0,0 +1,12 @@ +package model + +type UsCitys struct { + ID int `json:"id"` + IDState int `json:"idState"` + City string `json:"city"` + County string `json:"county"` +} + +func (UsCitys) TableName() string { + return "us_citys" +} diff --git a/model/us_states.go b/model/us_states.go new file mode 100644 index 0000000..1fb68a5 --- /dev/null +++ b/model/us_states.go @@ -0,0 +1,18 @@ +package model + +type UsStates struct { + ID int `json:"id"` + StateCode string `json:"stateCode"` + StateName string `json:"stateName"` +} + +type UsSelect struct { + ID int `json:"id"` + StateCode string `json:"stateCode"` + StateName string `json:"stateName"` + Child []UsCitys `gorm:"-" json:"children"` +} + +func (UsStates) TableName() string { + return "us_states" +} diff --git a/model/user.go b/model/user.go new file mode 100755 index 0000000..fee0974 --- /dev/null +++ b/model/user.go @@ -0,0 +1,64 @@ +// 自动生成模板User +package model + +import ( + "pure/global" + "pure/model/request" + "time" + + uuid "github.com/satori/go.uuid" +) + +// 如果含有time.Time 请自行import time包 +type User struct { + global.MG_MODEL + UUID uuid.UUID `gorm:"unique;size:64" json:"uuid"` //用户uuid编码 + Username string `gorm:"size:128" json:"username"` //用户登录名 + NickName string `gorm:"size:20" json:"nick_name"` //昵称 + Avatar string `gorm:"size:255" json:"avatar"` //头像 + Platform string `gorm:"type:text" json:"platform"` //json格式的平台信息 + Appid string `json:"appid" form:"appid" gorm:"size:255"` //用户所属应用 + Organization string `json:"organization" form:"organization" gorm:"size:255"` //用户所属组织 + Type string `json:"type" form:"type" gorm:"size:255"` //用户类型(随用户所属而定) + Phone string `json:"phone" form:"phone" gorm:"size:255"` //用户手机号 + CountryCode string `json:"country_code" form:"country_code" gorm:"size:255"` //用户手机号国家代码 + Email string `json:"email" form:"email" gorm:"size:255"` //用户邮箱 + Password string `json:"password" form:"password" gorm:"size:255"` //用户密码 + PasswordSalt string `json:"password_salt" form:"password_salt" gorm:"size:255"` //用户密码盐 + Tags string `gorm:"type:text" json:"tags"` //个人标签 + Facebook string `gorm:"size:255" json:"facebook"` //facebook + Douyin string `gorm:"size:255" json:"douyin"` //抖音 + Tiktok string `gorm:"size:255" json:"tiktok"` //tiktok + Instagram string `gorm:"size:255" json:"instagram"` //instagram + Twitter string `gorm:"size:255" json:"twitter"` //twitter + Google string `gorm:"size:255" json:"google"` //google + Youtube string `gorm:"size:255" json:"youtube"` //youtube + Ios string `gorm:"size:255" json:"ios"` //ios + IsAuth bool `gorm:"default:0" json:"is_auth"` //是否认证 0未认证 1已认证 + IDForbidden bool `json:"id_forbidden"` //是否禁用 + ForbiddenTime *time.Time `json:"forbidden_time"` //禁用时间 + ForbiddenReason string `json:"forbidden_reason"` //禁用原因 + ForbiddenOperation string `json:"forbidden_operation"` //禁用操作人 + Jwt string `gorm:"type:text" json:"jwt"` //最后登录jwt + Source string `json:"source" gorm:"size:255"` //用户来源 + LogOffTime *time.Time `json:"log_off_time"` //注销时间 +} + +type UserSimple struct { + UUID uuid.UUID `json:"uuid"` //用户uuid编码 + NickName string `json:"nick_name"` //昵称 + Avatar string `json:"avatar"` //头像 + Phone string `json:"phone"` // 手机号 + Platform string `json:"-"` //json格式的平台信息 + Tags string `json:"tags"` //个人标签 + Email string `json:"email"` //用户邮箱 + Platforms []request.Platform `gorm:"-" json:"platform"` //平台 +} + +func (User) TableName() string { + return "user" +} + +func (UserSimple) TableName() string { + return "user" +} diff --git a/model/version.go b/model/version.go new file mode 100644 index 0000000..6a86faa --- /dev/null +++ b/model/version.go @@ -0,0 +1,32 @@ +package model + +import "pure/global" + +type Version struct { // 版本号 + global.MG_MODEL + Version string `gorm:"size:20" json:"version"` // 版本号 1.0.0.11 + Code int64 `gorm:"type:int(11)" json:"code"` // 版本编号 + Type int `gorm:"type:int(1)" json:"type"` // 1:ios 2:android 3:h5 + Info string `gorm:"type:text" json:"info"` // 版本更新描述 + IsForce bool `gorm:"type:tinyint(1)" json:"is_force"` // 是否强制更新 true:是 + Tip bool `gorm:"type:tinyint(1);default:1" json:"tip"` // 是否提示升级 true=是 + Url string `gorm:"size:255" json:"url"` // 下载地址 + MD5 string `gorm:"size:64" json:"md5"` // 文件md5 + Status int `gorm:"type:int(1)" json:"status"` // 状态 0:未上线 1:已上线 2:审核中 +} + +type VersionV struct { + Version string `json:"version"` // 版本号 + Code int64 `json:"code"` // 版本编号 + Info string `json:"info"` // 版本更新描述 + IsForce bool `json:"is_force"` // 是否强制更新 true:是 + Url string `json:"url"` // apk下载地址 + MD5 string `json:"md5"` // apk文件md5 + Tip bool `json:"tip"` // 是否提示升级 true=是 + Status int `json:"-"` // 1:已上线 2:审核中 + HideAndSeek bool `json:"hide_and_seek"` // +} + +func (Version) TableName() string { + return "version" +} diff --git a/model/wallet.go b/model/wallet.go new file mode 100644 index 0000000..19ab6d9 --- /dev/null +++ b/model/wallet.go @@ -0,0 +1,18 @@ +package model + +import "pure/global" + +type Wallet struct { + global.MG_MODEL + UserID string `gorm:"size:50" json:"userId"` + Balance float64 `gorm:"type:decimal(10,2)" json:"balance"` //可用余额 + TransitBalance float64 `gorm:"type:decimal(10,2)" json:"transitBalance"` //在途余额 + Fund float64 `gorm:"type:decimal(10,2)" json:"-"` // 营销账户 + FundLock float64 `gorm:"type:decimal(10,2)" json:"-"` // 营销账户-锁定金额 + Platform string `gorm:"size:50" json:"platform"` //平台 saller(买家端) / customer(客户端) / influencer(网红端) + State int `gorm:"type:tinyint(1)" json:"state"` // 状态 0:正常 1:限制提现 2:禁止提现 +} + +func (Wallet) TableName() string { + return "wallet" +} diff --git a/model/webhook.go b/model/webhook.go new file mode 100644 index 0000000..97f5b97 --- /dev/null +++ b/model/webhook.go @@ -0,0 +1,12 @@ +package model + +import "pure/global" + +type PaypalWebhook struct { + global.MG_MODEL + Value string `gorm:"type:text" json:"value"` +} + +func (PaypalWebhook) TableName() string { + return "paypal_webhook" +} diff --git a/model/withdrawal.go b/model/withdrawal.go new file mode 100644 index 0000000..138b918 --- /dev/null +++ b/model/withdrawal.go @@ -0,0 +1,32 @@ +package model + +import ( + "pure/global" + "time" +) + +type Withdrawal struct { // 提现记录 + global.MG_MODEL + Platform string `gorm:"size:10" json:"platform"` // 平台 1:网红 2:商家 + WalletType int `gorm:"type:tinyint(1)" json:"wallet_type"` // 钱包类型 1:余额钱包 2:营销账户钱包 + FlowNo string `gorm:"size:50;unique" json:"flow_no"` // 流水号 + BillNo string `gorm:"size:50" json:"bill_no"` // 账单号 + Title string `gorm:"size:255" json:"title"` // 标题 + AccountType int `gorm:"type:int(1)" json:"account_type"` // 账户类型 1:paypal 2:银行卡 + BankCard + CreateBy string `gorm:"size:50" json:"create_by"` // 创建人/店铺 + Amount float64 `gorm:"type:decimal(10,2)" json:"amount"` // 金额 + CheckStatus string `gorm:"size:1" json:"check_status"` // 审核状态 0:待审核 1:审核通过 2:审核未通过 + CheckTime *time.Time `gorm:"" json:"check_time"` // 审核时间 + PayId string `gorm:"size:50" json:"pay_id"` // 支付id + Status string `gorm:"size:1" json:"status"` // 提现状态 0:进行中 1:成功 2:失败 + Remark string `gorm:"size:255" json:"remark"` // 备注 +} + +type WithdrawalView struct { + FlowNo string `json:"flow_no"` // 流水号 +} + +func (Withdrawal) TableName() string { + return "withdrawal" +} diff --git a/openapi.yaml b/openapi.yaml new file mode 100644 index 0000000..f8f3735 --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,10 @@ +# Generated with protoc-gen-openapi +# https://github.com/google/gnostic/tree/master/cmd/protoc-gen-openapi + +openapi: 3.0.3 +info: + title: "" + version: 0.0.1 +paths: {} +components: + schemas: {} diff --git a/packfile/notUsePackFile.go b/packfile/notUsePackFile.go new file mode 100644 index 0000000..e54aad3 --- /dev/null +++ b/packfile/notUsePackFile.go @@ -0,0 +1,3 @@ +// +build !packfile + +package packfile diff --git a/packfile/usePackFile.go b/packfile/usePackFile.go new file mode 100644 index 0000000..055f03d --- /dev/null +++ b/packfile/usePackFile.go @@ -0,0 +1,45 @@ +// +build packfile + +package packfile + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" +) + +//go:generate go-bindata -o=staticFile.go -pkg=packfile -tags=packfile ../resource/... ../config.yaml + +func writeFile(path string, data []byte) { + // 如果文件夹不存在,预先创建文件夹 + if lastSeparator := strings.LastIndex(path, "/"); lastSeparator != -1 { + dirPath := path[:lastSeparator] + if _, err := os.Stat(dirPath); err != nil && os.IsNotExist(err) { + os.MkdirAll(dirPath, os.ModePerm) + } + } + + // 已存在的文件,不应该覆盖重写,可能在前端更改了配置文件等 + if _, err := os.Stat(path); os.IsNotExist(err) { + if err2 := ioutil.WriteFile(path, data, os.ModePerm); err2 != nil { + fmt.Printf("Write file failed: %s\n", path) + } + } else { + fmt.Printf("File exist, skip: %s\n", path) + } +} + +func init() { + for key := range _bindata { + filePath, _ := filepath.Abs(strings.TrimPrefix(key, ".")) + data, err := Asset(key) + if err != nil { + // Asset was not found. + fmt.Printf("Fail to find: %s\n", filePath) + } else { + writeFile(filePath, data) + } + } +} diff --git a/resource/gorm_settings.yaml b/resource/gorm_settings.yaml new file mode 100644 index 0000000..329cb43 --- /dev/null +++ b/resource/gorm_settings.yaml @@ -0,0 +1,25 @@ +gorm: + settings: + - dsn-name: dsn1 + bind-tables: + - authority_menu + - casbin_rule + - exa_customers + - exa_file_chunks + - exa_file_upload_and_downloads + - exa_files + - exa_simple_uploaders + - jwt_blacklists + - sys_apis + - sys_authorities + - sys_authority_menus + - sys_base_menu_parameters + - sys_base_menus + - sys_data_authority_id + - sys_dictionaries + - sys_dictionary_details + - sys_operation_records + - sys_users + - dsn-name: dsn2 + bind-tables: + - bs_channel diff --git a/resource/rbac_model.conf b/resource/rbac_model.conf new file mode 100644 index 0000000..04ebedf --- /dev/null +++ b/resource/rbac_model.conf @@ -0,0 +1,14 @@ +[request_definition] +r = sub, obj, act + +[policy_definition] +p = sub, obj, act + +[role_definition] +g = _, _ + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = r.sub == p.sub && ParamsMatch(r.obj,p.obj) && r.act == p.act diff --git a/router/global/dict.go b/router/global/dict.go new file mode 100644 index 0000000..42a6ee3 --- /dev/null +++ b/router/global/dict.go @@ -0,0 +1,13 @@ +package global + +import ( + "github.com/gin-gonic/gin" + "pure/api/global" +) + +func InitDictRouter(Router *gin.RouterGroup) { + DictRouter := Router.Group("/dict") + { + DictRouter.GET("getDictDataList", global.GetSysDictDataList) + } +} diff --git a/router/global/global.go b/router/global/global.go new file mode 100644 index 0000000..ed5ddb4 --- /dev/null +++ b/router/global/global.go @@ -0,0 +1,19 @@ +package global + +import ( + "pure/api/global" + + "github.com/gin-gonic/gin" +) + +func InitGlobalRouter(Router *gin.RouterGroup) { + InOtherRouter := Router.Group("global") + { + InOtherRouter.GET("address", global.GetAddressList) //获取收货地址 + InOtherRouter.POST("address", global.AddAddress) //添加收货地址 + InOtherRouter.PUT("address", global.UpdateAddress) //修改收货地址 + InOtherRouter.DELETE("address", global.DeleteAddress) //删除收货地址 + InOtherRouter.GET("usSelect", global.GetUsSelect) //美国地区选择器 + InOtherRouter.GET("track", global.GetTrack) //美国地区选择器 + } +} diff --git a/router/influencer/base.go b/router/influencer/base.go new file mode 100644 index 0000000..fc56f75 --- /dev/null +++ b/router/influencer/base.go @@ -0,0 +1,25 @@ +package influencer + +import ( + "pure/api/influencer" + "pure/api/sys" + + "github.com/gin-gonic/gin" +) + +func InitInfluencerOtherRouter(Router *gin.RouterGroup) { + WithoutLoginRouter := Router.Group("") + WithoutLoginRouter.GET("mission/recommend-list", influencer.GetRecommendMissionList) //首页推荐任务列表 + + InOtherRouter := Router.Group("base") + { + InOtherRouter.POST("login", influencer.LoginInfluencer) //登录 + InOtherRouter.POST("register", influencer.Register) //注册 + InOtherRouter.POST("sendMessage", influencer.SendMessage) //发送短信验证码 + InOtherRouter.POST("sendEmail", influencer.SendEmail) //发送邮箱验证码 + InOtherRouter.POST("authorized", influencer.Authorized) //授权登录 + InOtherRouter.GET("brochure", sys.GetSysBrochure) //隐私协议单页 + InOtherRouter.GET("chain", influencer.GetChainInfo) // 获取区块链信息 + InOtherRouter.GET("version", sys.GetVersion) // 获取版本信息 + } +} diff --git a/router/influencer/goods.go b/router/influencer/goods.go new file mode 100644 index 0000000..561ae6f --- /dev/null +++ b/router/influencer/goods.go @@ -0,0 +1,13 @@ +package influencer + +import ( + "github.com/gin-gonic/gin" + "pure/api/influencer" +) + +func InitInfluencerGoodsRouter(Router *gin.RouterGroup) { + InRouter := Router.Group("goods") + { + InRouter.GET("detail", influencer.GetTbGoodsDetail) //商品详情 + } +} diff --git a/router/influencer/mission.go b/router/influencer/mission.go new file mode 100644 index 0000000..5b36aa0 --- /dev/null +++ b/router/influencer/mission.go @@ -0,0 +1,36 @@ +package influencer + +import ( + "pure/api/influencer" + + "github.com/gin-gonic/gin" +) + +func InitInfluencerMissionRouter(Router *gin.RouterGroup) { + InRouter := Router.Group("mission") + { + InRouter.GET("detail", influencer.GetMissionDetail) //任务详情 + InRouter.GET("list", influencer.GetMissionList) //任务列表 + InRouter.GET("claim", influencer.GetMissionClaim) //领取任务详情 + InRouter.GET("claim-list", influencer.GetMissionClaimList) //领取任务列表 + InRouter.POST("claim", influencer.ClaimMission) //领取任务 + InRouter.GET("collect-list", influencer.GetCollectionMissionList) //收藏任务列表 + InRouter.POST("collect", influencer.CollectMission) //收藏任务 + InRouter.POST("submit-works", influencer.SubmitClaimMissionWorks) //领取任务的提交作品 + InRouter.GET("bonus", influencer.GetMissionBonus) //任务累计奖金 + InRouter.POST("submit-video", influencer.SubmitClaimMissionVideo) //固定费用任务上传视频 + InRouter.GET("recommend-detail", influencer.GetRecommendMissionDetail) //首页推荐任务详情 + //InRouter.GET("recommend-list", influencer.GetRecommendMissionList) //首页推荐任务列表 + InRouter.GET("sys-reward-list", influencer.GetSysRewardList) //获取平台奖励列表 + InRouter.GET("sys-reward-summary", influencer.GetSysRewardSummary) //获取平台奖励汇总 + + InRouter.GET("order-data", influencer.GetMissionOrderStatistic) // 获取任务下订单统计数据 + } +} + +func InitBanner(Router *gin.RouterGroup) { + bannerRouter := Router.Group("banner") + { + bannerRouter.GET("list", influencer.GetBannerList) // banner列表 + } +} diff --git a/router/influencer/order.go b/router/influencer/order.go new file mode 100644 index 0000000..51c9619 --- /dev/null +++ b/router/influencer/order.go @@ -0,0 +1,18 @@ +package influencer + +import ( + "pure/api/influencer" + + "github.com/gin-gonic/gin" +) + +func InitInfluencerOrderRouter(Router *gin.RouterGroup) { + InRouter := Router.Group("order") + { + InRouter.GET("data", influencer.GetOrderData) // 数据 + InRouter.GET("detail", influencer.GetOrderDetail) // 详情 + InRouter.GET("goods/snapshot", influencer.GetOrderGoodsInfo) // 获取商品快照信息 + InRouter.GET("list", influencer.GetUserOrderList) // 列表 + InRouter.GET("total", influencer.GetOrderTotalList) // 订单统计 + } +} diff --git a/router/influencer/user.go b/router/influencer/user.go new file mode 100644 index 0000000..ad832d1 --- /dev/null +++ b/router/influencer/user.go @@ -0,0 +1,19 @@ +package influencer + +import ( + "pure/api/influencer" + + "github.com/gin-gonic/gin" +) + +func InitInfluencerUserRouter(Router *gin.RouterGroup) { + InRouter := Router.Group("user") + { + InRouter.GET("detail", influencer.GetUserDetail) //个人基本信息 + InRouter.PUT("detail", influencer.UpdateUserDetail) //修改基本信息 + InRouter.POST("bandPhone", influencer.BandPhone) //绑定手机号 + InRouter.POST("platformAuth", influencer.PlatformAuth) //平台认证 + InRouter.GET("statistics", influencer.GetUserStatistics) //个人基本信息 + InRouter.POST("logoff", influencer.UserLogOff) //注销账户 + } +} diff --git a/router/influencer/wallet.go b/router/influencer/wallet.go new file mode 100644 index 0000000..09bb6e0 --- /dev/null +++ b/router/influencer/wallet.go @@ -0,0 +1,28 @@ +package influencer + +import ( + "pure/api/influencer" + + "github.com/gin-gonic/gin" +) + +func InitInfluencerWalletRouter(Router *gin.RouterGroup) { + InRouter := Router.Group("wallet") + { + InRouter.GET("detail", influencer.GetUserWalletDetail) //账户信息 + InRouter.GET("accountList", influencer.GetUserAccountList) //提现账户列表 + //InRouter.GET("account") //提现账户详情 + InRouter.GET("bill/data", influencer.GetUserBillData) // 对账中心数据 + + InRouter.PUT("detail") //修改账户信息 + InRouter.POST("account", influencer.AddUserAccount) //提现账户添加(需验证码) + InRouter.PUT("account/default", influencer.UpdateAccountIsDefault) // 设置默认账户 + InRouter.DELETE("account", influencer.DeleteUserAccount) //提现账户删除(需验证码) + + InRouter.GET("bill-list", influencer.GetBillList) // 获取账单列表 + InRouter.GET("bill-notify", influencer.GetBillNotifyList) // 获取账单通知列表 + InRouter.GET("withdrawal", influencer.GetWithdrawal) // 获取提现详情 + InRouter.GET("withdrawal-list", influencer.GetWithdrawalList) // 获取提现列表 + InRouter.POST("withdrawal", influencer.UserWithdrawal) // 提交提现申请 + } +} diff --git a/service/address.go b/service/address.go new file mode 100644 index 0000000..4ef30c7 --- /dev/null +++ b/service/address.go @@ -0,0 +1,181 @@ +package service + +import ( + "encoding/json" + "errors" + + "pure/global" + "pure/model" + "pure/model/request" + "pure/model/response" +) + +func GetUserAddressList(userID string, info *request.ReqAddress) (error, any) { + var ( + err error + list []model.Address + ) + db := global.MG_DB.Model(&model.Address{}).Where("user_id=?", userID) + if info.ID != 0 { + db = db.Where("id=?", info.ID) + } + err = db.Find(&list).Error + if err != nil { + return errors.New("获取收货地址失败"), nil + } + return nil, list +} + +func AddUserAddressList(userID string, data *model.Address) error { + var ( + err error + ) + data.UserID = userID + if data.FirstName == "" || data.LastName == "" || data.Bldg == "" || data.City == "" || data.Street == "" || data.State == "" || data.ZipCode == "" { + return errors.New("有必填项未填写") + } + if len(data.FirstName) > 255 { + return errors.New("FirstName长度超出限制") + } + if len(data.LastName) > 255 { + return errors.New("LastName长度超出限制") + } + if len(data.Street) > 255 { + return errors.New("Street长度超出限制") + } + if len(data.Bldg) > 255 { + return errors.New("Bldg长度超出限制") + } + if len(data.City) > 255 { + return errors.New("City长度超出限制") + } + if len(data.State) > 255 { + return errors.New("State长度超出限制") + } + if len(data.ZipCode) > 255 { + return errors.New("ZipCode长度超出限制") + } + if len(data.Phone) > 20 { + return errors.New("Phone长度超出限制") + } + if data.Default == 1 { + global.MG_DB.Model(&model.Address{}).Where("user_id=?", userID).Update("default", 2) + } + err = global.MG_DB.Model(&model.Address{}).Create(data).Error + if err != nil { + return errors.New("添加收货地址失败") + } + return nil +} + +func UpdateAddress(userID string, data *model.Address) error { + var ( + err error + ) + if data.FirstName == "" || data.LastName == "" || data.Bldg == "" || data.City == "" || data.Street == "" || data.State == "" || data.ZipCode == "" { + return errors.New("有必填项未填写") + } + if len(data.FirstName) > 255 { + return errors.New("FirstName长度超出限制") + } + if len(data.LastName) > 255 { + return errors.New("LastName长度超出限制") + } + if len(data.Street) > 255 { + return errors.New("Street长度超出限制") + } + if len(data.Bldg) > 255 { + return errors.New("Bldg长度超出限制") + } + if len(data.City) > 255 { + return errors.New("City长度超出限制") + } + if len(data.State) > 255 { + return errors.New("State长度超出限制") + } + if len(data.ZipCode) > 255 { + return errors.New("ZipCode长度超出限制") + } + if len(data.Phone) > 20 { + return errors.New("Phone长度超出限制") + } + data.UserID = userID + if data.Default == 1 { + global.MG_DB.Model(&model.Address{}).Where("user_id=?", userID).Update("default", 2) + } + err = global.MG_DB.Model(&model.Address{}).Where("user_id=? and id=?", userID, data.ID).Updates(data).Error + if err != nil { + return errors.New("修改收货地址失败") + } + return nil +} + +func DeleteAddress(userID string, ID *global.BASE_ID) error { + var ( + err error + ) + err = global.MG_DB.Model(&model.Address{}).Where("user_id=? and id=?", userID, ID.ID).Delete(&model.Address{}).Error + if err != nil { + return errors.New("删除收货地址失败") + } + return nil +} + +func GetUsSelect() (error, any) { + var ( + err error + list []model.UsSelect + data []model.UsCitys + ) + err = global.MG_DB.Model(&model.UsStates{}).Find(&list).Error + if err != nil { + return errors.New("获取地址失败"), nil + } + err = global.MG_DB.Model(&model.UsCitys{}).Find(&data).Error + if err != nil { + return errors.New("获取地址失败"), nil + } + for v := range list { + for x := range data { + if data[x].IDState == list[v].ID { + list[v].Child = append(list[v].Child, data[x]) + } + } + } + return nil, list +} + +func GetTrack(trackId int64) ([]response.TrackItem, error) { + var list []response.TrackItem + var values []model.TrackValue + var track model.Track + err := global.MG_DB.Model(&model.Track{}).Where("id=?", trackId).First(&track).Error + if err != nil { + return list, err + } + err = json.Unmarshal([]byte(track.Value), &values) + if err != nil { + return list, err + } + for _, v := range values { + list = append(list, response.TrackItem{ + CheckpointDate: v.CheckpointDate, + DeliveryStatus: v.CheckpointDeliveryStatus, + TrackingDetail: v.TrackingDetail, + DeliveryStatusCn: toDeliveryStatus(v.CheckpointDeliveryStatus), + }) + } + return list, nil +} + +func toDeliveryStatus(status string) string { + switch status { + case "transit": + return "运输途中" + case "pickup": + return "到达待取" + case "delivered": + return "已签收" + } + return "" +} diff --git a/service/banner.go b/service/banner.go new file mode 100644 index 0000000..2650eb1 --- /dev/null +++ b/service/banner.go @@ -0,0 +1,41 @@ +package service + +import ( + "pure/global" + "pure/model" + "pure/model/response" +) + +func GetBannerList() (err error, list []response.BannerListResponse, total int64) { + + db := global.MG_DB.Model(&model.Banner{}) + + err = db.Count(&total).Error + var res []model.Banner + + err = db.Select("id,title,cover_url,relation_id,relation_type,link_type,link,type,status,sort"). + Where("status = ?", "1"). + Order("sort DESC").Find(&res).Error + + if err != nil { + return err, nil, 0 + } + for i := 0; i < len(res); i++ { + //精简字段赋值 + vRes := response.BannerListResponse{ + RelationId: res[i].RelationId, + RelationType: res[i].RelationType, + Title: res[i].Title, + CoverUrl: res[i].CoverUrl, + LinkType: res[i].LinkType, + Link: res[i].Link, + Type: res[i].Type, + Status: res[i].Status, + } + vRes.ID = res[i].ID + vRes.SortIndex = i + 1 + list = append(list, vRes) + } + + return err, list, total +} diff --git a/service/bill.go b/service/bill.go new file mode 100644 index 0000000..dc53c5b --- /dev/null +++ b/service/bill.go @@ -0,0 +1,157 @@ +package service + +import ( + "errors" + "pure/dto" + "pure/global" + "pure/model" + "pure/model/request" + "pure/utils" + "time" +) + +func GetBillData(userId string, info *request.GetBillDataParams) (dto.BillData, error) { + var ( + err error + result dto.BillData + ) + now := time.Now() + switch info.Uint { + case "1": //累计 + var statistic model.DtStatisticOrder + statistic, err = getStatisticsOrderInfluence(userId, "", nil) + if err != nil { + return result, err + } + result.Income = statistic.SettleReward + result.OrderMoney = statistic.OrderMoney + result.OrderNum = statistic.OrderNum + result.CancelOrderNum = statistic.OrderCancelNum + result.CancelOrderMoney = statistic.OrderCancelMoney + _, result.RewardUnfinished = getMissionClaimRewardUnfinished(userId) + + result.FlowIncome, result.FlowExpend, err = getBillFlowData(userId, &request.SearchBillParams{Uint: "1"}) + case "2": + var ( + timeArea = make([]string, 2) + statistic model.DtStatisticOrder + ) + timeArea[0] = now.AddDate(0, 0, -1).Format(utils.DateFormat) + timeArea[1] = now.Format(utils.DateFormat) + statistic, err = getStatisticsOrderInfluence(userId, "", timeArea) + if err != nil { + return result, err + } + result.Income = statistic.SettleReward + result.OrderMoney = statistic.OrderMoney + result.OrderNum = statistic.OrderNum + result.CancelOrderNum = statistic.OrderCancelNum + result.CancelOrderMoney = statistic.OrderCancelMoney + + result.FlowIncome, result.FlowExpend, err = getBillFlowData(userId, &request.SearchBillParams{Uint: "2"}) + case "3": + var ( + timeArea = make([]string, 2) + statistic model.DtStatisticOrder + ) + timeArea[0] = now.AddDate(0, 0, -29).Format(utils.DateFormat) + timeArea[1] = now.AddDate(0, 0, 1).Format(utils.DateFormat) + statistic, err = getStatisticsOrderInfluence(userId, "", timeArea) + if err != nil { + return result, err + } + result.Income = statistic.SettleReward + result.OrderMoney = statistic.OrderMoney + result.OrderNum = statistic.OrderNum + result.CancelOrderNum = statistic.OrderCancelNum + result.CancelOrderMoney = statistic.OrderCancelMoney + result.FlowIncome, result.FlowExpend, err = getBillFlowData(userId, &request.SearchBillParams{Uint: "3"}) + default: + return dto.BillData{}, errors.New("uint取值有误") + } + return result, err +} + +func getBillData(userId string, info *request.SearchBillParams) (float64, error) { + var ( + err error + result float64 + ) + db := global.MG_DB.Model(&model.Bill{}).Where("user_id = ?", userId) + now := time.Now() + switch info.Uint { + case "2": // 昨天 + db = db.Where("created_at >= ? AND created_at < ?", now.AddDate(0, 0, -1).Format(utils.DateFormat), now.Format(utils.DateFormat)) + case "3": // 30天 + db = db.Where("created_at >= ? AND created_at < ?", now.AddDate(0, 0, -29).Format(utils.DateFormat), now.AddDate(0, 0, 1).Format(utils.DateFormat)) + } + if info.Status != "" { + db = db.Where("`status` = ?", info.Status) + } + err = db.Select("SUM(price) as price").Scan(&result).Error + if err != nil { + return 0, err + } + return result, nil +} + +func getBillFlowData(userId string, info *request.SearchBillParams) (income float64, expend float64, err error) { + var list []model.BillFlowData + db := global.MG_DB.Model(&model.Bill{}).Where("user_id = ?", userId) + now := time.Now() + switch info.Uint { + case "2": // 昨天 + db = db.Where("created_at >= ? AND created_at < ?", now.AddDate(0, 0, -1).Format(utils.DateFormat), now.Format(utils.DateFormat)) + case "3": // 30天 + db = db.Where("created_at >= ? AND created_at < ?", now.AddDate(0, 0, -29).Format(utils.DateFormat), now.AddDate(0, 0, 1).Format(utils.DateFormat)) + } + if info.Status != "" { + db = db.Where("`status` = ?", info.Status) + } + err = db.Select("`status`,SUM(price) as price").Group("`status`").Find(&list).Error + if err != nil { + return 0, 0, err + } + for _, data := range list { + if data.Status == 1 { + expend = data.Price + } else { + income = data.Price + } + } + return +} + +func GetBillList(userId string, info *request.SearchBillParams) ([]model.Bill, error) { + var ( + err error + result []model.Bill + ) + limit := info.PageSize + offset := info.PageSize * (info.Page - 1) + db := global.MG_DB.Model(&model.Bill{}).Where("user_id = ?", userId) + now := time.Now() + switch info.Uint { + case "2": // 昨天 + db = db.Where("created_at >= ? AND created_at < ?", now.AddDate(0, 0, -1).Format(utils.DateFormat), now.Format(utils.DateFormat)) + case "3": // 30天 + db = db.Where("created_at >= ? AND created_at < ?", now.AddDate(0, 0, -29).Format(utils.DateFormat), now.AddDate(0, 0, 1).Format(utils.DateFormat)) + } + if info.Status != "" { + db = db.Where("`status` = ?", info.Status) + } + err = db.Order("id DESC").Offset(offset).Limit(limit).Find(&result).Error + if err != nil { + return nil, err + } + return result, nil +} + +func getBillView(orderId string) (model.BillView, error) { + var ( + err error + result model.BillView + ) + err = global.MG_DB.Model(&model.Bill{}).Where("order_id = ?", orderId).Select("id,order_id,transaction_id").First(&result).Error + return result, err +} diff --git a/service/chain.go b/service/chain.go new file mode 100644 index 0000000..1f7cf9c --- /dev/null +++ b/service/chain.go @@ -0,0 +1,28 @@ +package service + +import ( + "math/rand" + "pure/model/response" + "pure/utils" + "time" +) + +func GetChainInfo(address string) (error, []response.ChainResp) { + var ( + err error + result []response.ChainResp + ) + now := time.Now() + r := rand.New(rand.NewSource(time.Now().UnixNano())) + for i := 0; i < 3; i++ { + intn := r.Intn(1000) + tmp := response.ChainResp{ + Time: &now, + BlockHeight: 28741283 + int64(intn), + BlockAddress: utils.GetInvitationLowerLen(64), + Hash: utils.GetInvitationLowerLen(64), + } + result = append(result, tmp) + } + return err, result +} diff --git a/service/collectiom_goods.go b/service/collectiom_goods.go new file mode 100644 index 0000000..f23e7e9 --- /dev/null +++ b/service/collectiom_goods.go @@ -0,0 +1,85 @@ +package service + +import ( + "errors" + "gorm.io/gorm" + "pure/global" + "pure/model" + "pure/model/request" +) + +func ChangeCollectionGoods(uuid string, info request.SpuNo) (err error, id uint) { + var ( + tmp model.CollectionGoods + collectionGoods model.CollectionGoods + ) + err = global.MG_DB.Model(&model.TbGoods{}).Where("spu_no = ?", info.SpuNo).First(&model.TbGoods{}).Error + if err != nil { + return + } + tx := global.MG_DB.Begin() + err = tx.Model(&model.CollectionGoods{}).Where("spu_no = ? AND create_by = ?", info.SpuNo, uuid).Find(&tmp).Error + if err != nil { + return + } + if tmp.ID == 0 { + collectionGoods.SpuNo = info.SpuNo + collectionGoods.CreateBy = uuid + err = tx.Model(&model.CollectionGoods{}).Create(&collectionGoods).Error + if err != nil { + tx.Rollback() + err = errors.New("收藏失败") + return + } + //商品收藏数+1 + err = tx.Model(&model.TbGoods{}).Where("spu_no = ?", info.SpuNo).UpdateColumn("collection_num", gorm.Expr("collection_num + 1")).Error + if err != nil { + tx.Rollback() + return + } + } else { + err = tx.Model(&model.CollectionGoods{}).Delete(&tmp).Error + if err != nil { + tx.Rollback() + err = errors.New("取消收藏失败") + return + } + //任务收藏数-1 + err = tx.Model(&model.TbGoods{}).Where("spu_no = ? AND collection_num > 0", info.SpuNo).UpdateColumn("collection_num", gorm.Expr("collection_num - 1")).Error + if err != nil { + tx.Rollback() + return + } + } + tx.Commit() + id = collectionGoods.ID + return +} + +func GetCollectionGoodsList(uuid string, info request.SearchCollectionGoods) (err error, list interface{}, total int64) { + limit := info.PageSize + offset := info.PageSize * (info.Page - 1) + db := global.MG_DB.Model(&model.CollectionGoods{}).Joins("INNER JOIN mission ON mission.id = collection_mission.mission_id"). + Where("collection_mission.create_by = ?", uuid) + err = db.Count(&total).Error + var res []model.TbGoodsDetail + err = db.Select("mission.id,mission.title,mission.goods_id,mission.goods_status,mission.num,mission.hire_type,mission.hire_money,mission.hire_ratio,mission.start_time,mission.end_time,mission.status"). + Preload("Goods", func(db *gorm.DB) *gorm.DB { + return db.Select("id,spu_no,title,title_eng,images,tags") + }).Limit(limit).Offset(offset).Find(&res).Error + if err != nil { + return err, nil, 0 + } + for i := 0; i < len(res); i++ { + res[i].CollectStatus = getGoodsCollectStatus(uuid, res[i].SpuNo) + } + return err, res, total +} + +func getGoodsCollectStatus(uuid string, spuNo string) (result bool) { + err := global.MG_DB.Model(&model.CollectionGoods{}).Where("create_by = ? AND spu_no = ?", uuid, spuNo).First(&model.CollectionGoods{}).Error + if err != nil { + return false + } + return true +} diff --git a/service/collection_mission.go b/service/collection_mission.go new file mode 100644 index 0000000..e072980 --- /dev/null +++ b/service/collection_mission.go @@ -0,0 +1,305 @@ +package service + +import ( + "errors" + "gorm.io/gorm" + "pure/global" + "pure/model" + "pure/model/request" + "pure/model/response" + "pure/utils" + "strconv" +) + +func ChangeCollectionMission(uuid string, info request.MissionId) (err error, id uint) { + var ( + tmp model.CollectionMission + collectionMission model.CollectionMission + ) + err = global.MG_DB.Model(&model.Mission{}).Where("id = ?", info.MissionId).First(&model.Mission{}).Error + if err != nil { + return + } + err = global.MG_DB.Model(&model.CollectionMission{}).Where("mission_id = ? AND create_by = ?", info.MissionId, uuid).Find(&tmp).Error + if err != nil { + return + } + tx := global.MG_DB.Begin() + if tmp.ID == 0 { + collectionMission.MissionId = info.MissionId + collectionMission.CreateBy = uuid + err = tx.Model(&model.CollectionMission{}).Create(&collectionMission).Error + if err != nil { + tx.Rollback() + err = errors.New("收藏失败") + return + } + //任务收藏数+1 + err = tx.Model(&model.Mission{}).Where("id = ?", info.MissionId).UpdateColumn("collection_num", gorm.Expr("collection_num + 1")).Error + if err != nil { + tx.Rollback() + return + } + } else { + err = tx.Model(&model.CollectionMission{}).Delete(&tmp).Error + if err != nil { + tx.Rollback() + err = errors.New("取消收藏失败") + return + } + //任务收藏数-1 + err = tx.Model(&model.Mission{}).Where("id = ? AND collection_num > 0", info.MissionId).UpdateColumn("collection_num", gorm.Expr("collection_num - 1")).Error + if err != nil { + tx.Rollback() + return + } + } + tx.Commit() + id = collectionMission.ID + return +} + +// 已废弃 +func GetCollectionMissionListBak(uuid string, info request.SearchCollectionMission) (err error, list interface{}, total int64) { + limit := info.PageSize + offset := info.PageSize * (info.Page - 1) + db := global.MG_DB.Model(&model.CollectionMission{}).Joins("INNER JOIN mission ON mission.id = collection_mission.mission_id"). + Where("collection_mission.create_by = ?", uuid) + err = db.Count(&total).Error + var res []model.MissionDetail + err = db.Select("mission.id,mission.title,mission.goods_id,mission.goods_status,mission.num,mission.hire_type,mission.hire_money,mission.hire_ratio,mission.start_time,mission.end_time,mission.`status`,mission.create_by"). + Preload("Goods", func(db *gorm.DB) *gorm.DB { + return db.Select("id,spu_no,title,title_eng,cover,images,tags,retail_price,price_min,price_max") + }).Order("collection_mission.id DESC").Limit(limit).Offset(offset).Find(&res).Error + if err != nil { + return err, nil, 0 + } + var ( + ids []uint + uuids []string + ) + for i := 0; i < len(res); i++ { + if res[i].CreateBy != "" { + uuids = append(uuids, res[i].CreateBy) + } + if res[i].HireType == 1 { //1:固定佣金 + res[i].HireMoneyExpect = utils.FormatFloatToString(res[i].HireMoney) + } else { //2:比例抽成 + if res[i].Goods.PriceMin == res[i].Goods.PriceMax { + res[i].HireMoneyExpect = utils.FormatFloatToString(res[i].Goods.PriceMin * (res[i].HireRatio / 100)) + } else { + res[i].HireMoneyExpect = utils.FormatFloatToString(res[i].Goods.PriceMin*(res[i].HireRatio/100)) + "-" + utils.FormatFloatToString(res[i].Goods.PriceMax*(res[i].HireRatio/100)) + } + } + ids = append(ids, res[i].ID) + //res[i].CollectStatus = getMissionCollectStatus(uuid, res[i].ID) + } + if len(ids) != 0 { + statusMap := getMissionCollectStatusMap(uuid, ids) + for i := 0; i < len(res); i++ { + res[i].CollectStatus = statusMap[res[i].ID] + } + } + if len(uuids) != 0 { + _, storeMap := getSellerStoreInfoMap(uuids) + for i := 0; i < len(res); i++ { + if val, ok := storeMap[res[i].CreateBy]; ok { + res[i].Store = val + } + } + } + return err, res, total +} + +// 收藏任务列表 +func GetCollectionMissionList(uuid string, info request.SearchCollectionMission) (err error, list []response.MissionCollectView, total int64) { + limit := info.PageSize + offset := info.PageSize * (info.Page - 1) + db := global.MG_DB.Model(&model.CollectionMission{}).Joins("INNER JOIN mission ON mission.id = collection_mission.mission_id"). + Where("collection_mission.create_by = ?", uuid) + err = db.Count(&total).Error + var res []model.MissionDetail + + err = db.Select("mission.id,mission.title,mission.goods_id,mission.goods_status,mission.num,mission.hire_type,mission.hire_money,mission.hire_ratio,mission.start_time,mission.end_time,mission.`status`,mission.create_by"). + Preload("Goods", func(db *gorm.DB) *gorm.DB { + return db.Select("id,spu_no,title,title_eng,cover,images,tags,retail_price,price_min,price_max") + }).Order("collection_mission.id DESC").Limit(limit).Offset(offset).Find(&res).Error + if err != nil { + return err, nil, 0 + } + var ( + ids []uint + uuids []string + missionList []response.MissionCollectView + ) + for i := 0; i < len(res); i++ { + if res[i].CreateBy != "" { + uuids = append(uuids, res[i].CreateBy) + } + if res[i].HireType == 1 { //1:固定佣金 + res[i].HireMoneyExpect = utils.FormatFloatToString(res[i].HireMoney) + } else { //2:比例抽成 + //按最高价显示 + res[i].HireMoneyExpect = utils.FormatFloatToString(res[i].Goods.PriceMax * (res[i].HireRatio / 100)) + } + bonus, sales, _ := GetMissionBonusAndSales(res[i].ID) + vMission := response.MissionCollectView{ + ID: 0, + MissionId: res[i].ID, + AchieveNum: sales, + TotalBonus: bonus.Total, + Status: res[i].Status, + HireType: res[i].HireType, + HireMoneyExpect: res[i].HireMoneyExpect, + Goods: response.MissionGoodsView{ + GoodsId: res[i].GoodsId, + SkuNo: "", + Title: res[i].Goods.Title, + Images: res[i].Goods.Cover, + Price: res[i].Goods.PriceMax, + SpuNo: res[i].Goods.SpuNo, + TitleEng: res[i].Goods.TitleEng, + }, + } + missionList = append(missionList, vMission) + + ids = append(ids, res[i].ID) + //res[i].CollectStatus = getMissionCollectStatus(uuid, res[i].ID) + } + + return err, missionList, total +} + +func getMissionCollectStatus(uuid string, id uint) (result bool) { + err := global.MG_DB.Model(&model.CollectionMission{}).Where("create_by = ? AND mission_id = ?", uuid, id).First(&model.CollectionMission{}).Error + if err != nil { + return false + } + return true +} + +func getMissionCollectStatusMap(uuid string, ids []uint) map[uint]bool { + var ( + list []model.CollectionMission + result = make(map[uint]bool) + ) + err := global.MG_DB.Model(&model.CollectionMission{}).Where("create_by = ? AND mission_id IN (?)", uuid, ids).Find(&list).Error + if err != nil { + return result + } + for i := 0; i < len(list); i++ { + result[list[i].MissionId] = true + } + for i := 0; i < len(ids); i++ { + if _, ok := result[ids[i]]; !ok { + result[ids[i]] = false + } + } + return result +} + +// 收藏任务列表 +func GetRecommendMissionList(info request.SearchRecommendMission) (err error, list []response.MissionRecommendResponse, total int64) { + limit := info.PageSize + offset := info.PageSize * (info.Page - 1) + db := global.MG_DB.Model(&model.MissionRecommend{}). + Joins("inner join mission_claim_video on mission_recommend.relation_id = mission_claim_video.id"). + Joins("inner join mission on mission.id = mission_claim_video.mission_id"). + Where("mission_claim_video.status = 2"). //审核通过状态 + Order("mission_recommend.sort desc") + err = db.Count(&total).Error + if err != nil { + return err, nil, 0 + } + var res []model.MissionRecommendDetail + + err = db.Preload("MissionVideo", func(db *gorm.DB) *gorm.DB { + return db.Preload("Mission", func(db *gorm.DB) *gorm.DB { + return db.Select("id,title,goods_id,goods_status,num,hire_type,hire_money,hire_ratio,claim_num,start_time,end_time,`status`,has_video,video_channel_ids,video_country_id,claim_days,create_by"). + Preload("Goods", func(db *gorm.DB) *gorm.DB { + return db.Select("id,spu_no,title,title_eng,images,retail_price,price_min,price_max,stock,sales,online,created_at,updated_at") + }) + }).Preload("Influencer", func(db *gorm.DB) *gorm.DB { + return db.Select("uuid,nick_name,phone") + }) + }).Order("id DESC").Limit(limit).Offset(offset).Find(&res).Error + + if err != nil { + return err, nil, 0 + } + for i := 0; i < len(res); i++ { + //精简字段赋值 + vRes := formatMissionRecommendData(res[i]) + vRes.Tag = GetTagNamesByRelation(strconv.Itoa(int(vRes.MissionRecommend.RelationId)), "02") + list = append(list, vRes) + } + + return err, list, total +} + +func GetRecommendMissionDetail(id request.IdReq) (err error, data response.MissionRecommendResponse) { + + db := global.MG_DB.Model(&model.MissionRecommend{}). + Joins("inner join mission_claim_video on mission_recommend.relation_id = mission_claim_video.id"). + Joins("inner join mission on mission.id = mission_claim_video.mission_id"). + Where("mission_recommend.id = ?", id.ID) + var res model.MissionRecommendDetail + + err = db.Preload("MissionVideo", func(db *gorm.DB) *gorm.DB { + return db.Preload("Mission", func(db *gorm.DB) *gorm.DB { + return db.Select("id,title,goods_id,goods_status,num,hire_type,hire_money,hire_ratio,claim_num,start_time,end_time,`status`,has_video,video_channel_ids,video_country_id,claim_days,create_by"). + Preload("Goods", func(db *gorm.DB) *gorm.DB { + return db.Select("id,spu_no,title,title_eng,images,retail_price,price_min,price_max,stock,sales,online,created_at,updated_at") + }) + }).Preload("Influencer", func(db *gorm.DB) *gorm.DB { + return db.Select("uuid,nick_name,phone") + }) + }).First(&res).Error + + if err != nil { + return err, data + } + data = formatMissionRecommendData(res) + + return err, data +} + +func formatMissionRecommendData(res model.MissionRecommendDetail) response.MissionRecommendResponse { + bonus, sales, claimNum := GetMissionBonusAndSales(res.MissionVideo.MissionId) + if res.MissionVideo.Mission.HireType == 1 { //1:固定佣金 + res.MissionVideo.Mission.HireMoneyExpect = utils.FormatFloatToString(res.MissionVideo.Mission.HireMoney) + } else { //2:比例抽成 + //按最高价显示 + res.MissionVideo.Mission.HireMoneyExpect = utils.FormatFloatToString(res.MissionVideo.Mission.Goods.PriceMax * (res.MissionVideo.Mission.HireRatio / 100)) + } + //精简字段赋值 + vRes := response.MissionRecommendResponse{ + MissionRecommend: res.MissionRecommend, + MissionVideoCommonData: response.MissionVideoCommonData{ + MissionId: res.MissionVideo.MissionId, + VideoUrl: res.MissionVideo.VideoUrl, + Cover: res.MissionVideo.Cover, + Title: res.MissionVideo.Mission.Title, + GoodsTitle: res.MissionVideo.Mission.Goods.Title, + GoodsTitleEng: res.MissionVideo.Mission.Goods.TitleEng, + Influencer: res.MissionVideo.Influencer, + Tag: "", + MissionStatus: res.MissionVideo.Mission.Status, + StartTime: res.MissionVideo.Mission.StartTime, + EndTime: res.MissionVideo.Mission.EndTime, + HireType: res.MissionVideo.Mission.HireType, + HireMoney: res.MissionVideo.Mission.HireMoney, + HireRatio: res.MissionVideo.Mission.HireRatio, + HireMoneyExpect: res.MissionVideo.Mission.HireMoneyExpect, + ReleaseCountry: res.MissionVideo.Mission.ReleaseCountry, + ReleaseChannels: res.MissionVideo.Mission.ReleaseChannels, + AchieveNum: sales, + TotalBonus: bonus.Total, + BoughtNum: bonus.UserTotal, + Width: res.MissionVideo.Width, + Height: res.MissionVideo.Height, + ClaimNum: claimNum, + }, + } + return vRes +} diff --git a/service/dict.go b/service/dict.go new file mode 100644 index 0000000..23b89ce --- /dev/null +++ b/service/dict.go @@ -0,0 +1,56 @@ +package service + +import ( + "fmt" + "pure/global" + "pure/model" +) + +func GetSysDictDataLabel(typeCode, value string) string { + var res string + + cacheKey := "bkb-admin_sys_dict_labels" + labelKey := fmt.Sprintf("%s_%s", typeCode, value) + res = RedisHashGet(cacheKey, labelKey) + if res == "" { + _ = global.MG_DB.Model(&model.SysDictData{}).Select("label").Where("type_code=? AND `value`=?", typeCode, value).Scan(&res).Error + go RedisHashSet(cacheKey, labelKey, res) + } + return res +} + +func GetSysDictDataList(typeCode string) (err error, list interface{}) { + var lists []model.SysDictDataView + err = global.MG_DB.Model(&model.SysDictData{}).Where("type_code=? AND `status`='1'", typeCode).Order("sort asc").Find(&lists).Error + return err, lists +} + +func GetSysDictDataListByTypeCode(typeCode string) (list []model.SysDictDataView, err error) { + var lists []model.SysDictDataView + err = global.MG_DB.Model(&model.SysDictData{}).Where("type_code=? AND `status`='1'", typeCode).Order("sort asc").Find(&lists).Error + return lists, err +} + +func FormatDictLabels(typeCode string, values []string) (labels []string) { + for _, vid := range values { + vLabel := GetSysDictDataLabel(typeCode, vid) + labels = append(labels, vLabel) + } + return labels +} + +func getDictMap(typeCode string, values []string) map[string]string { + var ( + list []model.SysDictData + result = make(map[string]string) + ) + db := global.MG_DB.Model(&model.SysDictData{}).Where("type_code = ?", typeCode) + if len(values) != 0 { + db = db.Where("values IN (?)", values) + } + _ = db.Find(&list).Error + for _, val := range list { + result[val.Value] = val.Label + } + return result +} diff --git a/service/jwt_black_list.go b/service/jwt_black_list.go new file mode 100755 index 0000000..ca31810 --- /dev/null +++ b/service/jwt_black_list.go @@ -0,0 +1,53 @@ +package service + +import ( + "errors" + "pure/global" + "pure/model" + "time" + + "gorm.io/gorm" +) + +//@function: JsonInBlacklist +//@description: 拉黑jwt +//@param: jwtList model.JwtBlacklist +//@return: err error + +func JsonInBlacklist(jwtList model.JwtBlacklist) (err error) { + err = global.MG_DB.Create(&jwtList).Error + return +} + +//@function: IsBlacklist +//@description: 判断JWT是否在黑名单内部 +//@param: jwt string +//@return: bool + +func IsBlacklist(jwt string) bool { + err := global.MG_DB.Where("jwt = ?", jwt).First(&model.JwtBlacklist{}).Error + isNotFound := errors.Is(err, gorm.ErrRecordNotFound) + return !isNotFound +} + +//@function: GetRedisJWT +//@description: 从redis取jwt +//@param: userName string +//@return: err error, redisJWT string + +func GetRedisJWT(userName string) (err error, redisJWT string) { + redisJWT, err = global.MG_REDIS.Get(userName).Result() + return err, redisJWT +} + +//@function: SetRedisJWT +//@description: jwt存入redis并设置过期时间 +//@param: jwt string, userName string +//@return: err error + +func SetRedisJWT(jwt string, userName string) (err error) { + // 此处过期时间等于jwt过期时间 + timer := time.Duration(global.MG_CONFIG.JWT.ExpiresTime) * time.Second + err = global.MG_REDIS.Set(userName, jwt, timer).Err() + return err +} diff --git a/service/mission.go b/service/mission.go new file mode 100644 index 0000000..cd56e6e --- /dev/null +++ b/service/mission.go @@ -0,0 +1,778 @@ +package service + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math" + "pure/initialize/api" + "strconv" + "strings" + "time" + + "github.com/spf13/cast" + "gorm.io/gorm" + + "pure/global" + "pure/model" + "pure/model/request" + "pure/model/response" + "pure/utils" +) + +func GetMissionDetail(uuid string, id uint) (error, model.MissionDetail) { + var ( + err error + result model.MissionDetail + ) + err = global.MG_DB.Model(&model.Mission{}). + Select("id,title,goods_id,goods_status,num,hire_type,hire_money,hire_ratio,start_time,end_time,status,create_by,has_sample,has_video,claim_stock,claim_days,claim_demands,video_channel_ids,description,claim_num,sample_num"). + Where("id = ?", id).Preload("Goods", func(db *gorm.DB) *gorm.DB { + return db.Select("id,spu_no,title,title_eng,images,tags,retail_price,price_min,price_max,stock,sales").Preload("Specs", func(db *gorm.DB) *gorm.DB { + return db.Select("id,goods_id,specs,stock,sku_no,price,image,goods_no,code").Unscoped() + }).Unscoped() + }).First(&result).Error + + if err != nil { + return err, result + } + + if result.VideoChannelIds != "" { + channelLabels := FormatDictLabels(model.ReleaseChannelCode, strings.Split(result.VideoChannelIds, ",")) + result.ReleaseChannels = strings.Join(channelLabels, "、") + } + claimExcept := GetMissionStatusExcept(result, uuid) + result.ClaimStatusExcept = claimExcept + trs := utils.InterTranslate(claimExcept, "zh", "en") + if trs != "" { + result.ClaimStatusExceptEng = trs + } + + if result.HireType == 1 { // 1:固定佣金 + result.HireMoneyExpect = utils.FormatFloatToString(result.HireMoney) + } else { // 2:比例抽成 + if result.Goods.PriceMin == result.Goods.PriceMax { + result.HireMoneyExpect = utils.FormatFloatToString(result.Goods.PriceMin * (result.HireRatio / 100)) + } else { + result.HireMoneyExpect = utils.FormatFloatToString(result.Goods.PriceMin*(result.HireRatio/100)) + "-" + utils.FormatFloatToString(result.Goods.PriceMax*(result.HireRatio/100)) + } + } + if result.CreateBy != "" { + _, result.Store = GetSellerStoreInfo(result.CreateBy) + } + result.CollectStatus = getMissionCollectStatus(uuid, result.ID) + // + result.GoodsUrl = global.MG_CONFIG.Tools.CustomerUrl + `/CommodityDetails?id=` + cast.ToString(result.GoodsId) + err = getSpecs(&result.Goods) + return nil, result +} + +func getSpecs(goods *model.TbGoodsSpecsView) (err error) { + attributeValues := make(map[uint]*model.TbAttributeValueJson) + for i := 0; i < len(goods.Specs); i++ { + err = json.Unmarshal([]byte(goods.Specs[i].Specs), &goods.Specs[i].Attributes) + if err != nil { + return err + } + if i == 0 { + var attributes []uint + for j := 0; j < len(goods.Specs[i].Attributes); j++ { + attributes = append(attributes, goods.Specs[i].Attributes[j].AttributeId) + } + orderSql := "FIELD(id" + for _, attribute := range attributes { + orderSql += fmt.Sprintf(",'%v'", attribute) + } + orderSql += ")" + err = global.MG_DB.Model(&model.TbAttribute{}).Select("id,`name`").Where("id IN (?)", attributes).Order(orderSql).Find(&goods.Attributes).Error + if err != nil { + return err + } + } + for _, attribute := range goods.Specs[i].Attributes { + if _, ok := attributeValues[attribute.AttributeId]; ok { + if !strings.Contains(attributeValues[attribute.AttributeId].Str, attribute.Value) { + attributeValues[attribute.AttributeId].Str += attribute.Value + "," + attributeValues[attribute.AttributeId].Items = append(attributeValues[attribute.AttributeId].Items, model.TbAttributeValueItem{ + Id: attribute.ValueId, Name: attribute.Value, Image: goods.Specs[i].Image}) + } + } else { + attributeValues[attribute.AttributeId] = &model.TbAttributeValueJson{Items: []model.TbAttributeValueItem{{ + Id: attribute.ValueId, Name: attribute.Value, Image: goods.Specs[i].Image}}, Str: attribute.Value + ","} + } + } + } + for i := 0; i < len(goods.Attributes); i++ { + if val, ok := attributeValues[goods.Attributes[i].ID]; ok { + goods.Attributes[i].Values = val.Items + } + } + return +} + +func GetMissionList(uuid string, info request.SearchMission) (err error, list any, total int64) { + limit := info.PageSize + offset := info.PageSize * (info.Page - 1) + db := global.MG_DB.Model(&model.Mission{}).Joins("INNER JOIN tb_goods ON tb_goods.id = mission.goods_id"). + Where("mission.goods_status = 1 AND tb_goods.stock > 0") + err = db.Count(&total).Error + var res []model.MissionDetail + err = db.Select("mission.id,mission.title,mission.goods_id,mission.goods_status,mission.num,mission.hire_type,mission.hire_money,mission.hire_ratio,mission.start_time,mission.end_time,mission.`status`,mission.create_by,case when mission.status = 2 then 900000000 when mission.status = 1 then 500000000+mission.id else mission.id end as sort_value"). + // 分段排序逻辑:进行中--结束时间正序,未开始--id倒序,已结束--id倒序 + Preload("Goods", func(db *gorm.DB) *gorm.DB { + return db.Select("tb_goods.id,tb_goods.spu_no,title,title_eng,tb_goods.images,tb_goods.tags,retail_price,price_min,price_max").Unscoped() + }).Limit(limit).Offset(offset).Order("sort_value desc").Order("end_time asc").Find(&res).Error + + if err != nil { + return err, nil, 0 + } + var ( + ids []uint + uuids []string + ) + for i := 0; i < len(res); i++ { + if res[i].HireType == 1 { // 1:固定佣金 + res[i].HireMoneyExpect = utils.FormatFloatToString(res[i].HireMoney) + } else { // 2:比例抽成 + if res[i].Goods.PriceMin == res[i].Goods.PriceMax { + // res[i].HireMoneyExpect = fmt.Sprintf("%v", res[i].Goods.PriceMin*(res[i].HireRatio/100)) + res[i].HireMoneyExpect = utils.FormatFloatToString(res[i].Goods.PriceMin * (res[i].HireRatio / 100)) + } else { + res[i].HireMoneyExpect = utils.FormatFloatToString(res[i].Goods.PriceMin*(res[i].HireRatio/100)) + "-" + utils.FormatFloatToString(res[i].Goods.PriceMax*(res[i].HireRatio/100)) + } + } + if res[i].CreateBy != "" { + uuids = append(uuids, res[i].CreateBy) + } + ids = append(ids, res[i].ID) + } + if len(ids) != 0 { + statusMap := getMissionCollectStatusMap(uuid, ids) + for i := 0; i < len(res); i++ { + if val, ok := statusMap[res[i].ID]; ok { + res[i].CollectStatus = val + } + } + } + if len(uuids) != 0 { + _, storeMap := getSellerStoreInfoMap(uuids) + for i := 0; i < len(res); i++ { + if val, ok := storeMap[res[i].CreateBy]; ok { + res[i].Store = val + } + } + } + return err, res, total +} + +func getMissionClaim(uuid, claimNo string) (err error, result model.MissionClaim) { + err = global.MG_DB.Model(&model.MissionClaim{}).Where("create_by = ? AND claim_no = ?", uuid, claimNo).First(&result).Error + return +} + +func GetMissionClaim(uuid string, id uint) (err error, res model.MissionClaimDetail) { + err = global.MG_DB.Model(&model.MissionClaim{}).Where("create_by = ? AND id = ?", uuid, id). + Select("id,mission_id,claim_no,achieve_num,`status`,created_at,updated_at,expire_at,finished,email"). + Preload("Order", func(db *gorm.DB) *gorm.DB { + return db.Select("order_id,mission_claim_id,`status`,courier,courier_url,courier_number,send_time"). + Preload("OrderGoods", func(db *gorm.DB) *gorm.DB { + return db.Select("order_id,price,sku_no,title,image,specs,id") + }) + }). + Preload("Mission", func(db *gorm.DB) *gorm.DB { + return db.Select("id,title,goods_id,goods_status,num,hire_type,hire_money,hire_ratio,start_time,end_time,`status`,create_by,claim_days"). + Preload("Goods", func(db *gorm.DB) *gorm.DB { + return db.Select("id,spu_no,title,title_eng,images,tags,retail_price,price_min,price_max").Unscoped() + }) + }).Preload("Works"). + Preload("Video", func(db *gorm.DB) *gorm.DB { + return db.Where("status in (1,2)").Order("id desc").Limit(1) + }).First(&res).Error + if err != nil { + return + } + res.Video.CreateTime = res.Video.CreatedAt + + if res.Mission.CreateBy != "" { + _, res.Mission.Store = GetSellerStoreInfo(res.Mission.CreateBy) + } + if res.Mission.HireType == 1 { // 1:固定佣金 + res.Mission.HireMoneyExpect = utils.FormatFloatToString(res.Mission.HireMoney) + } else { // 2:比例抽成 + res.Mission.HireMoneyExpect = utils.FormatFloatToString(res.Order.OrderGoods.Price * (res.Mission.HireRatio / 100)) + } + if res.Mission.ID != 0 { + res.Mission.CollectStatus = getMissionCollectStatus(uuid, res.Mission.ID) + } + res.StatusExcept = GetMissionClaimStatusExcept(res) + + res.SpreadUrl = global.MG_CONFIG.Tools.CustomerUrl + "/CommodityDetails?id=" + fmt.Sprintf("%v", res.Mission.Goods.ID) + "&spu_no=" + res.Mission.Goods.SpuNo + "&claim_no=" + res.ClaimNo + return +} + +func MergeMissionClaimList(uuid string, info request.SearchMissionClaim) (err error, list []model.MissionClaimDetail, total int64) { + // 进行中与已结束分段查询,在此处合并 + db := global.MG_DB.Model(&model.MissionClaim{}).Joins("inner join mission on mission.id = mission_claim.mission_id"). + Where("mission_claim.create_by = ?", uuid) + if info.HireType != 0 { + db = db.Where("mission.hire_type = ?", info.HireType) + } + + //是否 + if info.VideoUpload == 1 { + var delIds []uint + var claimVideos []model.MissionClaimVideo + err = global.MG_DB.Model(&model.MissionClaimVideo{}). + Select("id,mission_id,status,create_by,mission_claim_id"). + Where("status in (1,2) and create_by = ?", uuid). + Find(&claimVideos).Error + for _, c := range claimVideos { + if c.MissionClaimId != 0 { + delIds = append(delIds, c.MissionClaimId) + } + } + info.ExcludeIds = delIds + db.Where("mission_claim.id not in (?)", info.ExcludeIds) + } + + err = db.Count(&total).Error + var ( + partTotal int64 + partOffset int + limit int + offset int + newPage int + endedList []model.MissionClaimDetail + ) + limit = info.PageSize + offset = info.PageSize * (info.Page - 1) + // 查询进行中的数据 + info.MissionStatus = 2 + err, list, partTotal = GetMissionClaimList(uuid, info, offset, limit) + if len(list) < limit { + // 查询已结束的数据补齐 + info.MissionStatus = 3 + // 进行中总页数 + newPage = info.Page - int(math.Ceil(float64(partTotal)/float64(limit))) + partOffset = int(partTotal) % limit + if len(list) > 0 { + limit = info.PageSize - len(list) + offset = 0 + } else { + limit = info.PageSize + offset = info.PageSize*newPage - partOffset + } + + err, endedList, partTotal = GetMissionClaimList(uuid, info, offset, limit) + list = append(list, endedList...) + } + + return err, list, total +} + +func GetMissionClaimList(uuid string, info request.SearchMissionClaim, offset, limit int) (err error, list []model.MissionClaimDetail, total int64) { + db := global.MG_DB.Model(&model.MissionClaim{}).Where("mission_claim.create_by = ?", uuid) + + var res []model.MissionClaimDetail + + db = db.Joins("inner join mission on mission.id = mission_claim.mission_id"). + Select("mission_claim.id,mission_claim.mission_id,mission_claim.claim_no,mission_claim.achieve_num,mission_claim.`status`,mission_claim.created_at,mission_claim.updated_at,mission_claim.expire_at,mission_claim.finished").Preload("Order", func(db *gorm.DB) *gorm.DB { + return db.Select("order_id,mission_claim_id,`status`,courier,courier_url,courier_number"). + Preload("OrderGoods", func(db *gorm.DB) *gorm.DB { + return db.Select("order_id,sku_no,title,specs,image,price").Unscoped() + }) + }).Preload("Mission", func(db *gorm.DB) *gorm.DB { + return db.Select("id,title,goods_id,goods_status,num,hire_type,hire_money,hire_ratio,start_time,end_time,`status`,create_by"). + Preload("Goods", func(db *gorm.DB) *gorm.DB { + return db.Select("id,spu_no,title,title_eng,images,tags,retail_price,price_min,price_max").Unscoped() + }) + }) + + if info.HireType != 0 { + db = db.Where("mission.hire_type = ?", info.HireType) + } + + if len(info.ExcludeIds) != 0 { + db.Where("mission_claim.id not in (?)", info.ExcludeIds) + } + + if info.MissionStatus == 2 { + db = db.Where("mission.status = 2").Order("mission_claim.expire_at asc") + } else { + db = db.Where("mission.status != 2") + } + + err = db.Count(&total).Error + err = db.Order("mission_claim.id DESC").Limit(limit).Offset(offset).Find(&res).Error + + if err != nil { + return err, nil, 0 + } + var ( + ids []uint + uuids []string + resList []response.MissionClaimView + ) + for i := 0; i < len(res); i++ { + var vMissionClaim response.MissionClaimView + + if res[i].Mission.CreateBy != "" { + uuids = append(uuids, res[i].Mission.CreateBy) + } + if res[i].Mission.HireType == 1 { // 1:固定佣金 + res[i].Mission.HireMoneyExpect = utils.FormatFloatToString(res[i].Mission.HireMoney) + } else { // 2:比例抽成 + res[i].Mission.HireMoneyExpect = utils.FormatFloatToString(res[i].Order.OrderGoods.Price * (res[i].Mission.HireRatio / 100)) + } + res[i].SpreadUrl = global.MG_CONFIG.Tools.CustomerUrl + "/CommodityDetails?id=" + fmt.Sprintf("%v", res[i].Mission.Goods.ID) + "&spu_no=" + res[i].Mission.Goods.SpuNo + "&claim_no=" + res[i].ClaimNo + + if res[i].Mission.ID != 0 { + ids = append(ids, res[i].Mission.ID) + } + vRes := res[i] + vMissionClaim.MissionId = vRes.MissionId + vMissionClaim = response.MissionClaimView{ + ID: vRes.ID, + ClaimNo: vRes.ClaimNo, + MissionId: vRes.MissionId, + AchieveNum: vRes.AchieveNum, + Status: vRes.Status, + SpreadUrl: vRes.SpreadUrl, + HireType: vRes.Mission.HireType, + HireMoneyExpect: vRes.Mission.HireMoneyExpect, + EndTime: vRes.Mission.EndTime, + ExpireAt: vRes.ExpireAt, + CollectStatus: false, + Goods: response.MissionGoodsView{ + GoodsId: vRes.Mission.GoodsId, + SkuNo: vRes.Order.OrderGoods.SkuNo, + Title: vRes.Order.OrderGoods.Title, + Images: vRes.Order.OrderGoods.Image, + Price: vRes.Order.OrderGoods.Price, + SpuNo: vRes.Mission.Goods.SpuNo, + TitleEng: vRes.Mission.Goods.TitleEng, + }, + } + + resList = append(resList, vMissionClaim) + } + if len(ids) != 0 { + statusMap := getMissionCollectStatusMap(uuid, ids) + for i := 0; i < len(res); i++ { + res[i].Mission.CollectStatus = statusMap[res[i].ID] + } + } + if len(uuids) != 0 { + _, storeMap := getSellerStoreInfoMap(uuids) + for i := 0; i < len(res); i++ { + if val, ok := storeMap[res[i].Mission.CreateBy]; ok { + res[i].Mission.Store = val + } + } + } + + return err, res, total +} + +func ClaimMission(uuid string, info request.ClaimMission) (err error, id uint) { + var mission model.Mission + //查询网红是否被禁用 + var user model.User + err = global.MG_DB.Model(&model.User{}).Where("uuid = ?", uuid).First(&user).Error + if err != nil { + return errors.New("未找到用户信息"), 0 + } + if user.IDForbidden { + return errors.New("账号已被禁用"), 0 + } + if global.MG_DB.Model(&model.Mission{}).Where("id = ?", info.MissionId).First(&mission).Error != nil { + return errors.New("抱歉,未找到任务信息"), 0 + } + if mission.Status != 2 || mission.GoodsStatus != 1 { + return errors.New("抱歉,当前任务不可领取"), 0 + } + now := time.Now().UTC().Unix() + if mission.StartTime.Unix() > now || mission.EndTime.Unix() < now { + return errors.New("抱歉,不在任务领取时间内"), 0 + } + + if mission.HireType == 1 && mission.ClaimStock <= mission.ClaimNum { + return errors.New("可接人数已满额"), 0 + } + + if mission.HireType == 2 { + var total int64 + global.MG_DB.Model(&model.MissionClaim{}).Where("create_by = ? AND mission_id = ? and hire_type = 2", uuid, mission.ID).Count(&total) + if total >= 10 { + return errors.New("进行中任务已达上限"), 0 + } + } + + var address model.Address + if !errors.Is(global.MG_DB.Model(&model.MissionClaim{}).Where("create_by = ? AND mission_id = ?", uuid, info.MissionId).First(&model.MissionClaim{}).Error, gorm.ErrRecordNotFound) { // 判断email是否注册 + return errors.New("不可重复领取"), 0 + } + if global.MG_DB.Model(&model.Address{}).Where("user_id = ? AND id = ?", uuid, info.AddressId).First(&address).Error != nil { + return errors.New("抱歉,未找到地址信息"), 0 + } + var ( + missionClaim model.MissionClaim + missionClaimOrder model.MissionClaimOrder + missionClaimOrderGoods model.MissionClaimOrderGoods + missionClaimAddress model.MissionClaimAddress + ) + tx := global.MG_DB.Begin() + missionClaim.MissionId = info.MissionId + missionClaim.ClaimNo = utils.GetInvitationLowerLen(20) + missionClaim.AchieveNum = 0 + missionClaim.CreateBy = uuid + missionClaim.Status = 1 + expireDate := time.Now().AddDate(0, 0, mission.ClaimDays) + missionClaim.ExpireAt = expireDate + missionClaim.Email = info.Email //邮箱 + err = tx.Model(&model.MissionClaim{}).Create(&missionClaim).Error + if err != nil { + tx.Rollback() + return + } + // 任务领取人数+1 + err = tx.Model(&model.Mission{}).Where("id = ?", info.MissionId).UpdateColumn("claim_num", gorm.Expr("`claim_num` + 1")).Error + if err != nil { + tx.Rollback() + return + } + + // 创建任务订单 + var ( + goods model.TbGoods + goodsSpec model.TbGoodsSpecs + ) + err = tx.Model(&model.TbGoods{}).Where("online = 'on' AND spu_no = ?", info.SpuNo).First(&goods).Error + if err != nil { + tx.Rollback() + err = errors.New("未找到商品信息") + return + } + err = tx.Model(&model.TbGoodsSpecs{}).Where("status = 1 AND goods_id = ? AND sku_no = ?", goods.ID, info.SkuNo).First(&goodsSpec).Error + if err != nil { + tx.Rollback() + err = errors.New("未找到商品规格信息") + return + } + missionClaimOrder.OrderID = Generate() + missionClaimOrder.MissionClaimId = missionClaim.ID + missionClaimOrder.SpuNo = info.SpuNo + missionClaimOrder.SkuNo = info.SkuNo + missionClaimOrder.Number = 1 + missionClaimOrder.CreateBy = uuid + missionClaimOrder.Status = 2 // 待发货 + err = tx.Model(&model.MissionClaimOrder{}).Create(&missionClaimOrder).Error + if err != nil { + tx.Rollback() + err = errors.New("创建任务订单失败") + return + } + missionClaimOrderGoods.OrderID = missionClaimOrder.OrderID + missionClaimOrderGoods.SkuNo = info.SkuNo + missionClaimOrderGoods.Title = goods.Title + missionClaimOrderGoods.Image = goodsSpec.Image + missionClaimOrderGoods.Specs = goodsSpec.Specs + missionClaimOrderGoods.Price = goodsSpec.Price + err = tx.Model(&model.MissionClaimOrderGoods{}).Create(&missionClaimOrderGoods).Error + if err != nil { + tx.Rollback() + err = errors.New("创建任务订单失败") + return + } + + // 创建任务收获地址 + missionClaimAddress.Address = address + missionClaimAddress.ID = 0 + missionClaimAddress.AddressId = address.ID + missionClaimAddress.MissionClaimId = missionClaim.ID + missionClaimAddress.OrderID = missionClaimOrder.OrderID + err = tx.Model(&model.MissionClaimAddress{}).Create(&missionClaimAddress).Error + if err != nil { + tx.Rollback() + return + } + + _, seller := GetSellerStoreInfo(mission.CreateBy) + + if mission.HireType == 1 { + // 固定佣金任务锁定商家营销账户 + var wallet model.Wallet + err = global.MG_DB.Model(&model.Wallet{}).Where("platform = 'seller' AND user_id = ?", seller.StoreNo).First(&wallet).Error + if err != nil { + return + } + var billFund model.BillFund + billFund.UserID = mission.CreateBy + billFund.TransactionType = 1 + billFund.TransactionId = "MB" + Generate() // mission-bill + billFund.Title = "" + billFund.Price = mission.HireMoney + billFund.Balance = wallet.Fund + billFund.Platform = "seller" + billFund.RelatedId = missionClaim.ClaimNo + billFund.Status = 1 + err = tx.Model(&model.BillFund{}).Create(&billFund).Error + if err != nil { + tx.Rollback() + return + } + } + tx.Commit() + id = missionClaim.ID + + //给商家发送邮件 + go func(uid string, mission model.Mission, email string) { + _, user := GetUserDetail(uid) + body := fmt.Sprintf("您好,%s已被%s已接单,请及时回复网红疑问,促进网红完成任务", mission.Title, user.NickName) + global.EMAIL_CLIENT.SendEmail(context.Background(), &api.SendRequest{ + To: []string{email}, + Subject: "网红接任务", + Body: body, + }) + }(uuid, mission, seller.Email) + + //给网红发送邮件 + if mission.HasVideo == 1 && mission.VideoUrl != "" { + go func(mission model.Mission, email string, files string) { + subject := fmt.Sprintf("任务《%s》素材已发送", mission.Title) + body := "嗨,您接任务的素材已发送到邮箱,请查看,尽快完成任务。" + global.EMAIL_CLIENT.SendEmail(context.Background(), &api.SendRequest{ + To: []string{email}, + Subject: subject, + Body: body, + Files: []string{files}, + }) + }(mission, info.Email, mission.VideoUrl) + } + + return +} + +func SubmitClaimMissionWorks(uuid string, info request.ClaimMissionWorksList) (err error) { + var ( + missionClaim model.MissionClaim + ) + + err = global.MG_DB.Model(&model.MissionClaim{}).Where("create_by = ? AND id = ?", uuid, info.MissionClaimId).First(&missionClaim).Error + if err != nil { + err = errors.New("not found mission claim record") + return err + } + + tx := global.MG_DB.Begin() + for i := 0; i < len(info.Works); i++ { + var works model.MissionClaimWorks + works.Type = info.Works[i].Type + works.Homepage = info.Works[i].Homepage + works.Image = info.Works[i].Image + works.VideoUrl = info.Works[i].VideoUrl + if info.Works[i].ID != 0 { + if info.Works[i].Homepage == "" { + err = tx.Model(&model.MissionClaimWorks{}).Where("id = ?", info.Works[i].ID).Delete(&model.MissionClaimWorks{}).Error + if err != nil { + tx.Rollback() + return err + } + } else { + err = tx.Model(&model.MissionClaimWorks{}).Where("id = ?", info.Works[i].ID).Select("Type", "Homepage", "Image", "VideoUrl").Updates(&works).Error + if err != nil { + tx.Rollback() + return err + } + } + } else { + works.MissionClaimId = info.MissionClaimId + err = tx.Model(&model.MissionClaimWorks{}).Create(&works).Error + if err != nil { + tx.Rollback() + return err + } + } + } + claimStatus := 3 // 推广中 + err = tx.Model(&model.MissionClaim{}).Where("id = ? AND status = 2", info.MissionClaimId).UpdateColumn("status", claimStatus).Error + if err != nil { + tx.Rollback() + return err + } + tx.Commit() + return nil +} + +func SubmitClaimMissionVideo(uuid string, info request.ClaimMissionVideo) (err error) { + var ( + mission model.Mission + missionClaim model.MissionClaim + claimVideo model.MissionClaimVideo + achieveNum int64 + ) + + err = global.MG_DB.Model(&model.MissionClaim{}).Where("create_by = ? AND id = ?", uuid, info.MissionClaimId).First(&missionClaim).Error + if err != nil { + err = errors.New("not found mission claim record") + return err + } + err = global.MG_DB.Model(&model.Mission{}).Where("id = ?", missionClaim.MissionId).First(&mission).Error + if err != nil { + err = errors.New("not found mission record") + return err + } + + // 判断有无审核通过和待审核的 + err = global.MG_DB.Model(&model.MissionClaimVideo{}).Where("mission_claim_id = ? and status in (1,2)", info.MissionClaimId).First(&model.MissionClaimVideo{}).Error + if !errors.Is(err, gorm.ErrRecordNotFound) { + return errors.New("不能重复上传") + } + if info.SourceType == 2 { + global.MG_DB.Model(&model.MissionClaimVideo{}).Where("create_by = ? and source_type = 2 and status in (1,2)", uuid).Count(&achieveNum) + } + + tx := global.MG_DB.Begin() + claimVideo.MissionClaimId = info.MissionClaimId + claimVideo.VideoUrl = info.VideoUrl + claimVideo.Cover = info.Cover + claimVideo.Status = 1 // 待审核 + claimVideo.SourceType = info.SourceType // 来源类型 + claimVideo.MissionId = missionClaim.MissionId // 任务ID + claimVideo.CreateBy = uuid // 创建者ID + claimVideo.Width = info.Width //宽度 + claimVideo.Height = info.Height //高度 + err = tx.Model(&model.MissionClaimVideo{}).Create(&claimVideo).Error + if err != nil { + tx.Rollback() + return err + } + // 完成平台任务奖励 + if info.SourceType == 2 { + err = AddSysMissionReward(request.AddSysMissionReward{ + Type: 1, + RelationId: strconv.Itoa(int(claimVideo.ID)), + AchieveNum: achieveNum + 1, + CreateBy: uuid, + }, tx) + if err != nil { + tx.Rollback() + return err + } + } + tx.Commit() + return nil +} + +// 查询任务奖金 +func GetMissionBonus(code string) model.MissionBonus { + var ( + bonus model.MissionBonus + ) + global.MG_DB.Model(&model.Bill{}).Select("sum(bill.price) total").Joins("inner join `order` b on bill.order_id=b.order_id and b.code=?", code).Where("bill.status=2 and bill.type=1").Scan(&bonus) + return bonus +} + +func GetMissionStatusExcept(mission model.MissionDetail, uuid string) (except string) { + if mission.Status != 2 { + except = "当前时间,任务不可接" + return except + } + if mission.HireType == 1 && mission.ClaimStock <= mission.ClaimNum { + except = "可接人数已满额" + return except + } + + if !errors.Is(global.MG_DB.Model(&model.MissionClaim{}).Where("create_by = ? AND mission_id = ?", uuid, mission.ID).First(&model.MissionClaim{}).Error, gorm.ErrRecordNotFound) { // 判断email是否注册 + return "任务已接" + } + + if mission.HireType == 2 { + var total int64 + global.MG_DB.Model(&model.MissionClaim{}).Where("create_by = ? AND mission_id = ? and hire_type = 2", uuid, mission.ID).Count(&total) + if total >= 10 { + return "进行中任务已达上限" + } + } + + if mission.GoodsStatus != 1 { + except = "商品已下架,任务不可接" + return except + } + + //费用待发放 + + //费用已发放 + + return "" +} + +func GetMissionBonusAndSales(missionId uint) (model.MissionBonus, int64, int64) { + var ( + claimList []model.MissionClaim + codes []string + achieveNums int64 + bonus model.MissionBonus + claimNum int64 + ) + global.MG_DB.Model(&model.MissionClaim{}).Where("mission_id = ?", missionId).Find(&claimList) + for _, vClaim := range claimList { + codes = append(codes, vClaim.ClaimNo) + achieveNums += vClaim.AchieveNum + } + claimNum = int64(len(claimList)) + + global.MG_DB.Model(&model.Bill{}).Joins("INNER JOIN `order` ON `order`.order_id = bill.order_id"). + Select("SUM(bill.price) total,COUNT(DISTINCT bill.user_id) user_total").Where("bill.status=2 and bill.type=1 and `order`.`code` IN (?)", codes).Scan(&bonus) + return bonus, achieveNums, claimNum +} + +func getMissionClaimRewardUnfinished(uuid string) (error, float64) { + var ( + err error + result float64 + ) + err = global.MG_DB.Model(&model.MissionClaim{}).Where("create_by = ?", uuid).Select("SUM(reward_unfinished) as reward_unfinished").Scan(&result).Error + return err, result +} + +func GetMissionClaimStatusExcept(res model.MissionClaimDetail) string { + var ( + statusExcept string + ) + switch res.Status { + //状态 1:已领取待发货 2:已发货 3:已收货推广中 + case 1: + statusExcept = "等待样品发货" + case 2: + statusExcept = "等待链接上传" + if res.Mission.HireType == 1 { + if res.Video.ID == 0 { + statusExcept = "等待视频上传" + } else { + switch res.Video.Status { + case 1: + statusExcept = "等待视频审核" + case 2: + + case 3: + statusExcept = "视频审核不通过" + } + } + } + case 3: + statusExcept = "链接已上传" + //todo 查看奖励发放状态 + if res.Mission.HireType == 1 { + switch res.Video.RewardStatus { + case 1: + statusExcept = "费用待发放" + case 2: + statusExcept = "费用已发放" + } + } + } + + return statusExcept +} diff --git a/service/notify.go b/service/notify.go new file mode 100644 index 0000000..75bc61c --- /dev/null +++ b/service/notify.go @@ -0,0 +1,24 @@ +package service + +import ( + "pure/global" + "pure/model" + "pure/model/request" +) + +func GetNotifyList(userId string, info *request.SearchNotify) ([]model.Notify, int64, error) { + var ( + err error + total int64 + result []model.Notify + ) + limit := info.PageSize + offset := info.PageSize * (info.Page - 1) + db := global.MG_DB.Model(&model.Notify{}).Where("user_id = ?", userId) + if info.RelationType != "" { + db = db.Where("relation_type = ?", info.RelationType) + } + _ = db.Count(&total).Error + err = db.Order("id DESC").Offset(offset).Limit(limit).Find(&result).Error + return result, total, err +} diff --git a/service/order.go b/service/order.go new file mode 100644 index 0000000..47fc6cd --- /dev/null +++ b/service/order.go @@ -0,0 +1,459 @@ +package service + +import ( + "encoding/json" + "errors" + "fmt" + "os" + "strings" + "sync/atomic" + "time" + + "github.com/plutov/paypal" + "github.com/w3liu/go-common/constant/timeformat" + + "pure/dto" + "pure/global" + "pure/model" + "pure/model/request" + "pure/utils" +) + +func GetOrderData(userId string, info *request.SceneParams) (dto.OrderData, error) { + var ( + // err error + result dto.OrderData + ) + // TODO 全部数据包含哪些状态 + switch info.Scene { + case "my": + result.Unship, _ = getOrderCount(userId, &request.SearchOrderList{Status: 2}) + result.Shipped, _ = getOrderCount(userId, &request.SearchOrderList{Status: 3}) + result.Finished, _ = getOrderCount(userId, &request.SearchOrderList{Status: 4}) + result.Cancel, _ = getOrderCount(userId, &request.SearchOrderList{Status: 5}) + default: + result.All, _ = getOrderCount(userId, &request.SearchOrderList{Status: 0}) + result.Unship, _ = getOrderCount(userId, &request.SearchOrderList{Status: 2}) + result.Shipped, _ = getOrderCount(userId, &request.SearchOrderList{Status: 3}) + result.Finished, _ = getOrderCount(userId, &request.SearchOrderList{Status: 4}) + result.Cancel, _ = getOrderCount(userId, &request.SearchOrderList{Status: 5}) + } + return result, nil +} + +func getOrderCount(userId string, info *request.SearchOrderList) (int64, error) { + var ( + err error + result int64 + ) + db := global.MG_DB.Model(&model.Order{}).Joins("INNER JOIN mission_claim ON mission_claim.claim_no = `order`.`code`"). + Where("`order`.`status` IN (2,3,4,5) AND mission_claim.create_by = ?", userId) + if info.Status != 0 { + db = db.Where("`order`.status = ?", info.Status) + } + if info.Code != "" { + db = db.Where("`order`.`code` = ?", info.Code) + } + switch info.Group { + case "user": // 下单人数 + db = db.Group("`order`.user_id") + err = db.Count(&result).Error + default: + err = db.Count(&result).Error + } + return result, err +} + +func GetOrderList(userId string, info *request.SearchOrderList) (error, any, int64) { + var ( + err error + data []model.OrderList + total int64 + ) + limit := info.PageSize + offset := info.PageSize * (info.Page - 1) + db := global.MG_DB.Model(&model.Order{}).Joins("INNER JOIN mission_claim ON mission_claim.claim_no = `order`.`code`"). + Where("`order`.`status` IN (2,3,4,5) AND mission_claim.create_by = ?", userId) + if info.Status != 0 { + db = db.Where("`order`.`status` = ?", info.Status) + } + if info.Code != "" { + db = db.Where("`order`.`code` = ?", info.Code) + } + err = db.Order("order.id desc").Offset(offset).Limit(limit).Find(&data).Error + if err != nil { + return errors.New("获取订单失败"), data, total + } + if len(data) == 0 { + return nil, data, total + } + var orderIds, userIds, claimNos, platforms []string + for _, val := range data { + orderIds = append(orderIds, val.OrderID) + userIds = append(userIds, val.UserID) + if val.Code != "" { + claimNos = append(claimNos, val.Code) + } + if val.Platform != "" { + platforms = append(platforms, val.Platform) + } + } + var ( + orderGoodsList []model.OrderGoodsDetail + goodsMap = make(map[string]model.OrderGoodsDetail) + ) + err = global.MG_DB.Model(&model.OrderGoods{}).Where("order_id IN (?)", orderIds).Find(&orderGoodsList).Error + if err != nil { + return errors.New("获取订单商品信息失败"), data, total + } + for _, goods := range orderGoodsList { + goodsMap[goods.OrderID] = goods + } + var ( + users []model.UserSimple + userMap = make(map[string]model.UserSimple) + ) + err = global.MG_DB.Model(&model.User{}).Where("`type` = 'customer' AND uuid IN (?)", userIds).Find(&users).Error + if err != nil { + return errors.New("获取订单用户信息失败"), data, total + } + for _, user := range users { + userMap[user.UUID.String()] = user + } + var ( + missions []model.MissionClaimInfo + hireRatioMap = make(map[string]float64) + ) + err = global.MG_DB.Model(&model.MissionClaim{}).Select("mission_claim.claim_no,mission_claim.mission_id,b.hire_type,b.hire_money,b.hire_ratio"). + Joins("inner join mission b on mission_claim.mission_id=b.id").Where("claim_no IN (?) AND b.hire_type = 2", claimNos).Find(&missions).Error + if err != nil { + return errors.New("获取任务详情失败"), data, total + } + for _, val := range missions { + hireRatioMap[val.ClaimNo] = val.HireRatio + } + dictMap := getDictMap("release_channel", platforms) + for v := range data { + if val, ok := goodsMap[data[v].OrderID]; ok { + data[v].Goods = val + } + if val, ok := userMap[data[v].UserID]; ok { + data[v].User = val + } + if val, ok := hireRatioMap[data[v].Code]; ok { + data[v].InfluencerAmount = utils.FormatFloatToString(data[v].PaidPrice * val / 100) + } + if val, ok := dictMap[data[v].Platform]; ok { + data[v].Platform = val + } + } + return nil, data, total +} + +func GetOrderDetail(userId string, info *request.GetOrderParams) (error, model.OrderDetail) { + var ( + err error + data model.OrderDetail + tCommod model.TbGoods + ) + err = global.MG_DB.Model(&model.Order{}).Joins("INNER JOIN mission_claim ON mission_claim.claim_no = `order`.`code`"). + Where("mission_claim.create_by = ? AND order_id = ?", userId, info.OrderID).Find(&data).Error + if err != nil { + return errors.New("获取订单失败"), data + } + err = global.MG_DB.Model(&model.OrderAddress{}).Where("order_id=?", info.OrderID).Find(&data.Address).Error + if err != nil { + return errors.New("获取订单地址失败"), data + } + err = global.MG_DB.Model(&model.OrderGoods{}).Where("order_id=?", info.OrderID).Find(&data.Goods).Error + if err != nil { + return errors.New("获取订单商品信息失败"), data + } + err = global.MG_DB.Model(&model.OrderDeliver{}).Where("order_id=?", info.OrderID).Find(&data.Deliver).Error + if err != nil { + return errors.New("获取发货信息失败"), data + } + if data.Code != "" { + var mission model.MissionClaimInfo + _ = global.MG_DB.Model(&model.MissionClaim{}).Joins("inner join mission b on mission_claim.mission_id=b.id"). + Select("mission_claim.claim_no,mission_claim.mission_id,b.hire_type,b.hire_money,b.hire_ratio").Where("claim_no = ? AND b.hire_type = 2", data.Code).First(&mission) + if mission.MissionId != 0 { + amount := data.PaidPrice * mission.HireRatio / 100 + data.InfluencerAmount = utils.FormatFloatToString(amount) + } + } + if data.Platform != "" { + data.Platform = GetSysDictDataLabel("release_channel", data.Platform) + } + global.MG_DB.Model(&model.TbGoods{}).Where("id=?", data.CommodID).Find(&tCommod) + global.MG_DB.Model(&model.SellerStore{}).Select("store_no,`type`,email").Where("store_no = ?", tCommod.StoreNo).Find(&data.Store) + _ = global.MG_DB.Model(&model.OrderPostSale{}).Select("id,order_id,status,remark,examine_time,refund_time,refund_status,created_at").Where("order_id = ? AND status IN (1,2,3)", data.OrderID).First(&data.PostSale).Error + if data.PayTime != nil { + data.Bill, _ = getBillView(data.OrderID) + } + data.Chain = model.Chain{Address: "b714e5508531a7b50d0696abdc83d2333bd896db24f68eb1470bb9529390ef3e"} + return nil, data +} + +func GetOrderGoods(userId string, info *request.GetOrderParams) (error, model.OrderGoodsDetail) { + var ( + err error + order model.Order + result model.OrderGoodsDetail + ) + err = global.MG_DB.Model(&model.Order{}).Joins("INNER JOIN mission_claim ON mission_claim.claim_no = `order`.`code`"). + Where("mission_claim.create_by = ? AND order_id = ?", userId, info.OrderID).Find(&order).Error + if err != nil { + return errors.New("获取订单失败"), result + } + err = global.MG_DB.Model(&model.OrderGoods{}).Where("order_id = ?", info.OrderID).Find(&result).Error + if err != nil { + return errors.New("获取订单商品信息失败"), result + } + err = global.MG_DB.Model(&model.OrderGoodsSpecs{}).Where("order_goods_id = ?", result.ID).Find(&result.GoodsSpecs).Error + if err != nil { + return errors.New("获取订单商品规格信息失败"), result + } + attributeValues := make(map[uint]*model.TbAttributeValueJson) + for i := 0; i < len(result.GoodsSpecs); i++ { + var attributeList []model.TbAttributeDetail + err = json.Unmarshal([]byte(result.GoodsSpecs[i].Specs), &attributeList) + if err != nil { + return err, result + } + if i == 0 { + var attributes []uint + for j := 0; j < len(attributeList); j++ { + attributes = append(attributes, attributeList[j].AttributeId) + } + orderSql := "FIELD(id" + for _, attribute := range attributes { + orderSql += fmt.Sprintf(",'%v'", attribute) + } + orderSql += ")" + err = global.MG_DB.Model(&model.TbAttribute{}).Select("id,`name`").Where("id IN (?)", attributes).Order(orderSql).Find(&result.Attributes).Error + if err != nil { + return err, result + } + } + for _, attribute := range attributeList { + if _, ok := attributeValues[attribute.AttributeId]; ok { + if !strings.Contains(attributeValues[attribute.AttributeId].Str, attribute.Value) { + attributeValues[attribute.AttributeId].Str += attribute.Value + "," + attributeValues[attribute.AttributeId].Items = append(attributeValues[attribute.AttributeId].Items, model.TbAttributeValueItem{Id: attribute.ValueId, Name: attribute.Value, Image: result.GoodsSpecs[i].Image}) + } + } else { + attributeValues[attribute.AttributeId] = &model.TbAttributeValueJson{Items: []model.TbAttributeValueItem{{Id: attribute.ValueId, Name: attribute.Value, Image: result.GoodsSpecs[i].Image}}, Str: attribute.Value + ","} + } + } + } + for i := 0; i < len(result.Attributes); i++ { + if val, ok := attributeValues[result.Attributes[i].ID]; ok { + result.Attributes[i].Values = val.Items + } + } + return err, result +} + +// 用户提现 +func CreatePayOutPayer(paypalName, amount, withdID string) (error, *paypal.PayoutResponse) { + var ( + err error + c *paypal.Client + ) + if global.MG_CONFIG.Paypal.Env == "SandBox" { + c, err = paypal.NewClient(global.MG_CONFIG.Paypal.ClientID, global.MG_CONFIG.Paypal.Secret, paypal.APIBaseSandBox) + if err != nil { + return err, nil + } + } else { + c, err = paypal.NewClient(global.MG_CONFIG.Paypal.ClientID, global.MG_CONFIG.Paypal.Secret, paypal.APIBaseLive) + if err != nil { + return err, nil + } + } + _, err = c.GetAccessToken() + if err != nil { + return err, nil + } + payout := paypal.Payout{} + send := &paypal.SenderBatchHeader{ + SenderBatchID: withdID, + } + item := make([]paypal.PayoutItem, 1) + fmt.Println(amount) + item[0] = paypal.PayoutItem{ + RecipientType: "EMAIL", + Receiver: paypalName, + Amount: &paypal.AmountPayout{ + Currency: "USD", // 收款类型 + Value: amount, // 收款数量 + }, + Note: "打款", + } + payout.SenderBatchHeader = send + payout.Items = item + fmt.Println(payout.Items[0].Amount) + resp, err := c.CreateSinglePayout(payout) + if err != nil { + fmt.Println(err.Error()) + fmt.Println(resp) + return err, nil + } + return err, resp +} + +// 生成24位订单号 +// 前面17位代表时间精确到毫秒,中间3位代表进程id,最后4位代表序号 +var num int64 + +func Generate() string { + t := time.Now() + s := t.Format(timeformat.Continuity) + m := t.UnixNano()/1e6 - t.UnixNano()/1e9*1e3 + ms := sup(m, 3) + p := os.Getpid() % 1000 + ps := sup(int64(p), 3) + i := atomic.AddInt64(&num, 1) + r := i % 10000 + rs := sup(r, 4) + n := fmt.Sprintf("%s%s%s%s", s, ms, ps, rs) + return n +} + +// 对长度不足n的数字前面补0 +func sup(i int64, n int) string { + m := fmt.Sprintf("%d", i) + for len(m) < n { + m = fmt.Sprintf("0%s", m) + } + return m +} + +func GetOrderTotalList(info *request.SearchOrderList) (error, any) { + var ( + err error + data model.OrderTotal + ) + if info.Code == "" { + return errors.New("任务码不可为空"), nil + } + db := global.MG_DB.Model(&model.Order{}) + if info.Status != 0 { + db = db.Where("status=?", info.Status) + } + if info.Code != "" { + db = db.Where("code=?", info.Code) + } + err = db.Select("sum(case when `status`=2 then 1 else 0 end) status2,sum(case when `status`=3 then 1 else 0 end) status3,sum(case when `status`=4 then 1 else 0 end) status4").Scan(&data).Error + if err != nil { + return errors.New("获取订单失败"), data + } + return nil, data +} + +func GetMissionOrderStatistic(userId, claimNo string) (dto.MissionOrderStatistic, error) { + var ( + err error + claim model.MissionClaim + statistic model.DtStatisticOrder + result dto.MissionOrderStatistic + ) + err, claim = getMissionClaim(userId, claimNo) + if err != nil { + return result, err + } + statistic, _ = getStatisticsOrderByValues([]string{}, "", "2", claimNo) + visits := GetGoodsVisit(claimNo) + result = dto.MissionOrderStatistic{ + OrderNum: statistic.OrderNum, + OrderDoneNum: statistic.OrderDoneNum, + OrderMoney: statistic.OrderMoney, + SettleReward: claim.RewardFinished, + TransitReward: claim.RewardUnfinished, + RewardRatio: 0.1, + Uv: visits, + SellNum: claim.AchieveNum, + } + result.OrderUserNum, _ = getOrderCount(userId, &request.SearchOrderList{Group: "user", Code: claimNo}) + + return result, nil +} + +func getStatisticsOrder(value, unit, relationId string) (model.DtStatisticOrder, error) { + var ( + err error + result model.DtStatisticOrder + ) + db := global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`value` = ? AND `unit` = ?", value, unit) + if relationId != "" { + db = db.Where("`relation_id` = ?", relationId) + } + err = db.First(&result).Error + return result, err +} + +// 累计销量 "all","all","goods_id" +// 30天销量 "day","30","goods_id" +func GetStatisticsOrderByValues(unit string, value int, relationId string) (model.DtStatisticOrder, error) { + if value < 0 { + return model.DtStatisticOrder{}, errors.New("value error") + } + var values = make([]string, 0) + now := time.Now() + switch unit { + case "day": + if value == 0 { + values = append(values, now.Format("20060102")) + } else { + tmp := now.AddDate(0, 0, -value) + for i := 0; i < value; i++ { + values = append(values, tmp.Format("20060102")) + tmp = tmp.AddDate(0, 0, 1) + } + } + case "month": + + } + return getStatisticsOrderByValues(values, "day", "", relationId) +} + +func getStatisticsOrderByValues(values []string, unit, t, relationId string) (model.DtStatisticOrder, error) { + var ( + err error + result model.DtStatisticOrder + ) + db := global.MG_DB.Model(&model.DtStatisticOrder{}).Where("`unit` = ?", unit). + Select("SUM(order_num) as order_num,SUM(order_done_num) as order_done_num,SUM(order_money) as order_money,SUM(sale_volume) as sale_volume,SUM(settle_reward) as settle_reward,SUM(order_cancel_num) as order_cancel_num,SUM(order_cancel_money) as order_cancel_money") + if len(values) != 0 { + db = db.Where("`value` IN (?) ", values) + } + if t != "" { + db = db.Where("`type` = ?", t) + } + if relationId != "" { + db = db.Where("`relation_id` = ?", relationId) + } + err = db.First(&result).Error + return result, err +} + +// 获取网红维度订单数据统计 +func getStatisticsOrderInfluence(uuid, unit string, timeArea []string) (model.DtStatisticOrder, error) { + var ( + err error + result model.DtStatisticOrder + ) + db := global.MG_DB.Model(&model.DtStatisticOrder{}).Joins("INNER JOIN mission_claim ON mission_claim.claim_no = dt_statistic_order.relation_id"). + Where("dt_statistic_order.`type` = 2 AND mission_claim.create_by = ? AND dt_statistic_order.`unit` = ?", uuid, unit) + if len(timeArea) == 2 { + db = db.Where("dt_statistic_order.created_at >= ? AND dt_statistic_order.created_at < ?", timeArea[0], timeArea[1]) + } + err = db.Select("SUM(dt_statistic_order.order_num) as order_num,SUM(dt_statistic_order.order_done_num) as order_done_num,SUM(dt_statistic_order.order_money) as order_money,SUM(dt_statistic_order.sale_volume) as sale_volume,SUM(dt_statistic_order.settle_reward) as settle_reward,SUM(dt_statistic_order.order_cancel_num) as order_cancel_num,SUM(dt_statistic_order.order_cancel_money) as order_cancel_money").First(&result).Error + return result, err +} + +func GetGoodsVisit(claimNo string) (count int64) { + global.MG_DB.Model(&model.GoodsVisit{}).Where("claim_no=?", claimNo).Count(&count) + return count +} diff --git a/service/redis_tools.go b/service/redis_tools.go new file mode 100644 index 0000000..ebdbf4f --- /dev/null +++ b/service/redis_tools.go @@ -0,0 +1,355 @@ +package service + +import ( + "fmt" + "pure/global" + "strconv" + "time" + + "github.com/go-redis/redis" +) + +// RedisGet ... +func RedisGet(key string) string { + result, err := global.MG_REDIS.Get(key).Result() + if err != nil { + return "" + } + return result +} + +func RedisSet(key string, value interface{}, expiration time.Duration) string { + result, err := global.MG_REDIS.Set(key, value, expiration).Result() + if err != nil { + //global.MG_LOG.Error("Redis Set Error:", zap.Any("err", err)) + return "" + } + return result +} + +func RedisDel(key ...string) (int64, error) { + result, err := global.MG_REDIS.Del(key...).Result() + if err != nil { + //global.MG_LOG.Error("Redis Del Error:", zap.Any("err", err)) + return -1, err + } + return result, err +} + +func RedisZAdd1(client *redis.Client, key string, values map[float64]interface{}) (int64, error) { + var members []redis.Z + for scale, value := range values { + members = append(members, redis.Z{ + Score: scale, + Member: value, + }) + } + result, err := client.ZAdd(key, members...).Result() + if err != nil { + //global.MG_LOG.Error("Redis ZAdd Error:", zap.Any("err", err)) + return 0, err + } + return result, nil +} + +func RedisDel2(client *redis.Client, key ...string) (int64, error) { + result, err := client.Del(key...).Result() + if err != nil { + //global.MG_LOG.Error("Redis2 Del Error:", zap.Any("err", err)) + return -1, err + } + return result, err +} + +// RedisHashSet 向key的hash中添加元素field的值 +func RedisHashSet(key, field string, data interface{}) error { + err := global.MG_REDIS.HSet(key, field, data).Err() + if err != nil { + //global.MG_LOG.Error("Redis HSet Error:", zap.Any("err", err)) + return err + } + return nil +} + +// RedisBatchHashSet 批量向key的hash添加对应元素field的值 +func RedisBatchHashSet(key string, fields map[string]interface{}) (error, string) { + val, err := global.MG_REDIS.HMSet(key, fields).Result() + if err != nil { + //global.MG_LOG.Error("Redis HMSet Error:", zap.Any("err", err)) + return err, "" + } + return nil, val +} + +func RedisHDel(key string, fields ...string) (error, int64) { + result, err := global.MG_REDIS.HDel(key, fields...).Result() + if err != nil { + //global.MG_LOG.Error("Redis HMSet Error:", zap.Any("err", err)) + return err, 0 + } + return nil, result +} + +func RedisHSet(key, field string, value interface{}) (error, bool) { + val, err := global.MG_REDIS.HSet(key, field, value).Result() + if err != nil { + //global.MG_LOG.Error("Redis HSet Error:", zap.Any("err", err)) + return err, false + } + return nil, val +} + +func RedisBatchHashSet1(key string, fields map[string]interface{}) (error, string) { + val, err := global.MG_REDIS.HMSet(key, fields).Result() + if err != nil { + //global.MG_LOG.Error("Redis HMSet Error:", zap.Any("err", err)) + return err, "" + } + return nil, val +} + +// RedisHashGet 通过key获取hash的元素值 +func RedisHashGet(key, field string) string { + val, err := global.MG_REDIS.HGet(key, field).Result() + if err != nil { + return "" + } + return val +} + +func RedisHashMGet(key string, fields ...string) []interface{} { + val, err := global.MG_REDIS.HMGet(key, fields...).Result() + if err != nil { + return nil + } + return val +} + +//HGetAll +func RedisHashGetAll(key string) map[string]string { + val, err := global.MG_REDIS.HGetAll(key).Result() + if err != nil { + return nil + } + return val +} + +// RedisBatchHashGet 批量获取key的hash中对应多元素值 +func RedisBatchHashGet(key string, fields ...string) map[string]interface{} { + resMap := make(map[string]interface{}) + for _, field := range fields { + val, err := global.MG_REDIS.HGet(key, fmt.Sprintf("%s", field)).Result() + if err == nil && val != "" { + resMap[field] = val + } + } + return resMap +} + +func RedisLPush(key string, values ...interface{}) (int64, error) { + result, err := global.MG_REDIS.LPush(key, values...).Result() + if err != nil { + //global.MG_LOG.Error("Redis LPush Error:", zap.Any("err", err)) + return 0, err + } + return result, nil +} + +func RedisLPop(key string) (error, string) { + result, err := global.MG_REDIS.LPop(key).Result() + if err != nil { + return err, "" + } + return err, result +} + +// RedisSAdd 无序集合添加 +func RedisSAdd(key string, values ...interface{}) (int64, error) { + result, err := global.MG_REDIS.SAdd(key, values...).Result() + if err != nil { + //global.MG_LOG.Error("Redis LPush Error:", zap.Any("err", err)) + return 0, err + } + return result, nil +} + +func RedisSIsMember(key string, value interface{}) (bool, error) { + result, err := global.MG_REDIS.SIsMember(key, value).Result() + if err != nil { + //global.MG_LOG.Error("Redis LPush Error:", zap.Any("err", err)) + return false, err + } + return result, nil +} + +func RedisSRem(key string, values ...interface{}) (int64, error) { + result, err := global.MG_REDIS.SRem(key, values...).Result() + if err != nil { + return 0, err + } + return result, err +} + +// RedisSMembers 从无序集合中获取数据 +func RedisSMembers(key string) ([]string, error) { + val, err := global.MG_REDIS.SMembers(key).Result() + if err != nil { + //global.MG_LOG.Error("Redis SMembers Error:", zap.Any("err", err)) + return nil, err + } + return val, nil +} + +// RedisZAdd 有序集合添加 +func RedisZAdd(key string, values map[float64]interface{}) (int64, error) { + var members []redis.Z + for scale, value := range values { + members = append(members, redis.Z{ + Score: scale, + Member: value, + }) + } + result, err := global.MG_REDIS.ZAdd(key, members...).Result() + if err != nil { + //global.MG_LOG.Error("Redis ZAdd Error:", zap.Any("err", err)) + return 0, err + } + return result, nil +} + +func RedisZAdd2(key string, values ...global.RedisValueScore) (int64, error) { + var members []redis.Z + for _, value := range values { + members = append(members, redis.Z{ + Score: value.Score, + Member: value.Value, + }) + } + result, err := global.MG_REDIS.ZAdd(key, members...).Result() + if err != nil { + //global.MG_LOG.Error("Redis ZAdd Error:", zap.Any("err", err)) + return 0, err + } + return result, nil +} + +func RedisZRem(client *redis.Client, key string, values ...interface{}) (int64, error) { + result, err := client.ZRem(key, values...).Result() + if err != nil { + return 0, err + } + return result, err +} + +func RedisZCard(key string) (int64, error) { + result, err := global.MG_REDIS.ZCard(key).Result() + if err != nil { + //global.MG_LOG.Error("Redis ZAdd Error:", zap.Any("err", err)) + return 0, err + } + return result, nil +} + +func RedisZRange(key string, start, stop int64, sort string) ([]interface{}, error) { + var val = make([]interface{}, 0) + if sort == "asc" { //scale 正序 + result, err := global.MG_REDIS.ZRangeWithScores(key, start, stop).Result() + if err != nil { + //global.MG_LOG.Error("Redis ZPopMax Error:", zap.Any("err", err)) + return val, err + } + for _, z := range result { + val = append(val, z.Member) + } + } else { //scale 倒序 + result, err := global.MG_REDIS.ZRevRange(key, start, stop).Result() + if err != nil { + //global.MG_LOG.Error("Redis ZPopMax Error:", zap.Any("err", err)) + return val, err + } + for _, z := range result { + val = append(val, z) + } + return val, nil + } + + return val, nil +} + +func RedisZRangeByScoreWithScores(client *redis.Client, key string, start, stop int64, offset, limit int, sort string) ([]interface{}, error) { + var ( + err error + startStr, stopStr string + //flag string + result []redis.Z + val = make([]interface{}, 0) + ) + if start > 0 { + startStr = strconv.FormatInt(start, 10) + } else { + startStr = "-inf" + } + if stop > 0 { + stopStr = strconv.FormatInt(stop, 10) + } else { + stopStr = "+inf" + } + if start != stop { + stopStr = "(" + stopStr + } + if sort == "asc" { //scale 正序 + result, err = client.ZRangeByScoreWithScores(key, redis.ZRangeBy{ + Min: startStr, + Max: stopStr, + Offset: int64(offset), + Count: int64(limit), + }).Result() + if err != nil { + //global.MG_LOG.Error("Redis ZRangeByScoreWithScores Error:", zap.Any("err", err)) + return val, err + } + } else { + result, err = client.ZRevRangeByScoreWithScores(key, redis.ZRangeBy{ + Min: startStr, + Max: stopStr, + Offset: int64(offset), + Count: int64(limit), + }).Result() + if err != nil { + //global.MG_LOG.Error("Redis ZRangeByScoreWithScores Error:", zap.Any("err", err)) + return val, err + } + } + for _, z := range result { + val = append(val, z.Member) + } + return val, nil +} + +// RedisIncr 获取自增唯一ID +func RedisIncr(key string) int { + val, err := global.MG_REDIS.Incr(key).Result() + if err != nil { + //global.MG_LOG.Error("Redis RedisIncr Error:", zap.Any("err", err)) + } + return int(val) +} + +func RedisTest(key string, values ...interface{}) { + result, err := global.MG_REDIS.SRem(key, values...).Result() + if err != nil { + fmt.Println(err) + } + fmt.Println(result) +} + +func RedisSetNX(key string, value interface{}, expiration time.Duration) (error, bool) { + val, err := global.MG_REDIS.SetNX(key, value, expiration).Result() + if err != nil { + if err != nil { + fmt.Println("Redis SetNX Error:", err.Error()) + } + return err, false + } + return nil, val +} diff --git a/service/seller_store.go b/service/seller_store.go new file mode 100644 index 0000000..50b3441 --- /dev/null +++ b/service/seller_store.go @@ -0,0 +1,24 @@ +package service + +import ( + "pure/global" + "pure/model" +) + +func GetSellerStoreInfo(uuid string) (err error, res model.SellerStoreInfo) { + err = global.MG_DB.Model(&model.SellerStore{}).Select("store_no,type,email,create_by").Where("create_by = ?", uuid).First(&res).Error + return +} + +func getSellerStoreInfoMap(uuids []string) (err error, res map[string]model.SellerStoreInfo) { + var list []model.SellerStoreInfo + err = global.MG_DB.Model(&model.SellerStore{}).Select("store_no,type,email,create_by").Where("create_by IN (?)", uuids).Find(&list).Error + if err != nil { + return + } + res = make(map[string]model.SellerStoreInfo) + for i := 0; i < len(list); i++ { + res[list[i].CreateBy] = list[i] + } + return +} diff --git a/service/sys_brochure.go b/service/sys_brochure.go new file mode 100644 index 0000000..68eb35a --- /dev/null +++ b/service/sys_brochure.go @@ -0,0 +1,11 @@ +package service + +import ( + "pure/global" + "pure/model" +) + +func GetSysBrochure(t string) (err error, brochure model.SysBrochure) { + err = global.MG_DB.Model(&model.SysBrochure{}).Where("`type` = ?", t).First(&brochure).Error + return +} diff --git a/service/sys_mission_reward.go b/service/sys_mission_reward.go new file mode 100644 index 0000000..f6ed117 --- /dev/null +++ b/service/sys_mission_reward.go @@ -0,0 +1,133 @@ +package service + +import ( + "errors" + "fmt" + "gorm.io/gorm" + "pure/global" + "pure/model" + "pure/model/request" + "pure/model/response" +) + +func AddSysMissionReward(params request.AddSysMissionReward, tx *gorm.DB) error { + switch params.Type { + case 1: + //上传视频 + var ( + rewardData, checkReward model.SysMissionReward + bonusMap map[int64]float64 + err error + bonus float64 + ) + bonusMap = map[int64]float64{ + 1: 0.5, + 3: 1.0, + 5: 2.0, + } + if _, ok := bonusMap[params.AchieveNum]; !ok { + return err + } + bonus = bonusMap[params.AchieveNum] + err = tx.Model(&model.SysMissionReward{}). + Where("create_by = ? and achieve_num = ? and type = ?", params.CreateBy, params.AchieveNum, params.Type). + First(&checkReward).Error + if checkReward.ID > 0 { + return errors.New("不能重复提交") + } + rewardData = model.SysMissionReward{ + Title: fmt.Sprintf("上传%d次带货视频", params.AchieveNum), + Type: params.Type, + RelationId: params.RelationId, + Bonus: bonus, + Status: 1, //待发放 + AchieveNum: params.AchieveNum, + CreateBy: params.CreateBy, + } + err = tx.Model(&model.SysMissionReward{}).Create(&rewardData).Error + if err != nil { + return errors.New("提交失败") + } + case 2: + //信息完善 + return nil + case 3: + //商家任务 + return nil + } + return nil +} + +func GetSysMissionRewardList(params request.SearchSysReward, uuid string) (err error, list []model.SysMissionReward, total int64) { + limit := params.PageSize + offset := params.PageSize * (params.Page - 1) + db := global.MG_DB.Model(&model.SysMissionReward{}). + Where("create_by = ?", uuid) + if params.Status != 0 { + db = db.Where("status = ?", params.Status) + } + db.Count(&total) + var res []model.SysMissionReward + err = db.Order("id desc").Offset(offset).Limit(limit).Find(&res).Error + if err != nil { + return err, nil, 0 + } + + return err, res, total +} + +func GetSysRewardSummary(uuid string, params request.SearchSysRewardSummary) (err error, res response.SysMissionBonus) { + var ( + bonus []model.SysMissionBonus + ) + + db := global.MG_DB.Model(&model.SysMissionReward{}).Select("sum(bonus) as bonus,type,count(1) as total"). + Where("create_by = ?", uuid) + if params.Status != 0 { + db = db.Where("status = ?", params.Status) + } + err = db.Group("type").Find(&bonus).Error + if err != nil { + return errors.New("查询失败"), res + } + + db = global.MG_DB.Model(&model.SysMissionReward{}). + Where("create_by = ?", uuid) + + var recordList []model.SysMissionReward + err = db.Order("id desc").Find(&recordList).Error + if err != nil { + return errors.New("查询失败"), res + } + + res.VideoBonus.Title = "视频上传" + res.VideoBonus.AchieveMax = 5 + res.VideoBonus.MissionList = []response.SysMissionDesc{ + {Title: "上传1次带货视频", Bonus: 0.5, Description: "每个任务仅计入1次,不可重复上传", TitleEng: "Upload a sales video once", DescriptionEng: "Each task is only counted once and cannot be uploaded repeatedly"}, + {Title: "上传3次带货视频", Bonus: 1, Description: "每个任务仅计入1次,不可重复上传", TitleEng: "Upload sales videos 3 times", DescriptionEng: "Each task is only counted once and cannot be uploaded repeatedly"}, + {Title: "上传5次带货视频", Bonus: 2, Description: "每个任务仅计入1次,不可重复上传", TitleEng: "Upload sales videos 5 times", DescriptionEng: "Each task is only counted once and cannot be uploaded repeatedly"}, + } + + for _, vBonus := range bonus { + switch vBonus.Type { + case 1: + //视频上传 + var achieveNum int64 + global.MG_DB.Model(&model.MissionClaimVideo{}).Where("create_by = ? and source_type = 2 and status in (1,2)", uuid).Count(&achieveNum) + vBonus.AchieveNum = achieveNum + res.VideoBonus.SysMissionBonus = vBonus + //标记用户奖励状态 + for vi, _ := range res.VideoBonus.MissionList { + for _, vRecord := range recordList { + if res.VideoBonus.MissionList[vi].Title == vRecord.Title { + res.VideoBonus.MissionList[vi].Status = vRecord.Status + } + } + } + } + res.Total += vBonus.Total + res.TotalBonus += vBonus.Bonus + + } + return nil, res +} diff --git a/service/tags.go b/service/tags.go new file mode 100644 index 0000000..de89aa9 --- /dev/null +++ b/service/tags.go @@ -0,0 +1,49 @@ +package service + +import ( + "pure/global" + "pure/model" + "strings" +) + +func GetTagsNameByIds(ids []uint) (tags string) { + var ( + tagList []model.Tags + names []string + ) + global.MG_DB.Model(&model.Tags{}).Where("id in (?)", ids).Find(&tagList) + for _, vTag := range tagList { + names = append(names, vTag.Value) + } + + return strings.Join(names, ",") +} + +func GetTagsByIds(ids []uint) (tags []model.TagsDesc) { + var ( + tagList []model.TagsDesc + ) + global.MG_DB.Model(&model.Tags{}).Where("id in (?)", ids).Find(&tagList) + + return tagList +} + +func GetTagNamesByRelation(relationId, relationType string) string { + //params:relationType 标签类型 01-任务 02-任务视频 03-网红 + var ( + relationList []model.TagRelation + tagIds []uint + tagNames string + ) + global.MG_DB.Model(&model.TagRelation{}). + Where("relation_type = ? and relation_id = ?", relationType, relationId).Find(&relationList) + if len(relationList) == 0 { + return tagNames + } + for _, v := range relationList { + tagIds = append(tagIds, v.TagId) + } + tagNames = GetTagsNameByIds(tagIds) + + return tagNames +} diff --git a/service/tb_category.go b/service/tb_category.go new file mode 100644 index 0000000..37c78e3 --- /dev/null +++ b/service/tb_category.go @@ -0,0 +1,48 @@ +package service + +import ( + "pure/global" + "pure/model" +) + +func GetTbCategoryBreadcrumb(id uint) (error, []model.Breadcrumb) { + var ( + category model.Breadcrumb + result = make([]model.Breadcrumb, 0) + ) + err := global.MG_DB.Table("tb_category").Select("id,`name`,pid,is_leaf").Where("status = 1 AND id = ?", id).Find(&category).Error + if err != nil { + return err, nil + } + if category.Pid != 0 { + err = getTbCategoryParent(&category) + if err != nil { + return err, nil + } + } + transferBreadcrumbList(&category, &result) + return nil, result +} + +func getTbCategoryParent(breadcrumb *model.Breadcrumb) (err error) { + var tmp model.Breadcrumb + err = global.MG_DB.Table("tb_category").Select("id,`name`,pid,is_leaf").Where("status = 1 AND id = ?", breadcrumb.Pid).Find(&tmp).Error + if err != nil { + return err + } + breadcrumb.Parent = &tmp + if breadcrumb.Parent.Pid != 0 { + err = getTbCategoryParent(breadcrumb.Parent) + return err + } + return nil +} + +func transferBreadcrumbList(info *model.Breadcrumb, breadcrumbs *[]model.Breadcrumb) { + if info.ID != 0 { + *breadcrumbs = append(*breadcrumbs, *info) + if info.Parent != nil { + transferBreadcrumbList(info.Parent, breadcrumbs) + } + } +} diff --git a/service/tb_goods.go b/service/tb_goods.go new file mode 100644 index 0000000..cb2b33a --- /dev/null +++ b/service/tb_goods.go @@ -0,0 +1,146 @@ +package service + +import ( + "encoding/json" + "errors" + "fmt" + "gorm.io/gorm" + "pure/global" + "pure/model" + "pure/model/request" + "strings" +) + +func GetTbGoods(info request.Goods) (error, model.TbGoodsDetail) { + var ( + err error + result model.TbGoodsDetail + ) + if info.ID == 0 && info.SkuNo == "" { + err = errors.New("参数有误") + return err, result + } + db := global.MG_DB.Table("tb_goods").Select("id,spu_no,category_id,title,title_eng,images,content,content_text,list_price,retail_price,price_min,price_max,tags,online"). + Preload("Specs", func(db *gorm.DB) *gorm.DB { + return db.Select("id,goods_id,specs,sku_no,stock,price,image,goods_no,code").Where("status = 1") + }) + if info.ID != 0 { + db = db.Where("id = ?", info.ID) + } + if info.SkuNo != "" { + db = db.Where("spu_no = ?", info.SkuNo) + } + err = db.First(&result).Error + if err != nil { + return err, result + } + var attributeValues = make(map[uint]*model.TbAttributeValueJson) + for i := 0; i < len(result.Specs); i++ { + err = json.Unmarshal([]byte(result.Specs[i].Specs), &result.Specs[i].Attributes) + if err != nil { + return err, result + } + if i == 0 { + var attributes []uint + for j := 0; j < len(result.Specs[i].Attributes); j++ { + attributes = append(attributes, result.Specs[i].Attributes[j].AttributeId) + } + orderSql := "FIELD(id" + for _, attribute := range attributes { + orderSql += fmt.Sprintf(",'%v'", attribute) + } + orderSql += ")" + err = global.MG_DB.Model(&model.TbAttribute{}).Select("id,`name`").Where("id IN (?)", attributes).Order(orderSql).Find(&result.Attributes).Error + if err != nil { + return err, result + } + } + for _, attribute := range result.Specs[i].Attributes { + if _, ok := attributeValues[attribute.AttributeId]; ok { + if !strings.Contains(attributeValues[attribute.AttributeId].Str, attribute.Value) { + attributeValues[attribute.AttributeId].Str += attribute.Value + "," + attributeValues[attribute.AttributeId].Items = append(attributeValues[attribute.AttributeId].Items, model.TbAttributeValueItem{Name: attribute.Value, Image: result.Specs[i].Image}) + } + } else { + attributeValues[attribute.AttributeId] = &model.TbAttributeValueJson{Items: []model.TbAttributeValueItem{{Name: attribute.Value, Image: result.Specs[i].Image}}, Str: attribute.Value + ","} + } + } + } + for i := 0; i < len(result.Attributes); i++ { + if val, ok := attributeValues[result.Attributes[i].ID]; ok { + result.Attributes[i].Values = val.Items + } + } + _, result.Breadcrumb = GetTbCategoryBreadcrumb(result.CategoryId) //获取分类面包屑 + return nil, result +} + +func GetTbGoodsWithMission(uuid string, info request.Goods) (error, model.TbGoodsDetail) { + var ( + err error + result model.TbGoodsDetail + ) + if info.ID == 0 && info.SkuNo == "" { + err = errors.New("参数有误") + return err, result + } + db := global.MG_DB.Table("tb_goods").Select("id,spu_no,category_id,title,title_eng,images,content,content_text,list_price,retail_price,price_min,price_max,tags,online"). + Preload("Specs", func(db *gorm.DB) *gorm.DB { + return db.Select("id,goods_id,specs,sku_no,stock,price,image").Where("status = 1") + }) + if info.ID != 0 { + db = db.Where("id = ?", info.ID) + } + if info.SkuNo != "" { + db = db.Where("spu_no = ?", info.SkuNo) + } + err = db.First(&result).Error + if err != nil { + return err, result + } + var attributeValues = make(map[uint]*model.TbAttributeValueJson) + for i := 0; i < len(result.Specs); i++ { + err = json.Unmarshal([]byte(result.Specs[i].Specs), &result.Specs[i].Attributes) + if err != nil { + return err, result + } + if i == 0 { + var attributes []uint + for j := 0; j < len(result.Specs[i].Attributes); j++ { + attributes = append(attributes, result.Specs[i].Attributes[j].AttributeId) + } + orderSql := "FIELD(id" + for _, attribute := range attributes { + orderSql += fmt.Sprintf(",'%v'", attribute) + } + orderSql += ")" + err = global.MG_DB.Model(&model.TbAttribute{}).Select("id,`name`").Where("id IN (?)", attributes).Order(orderSql).Find(&result.Attributes).Error + if err != nil { + return err, result + } + } + for _, attribute := range result.Specs[i].Attributes { + if _, ok := attributeValues[attribute.AttributeId]; ok { + if !strings.Contains(attributeValues[attribute.AttributeId].Str, attribute.Value) { + attributeValues[attribute.AttributeId].Str += attribute.Value + "," + attributeValues[attribute.AttributeId].Items = append(attributeValues[attribute.AttributeId].Items, model.TbAttributeValueItem{Name: attribute.Value, Image: result.Specs[i].Image}) + } + } else { + attributeValues[attribute.AttributeId] = &model.TbAttributeValueJson{Items: []model.TbAttributeValueItem{{Name: attribute.Value, Image: result.Specs[i].Image}}, Str: attribute.Value + ","} + } + } + } + for i := 0; i < len(result.Attributes); i++ { + if val, ok := attributeValues[result.Attributes[i].ID]; ok { + result.Attributes[i].Values = val.Items + } + } + _, result.Breadcrumb = GetTbCategoryBreadcrumb(result.CategoryId) //获取分类面包屑 + result.CollectStatus = getGoodsCollectStatus(uuid, info.SkuNo) + return nil, result +} + +// 统计商品总销售量 +func UpdateTbGoodsSalesByGoodsId(goodsId uint, count int) { + _ = global.MG_DB.Model(&model.TbGoods{}).Where("id = ?", goodsId).UpdateColumn("sales", gorm.Expr("sales + ?", count)).Error +} diff --git a/service/user.go b/service/user.go new file mode 100644 index 0000000..13808db --- /dev/null +++ b/service/user.go @@ -0,0 +1,868 @@ +package service + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "pure/global" + "pure/initialize/api" + "pure/model" + "pure/model/request" + "pure/model/response" + "pure/utils" + "strconv" + "strings" + "time" + + uuid "github.com/satori/go.uuid" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + "golang.org/x/oauth2/instagram" +) + +func UserLogin(u *request.UserLogin) (err error, userInter *model.User) { + var user model.User + switch u.Type { + case "1": + if global.MG_CONFIG.System.Env != "prod" && u.Code == "888888" { + + } else { + resp, err := global.SMS_CLIENT.VerifyCode(context.Background(), &api.SmsCodeVerifyRequest{ + Phone: u.Phone, + Code: u.Code, + }) + if err != nil { + return err, nil + } + if resp.Code != 0 { + return errors.New("验证码验证失败"), nil + } + } + err = global.MG_DB.Where("phone = ? and appid=? and type=? and log_off_time is null", u.Phone, u.Appid, "influencer").Find(&user).Error + if err != nil { + return errors.New("获取用户失败"), nil + } + case "2": + code := RedisGet("email_code:" + u.Email) + if global.MG_CONFIG.System.Env != "prod" && u.Code == "888888" { + + } else if code != u.Code { + return errors.New("验证码验证失败"), nil + } + err = global.MG_DB.Where("email = ? and appid=? and type=? and log_off_time is null", u.Email, u.Appid, "influencer").Find(&user).Error + if err != nil { + return errors.New("获取用户失败"), nil + } + } + if user.UUID == uuid.Nil { + return errors.New("用户名或密码错误"), nil + } + return err, &user +} + +func UserRegister(u *request.UserRegister) (err error, userInter *model.User) { + var user model.User + global.MG_DB.Where("email = ? and appid=? and type=? and log_off_time is null", u.Email, u.Appid, "influencer").Find(&user) + if user.UUID == uuid.Nil { + //用户注册 + user.UUID = uuid.NewV4() + user.NickName = u.Nickname + user.Email = u.Email + user.Avatar = u.Avatar + user.Appid = u.Appid + user.Type = "influencer" + user.CountryCode = u.CountryCode + err = global.MG_DB.Model(&model.User{}).Create(&user).Error + if err != nil { + return errors.New("注册失败,请稍后再试"), nil + } + var wallet model.Wallet + wallet.UserID = user.UUID.String() + wallet.Platform = "influencer" + wallet.State = 0 + global.MG_DB.Model(&model.Wallet{}).Create(&wallet) + } else { + return errors.New("用户已存在"), nil + } + return err, &user +} + +func UserBandPhone(u *request.UserBandPhone, appid, userID string) (err error) { + if global.MG_CONFIG.System.Env != "prod" && u.Code == "888888" { + + } else { + resp, err := global.SMS_CLIENT.VerifyCode(context.Background(), &api.SmsCodeVerifyRequest{ + Phone: u.Phone, + Code: u.Code, + }) + if err != nil { + return err + } + if resp.Code != 0 { + return errors.New("验证码验证失败") + } + } + var user model.User + err = global.MG_DB.Where("phone = ? and appid=? and type=?", u.Phone, appid, "influencer").Find(&user).Error + if err != nil { + return errors.New("获取用户失败") + } + if user.UUID != uuid.Nil { + return errors.New("手机号已被绑定") + } + err = global.MG_DB.Model(&model.User{}).Where("uuid=?", userID).Update("phone", u.Phone).Error + if err != nil { + return errors.New("绑定失败") + } + return err +} + +func UserPlatformAuth(u *request.UserPlatformAuth, userID string) (err error) { + var ( + platformJson string + uMap = make(map[string]interface{}) + user model.UserSimple + platforms []request.Platform + dictData []model.SysDictData + ) + err = global.MG_DB.Model(&model.User{}).Where("uuid=?", userID).Find(&user).Error + if err != nil { + return errors.New("获取用户失败") + } + err = global.MG_DB.Model(&model.SysDictData{}).Where("type_code=?", "release_channel").Find(&dictData).Error + if err != nil { + return errors.New("获取用户失败") + } + err = json.Unmarshal([]byte(user.Platform), &platforms) + t := time.Now() + u.Platform.CreatedAt = &t + u.Platform.IsAuth = false + if err != nil { + for i := 0; i < len(dictData); i++ { + platforms = append(platforms, request.Platform{ + Platform: dictData[i].Value, + }) + } + for i := 0; i < len(platforms); i++ { + if platforms[i].Platform == u.Platform.Platform { + platforms[i] = u.Platform + platforms[i].CreatedAt = &t + } + } + // platforms = append(platforms, u.Platform) + } else { + for i := 0; i < len(platforms); i++ { + if platforms[i].Platform == u.Platform.Platform && !platforms[i].IsAuth { + platforms[i] = u.Platform + platforms[i].CreatedAt = &t + } + } + } + platformByte, err := json.Marshal(platforms) + if err != nil { + return errors.New("平台认证格式不正确") + } + platformJson = string(platformByte) + uMap["platform"] = platformJson + uMap["tags"] = u.Tags + tx := global.MG_DB.Begin() + err = tx.Model(&model.User{}).Where("uuid=?", userID).Updates(uMap).Error + if err != nil { + return errors.New("提交失败") + } + var platformAuth model.PlatformAuth + platformAuth.UserID = userID + platformAuth.Platform = u.Platform + platformAuth.Status = "0" + err = tx.Model(&model.PlatformAuth{}).Create(&platformAuth).Error + if err != nil { + tx.Rollback() + return errors.New("提交失败") + } + tx.Commit() + return nil +} + +func UserAuthorized(u *request.UserAuthorized) (Iuser model.User, err error) { + var ( + aceessToken string + userID string + provider model.Provider + user model.ProviderUser + providerList model.ClentProvider + application model.Application + ) + err = global.MG_DB.Where("appid=?", u.Appid).Find(&application).Error + if err != nil { + return Iuser, errors.New("获取应用失败") + } + if application.ID == 0 { + return Iuser, errors.New("应用不存在") + } + err = json.Unmarshal([]byte(application.Provider), &providerList) + if err != nil { + return Iuser, errors.New("获取应用失败") + } + switch u.Client { + case "android": + for _, v := range providerList.Android { + if v.Code == u.Platform { + provider = v + } + } + case "ios": + for _, v := range providerList.Ios { + if v.Code == u.Platform { + provider = v + } + } + default: + for _, v := range providerList.Web { + if v.Code == u.Platform { + provider = v + } + } + } + if provider.Code == "" { + return Iuser, errors.New("平台不存在") + } + if u.Uuid == "" { + if u.Code != "" { + //换取token + err, aceessToken, userID = GetAccessToken(provider, u.Code) + if err != nil { + fmt.Println(err.Error()) + return Iuser, errors.New("获取token失败") + } + } + if u.Token != "" { + aceessToken = u.Token + } + //换取用户信息 + if provider.UserInfoURI != "" { + err, user = GetUserInfo(provider, aceessToken, userID) + if err != nil { + return Iuser, errors.New("获取用户信息失败") + } + if user.Avatar == "" { + user.Avatar = "https://minio.sumweal.com/nft/221109/C82M980ZLumQCzt857yxur92iAsGdCc7271sDn8MPf666sk44V.png" + } + } + } else { + user.UserID = u.Uuid + if user.Avatar == "" { + user.Avatar = "https://minio.sumweal.com/nft/221109/C82M980ZLumQCzt857yxur92iAsGdCc7271sDn8MPf666sk44V.png" + } + } + if user.UserID == "" { + return Iuser, errors.New("授权登录失败") + } + //查询用户是否存在 + query := fmt.Sprintf("%s = ? AND appid = ? AND type = ? and log_off_time is null", provider.Code) + global.MG_DB.Where(query, user.UserID, u.Appid, "influencer").Find(&Iuser) + if Iuser.UUID == uuid.Nil { + //注册 + Iuser.UUID = uuid.NewV4() + Iuser.NickName = user.NickName + Iuser.Avatar = user.Avatar + Iuser.Appid = u.Appid + Iuser.Type = "influencer" + switch provider.Code { + case "tiktok": + Iuser.Tiktok = user.UserID + case "facebook": + Iuser.Facebook = user.UserID + case "twitter": + Iuser.Twitter = user.UserID + case "google": + Iuser.Google = user.UserID + case "youtube": + Iuser.Youtube = user.UserID + case "instagram": + Iuser.Instagram = user.UserID + case "ios": + Iuser.Ios = user.UserID + } + if Iuser.NickName == "" { + Iuser.NickName = "BKB_" + utils.GetInvitationLen(4) + "_user" + } + if Iuser.Avatar == "" { + Iuser.Avatar = "https://minio.sumweal.com/nft/221109/C82M980ZLumQCzt857yxur92iAsGdCc7271sDn8MPf666sk44V.png" + } + err = global.MG_DB.Model(&model.User{}).Create(&Iuser).Error + if err != nil { + return Iuser, errors.New("注册失败,请稍后再试") + } + //添加三方登录标识 + var wallet model.Wallet + wallet.UserID = Iuser.UUID.String() + wallet.Platform = "influencer" + wallet.State = 0 + global.MG_DB.Model(&model.Wallet{}).Create(&wallet) + return Iuser, nil + } + return Iuser, nil +} + +func GetAccessToken(provider model.Provider, Code string) (err error, aceessToken string, userID string) { + //发送post请求 + switch provider.Code { + case "tiktok": + aceessToken, err = GetTiktokAccessToken(provider.ClientID, provider.ClientSecret, Code, provider.RedirectURI) + case "facebook": + //facebook可以直接获取token 暂不提供 + case "twitter": + aceessToken, err = GetTwitterAccessToken(provider.ClientID, provider.ClientSecret, Code, provider.RedirectURI) + case "google": + var ( + googleOauthConfig = &oauth2.Config{ + RedirectURL: provider.RedirectURI, + ClientID: provider.ClientID, + ClientSecret: provider.ClientSecret, + Scopes: []string{"https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email"}, + Endpoint: google.Endpoint, + } + token *oauth2.Token + ) + token, err = googleOauthConfig.Exchange(context.Background(), Code) + if err != nil { + return err, aceessToken, "" + } + aceessToken = token.AccessToken + case "youtube": + var ( + googleOauthConfig = &oauth2.Config{ + RedirectURL: provider.RedirectURI, + ClientID: provider.ClientID, + ClientSecret: provider.ClientSecret, + Scopes: []string{"https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email"}, + Endpoint: google.Endpoint, + } + token *oauth2.Token + ) + fmt.Println(provider, Code) + token, err = googleOauthConfig.Exchange(context.Background(), Code) + if err != nil { + return err, aceessToken, "" + } + aceessToken = token.AccessToken + case "instagram": + var ( + instagramOauthConfig = &oauth2.Config{ + RedirectURL: provider.RedirectURI, + ClientID: provider.ClientID, + ClientSecret: provider.ClientSecret, + Scopes: []string{"user_profile"}, + Endpoint: instagram.Endpoint, + } + ) + token, err := instagramOauthConfig.Exchange(context.Background(), Code) + fmt.Println(token) + if err != nil { + return err, aceessToken, "" + } + aceessToken = token.AccessToken + userID = strconv.Itoa(int(token.Extra("user_id").(float64))) + case "ios": + + default: + } + return +} + +func GetUserInfo(provider model.Provider, aceessToken, userID string) (err error, user model.ProviderUser) { + switch provider.Code { + case "tiktok": + tuser, err := getUserInfo(aceessToken) + if err != nil { + fmt.Println("Error:", err) + return err, user + } + user.UserID = tuser.OpenID + user.NickName = tuser.DisplayName + user.Avatar = tuser.AvatarURL + return nil, user + case "facebook": + var userID string + //校验token + tokenCheckURI := provider.TokenCheckURI + "?input_token=" + aceessToken + "&access_token=" + getAccessToken(provider.ClientID, provider.ClientSecret) + err, userID := DebugFacebookToken(aceessToken, tokenCheckURI) + if err != nil { + return errors.New("token校验失败"), user + } + //获取用户信息 + userInfoURI := strings.Replace(provider.UserInfoURI, "USER-ID", userID, 1) + userInfoURI = userInfoURI + "&access_token=" + getAccessToken(provider.ClientID, provider.ClientSecret) + faceUser, err := getThirdPartyLoginUserBO(userInfoURI) + if err != nil { + return errors.New("获取用户信息失败"), user + } + user.UserID = userID + user.NickName = faceUser.UserName + user.Email = faceUser.Email + user.Avatar = faceUser.Picture.Data.URL + return nil, user + case "instagram": + resp, err1 := http.Get(provider.UserInfoURI + userID + fmt.Sprintf("?fields=%v&access_token=%v", "id,username", aceessToken)) + if err1 != nil { + fmt.Println("Failed to get user info: ", err.Error()) + return + } + + defer resp.Body.Close() + content, err1 := io.ReadAll(resp.Body) + if err1 != nil { + fmt.Println("Failed to read response body: ", err1.Error()) + return + } + fmt.Println("Response body: ", string(content)) + var googleUser response.TripartiteInstagram + err1 = json.Unmarshal(content, &googleUser) + if err1 != nil { + fmt.Println("Failed to read response body: ", err1.Error()) + return + } + user.UserID = googleUser.ID + user.NickName = googleUser.Username + case "twitter": + user, err = getTwitterUserInfo(provider, aceessToken) + return err, user + case "google": + resp, err1 := http.Get("https://oauth2.googleapis.com/tokeninfo?id_token=" + aceessToken) + if err1 != nil { + fmt.Println("Failed to get user info: ", err.Error()) + return + } + + defer resp.Body.Close() + content, err1 := io.ReadAll(resp.Body) + if err1 != nil { + fmt.Println("Failed to read response body: ", err1.Error()) + return + } + var googleUser response.TripartiteGoogle + err1 = json.Unmarshal(content, &googleUser) + if err1 != nil { + fmt.Println("Failed to read response body: ", err1.Error()) + return + } + user.UserID = googleUser.Sub + user.NickName = googleUser.Name + // user.Email = googleUser.Email + user.Avatar = googleUser.Picture + fmt.Println("Response body: ", string(content)) + case "youtube": + resp, err1 := http.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + aceessToken) + fmt.Println("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + aceessToken) + if err1 != nil { + fmt.Println("Failed to get user info: ", err1.Error()) + return + } + + defer resp.Body.Close() + content, err1 := io.ReadAll(resp.Body) + if err1 != nil { + fmt.Println("Failed to read response body: ", err1.Error()) + return + } + var googleUser response.TripartiteGoogle + err1 = json.Unmarshal(content, &googleUser) + if err1 != nil { + fmt.Println("Failed to read response body: ", err1.Error()) + return + } + user.UserID = googleUser.ID + user.NickName = googleUser.Name + // user.Email = googleUser.Email + user.Avatar = googleUser.Picture + fmt.Println("Response body: ", string(content)) + + default: + } + return +} + +func DebugFacebookToken(accessToken, url string) (err error, userID string) { + // 构建请求 + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return err, "" + } + + // 发送请求 + client := http.Client{} + resp, err := client.Do(req) + if err != nil { + return err, "" + } + defer resp.Body.Close() + + // 读取响应数据 + body, err := io.ReadAll(resp.Body) + if err != nil { + return err, "" + } + fmt.Println(string(body)) + // 解析响应数据 + var result = make(map[string]interface{}) + if err := json.Unmarshal(body, &result); err != nil { + return err, "" + } + if _, ok := result["error"].(map[string]interface{}); ok { + errorMsg := result["error"].(map[string]interface{})["message"].(string) + return errors.New(errorMsg), "" + } + // 提取 access_token + if _, ok := result["data"].(map[string]interface{}); ok { + userID, ok := result["data"].(map[string]interface{})["user_id"].(string) + if !ok { + return errors.New("未能获取有效的user_id"), "" + } + return nil, userID + } + return errors.New("未能获取有效的user_id"), "" +} + +func GetTiktokAccessToken(clientKey, clientSecret, code, redirectURI string) (string, error) { + // 构建请求体 + data := url.Values{} + data.Set("client_key", clientKey) + data.Set("client_secret", clientSecret) + data.Set("code", code) + data.Set("grant_type", "authorization_code") + data.Set("redirect_uri", redirectURI) + + // 构建请求 + req, err := http.NewRequest("POST", "https://open.tiktokapis.com/v2/oauth/token", strings.NewReader(data.Encode())) + if err != nil { + return "", err + } + + // 设置请求头 + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + // 发送请求 + client := http.Client{} + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + // 读取响应数据 + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + // 解析响应数据 + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + return "", err + } + + // 检查是否返回错误 + if errorMsg, ok := result["error_description"].(string); ok { + return "", fmt.Errorf("获取 access token 失败:%s", errorMsg) + } + + // 提取 access_token + accessToken, ok := result["access_token"].(string) + if !ok { + return "", fmt.Errorf("未能获取有效的 access token") + } + + return accessToken, nil +} + +func GetTwitterAccessToken(clientKey, clientSecret, code, redirectURI string) (string, error) { + // 构建请求体 + data := url.Values{} + data.Set("code", code) + data.Set("grant_type", "authorization_code") + data.Set("client_id", clientKey) + data.Set("redirect_uri", redirectURI) + data.Set("code_verifier", "challenge") + + req, err := http.NewRequest("POST", "https://api.twitter.com/2/oauth2/token", strings.NewReader(data.Encode())) + if err != nil { + // handle error + } + + // 设置请求头 + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + // 发送请求 + client := http.Client{} + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + // 读取响应数据 + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + // 解析响应数据 + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + return "", err + } + + // 检查是否返回错误 + if errorMsg, ok := result["error_description"].(string); ok { + return "", fmt.Errorf("获取 access token 失败:%s", errorMsg) + } + + // 提取 access_token + accessToken, ok := result["access_token"].(string) + if !ok { + return "", fmt.Errorf("未能获取有效的 access token") + } + + return accessToken, nil +} + +func getThirdPartyLoginUserBO(url string) (model.FacebookUserInfo, error) { + resp, err := http.Get(url) + if err != nil { + return model.FacebookUserInfo{}, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return model.FacebookUserInfo{}, fmt.Errorf("Facebook请求查询用户接口失败,响应为%d", resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return model.FacebookUserInfo{}, err + } + + var userInfo model.FacebookUserInfo + err = json.Unmarshal(body, &userInfo) + if err != nil { + return model.FacebookUserInfo{}, err + } + + return userInfo, nil +} + +func getAccessToken(clientId string, clientSecret string) string { + url := "https://graph.facebook.com/oauth/access_token?client_id=" + clientId + "&client_secret=" + clientSecret + "&grant_type=client_credentials" + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return "" + } + res, err := http.DefaultClient.Do(req) + if err != nil { + return "" + } + defer res.Body.Close() + body, err := io.ReadAll(res.Body) + if err != nil { + return "" + } + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + return "" + } + fmt.Println(string(body)) + accessToken, ok := result["access_token"].(string) + if !ok { + return "" + } + return accessToken + // return url.QueryEscape(clientId + "|" + clientSecret) +} + +func getUserInfo(token string) (*model.TiktokUser, error) { + url := "https://open.tiktokapis.com/v2/user/info/?fields=open_id,union_id,avatar_url,display_name" + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + + req.Header.Add("Authorization", "Bearer "+token) + + res, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer res.Body.Close() + + body, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + var response response.TiktokResponse + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + + if response.Error.Code != "ok" { + return nil, fmt.Errorf("API error: %s", response.Error.Message) + } + + return &response.Data.User, nil +} + +func getUserSimple(ut, uuid string) (model.UserSimple, error) { + var ( + err error + result model.UserSimple + ) + err = global.MG_DB.Model(&model.User{}).Select("uuid,nick_name,avatar,phone,platform,tags").Where("`type` = ? AND uuid = ?", ut, uuid).Find(&result).Error + if err != nil { + return result, err + } + return result, nil +} + +func GetUserStatistics(uuid string) (err error, info response.UserStatistics) { + var ( + user model.UserSimple + collectionTotal int64 + ) + err = global.MG_DB.Model(&model.User{}).Where("uuid=?", uuid).Find(&user).Error + if err != nil { + return errors.New("获取用户失败"), info + } + + if user.Platform != "" { + var platforms []request.Platform + err = json.Unmarshal([]byte(user.Platform), &platforms) + for _, v := range platforms { + if v.IsAuth { + info.PlatformNum += 1 + } + } + } + + db := global.MG_DB.Model(&model.CollectionMission{}).Joins("INNER JOIN mission ON mission.id = collection_mission.mission_id"). + Where("collection_mission.create_by = ?", uuid) + err = db.Count(&collectionTotal).Error + info.CollectionMissionNum = collectionTotal + + return nil, info +} + +func UpdateUserDetail(userID string, userInfo *request.UserDetail) error { + var ( + err error + uMap = make(map[string]interface{}) + ) + switch userInfo.Type { + case "platform": + uMap["platform"] = userInfo.Platform + case "tags": + uMap["tags"] = userInfo.Tags + } + err = global.MG_DB.Model(&model.User{}).Where("uuid=?", userID).Updates(uMap).Error + if err != nil { + return errors.New("修改个人信息失败") + } + return nil +} + +func GetUserDetail(userID string) (err error, userInfo *model.UserSimple) { + var ( + user model.UserSimple + dictData []model.SysDictData + ) + err = global.MG_DB.Model(&model.User{}).Where("uuid=?", userID).Find(&user).Error + if err != nil { + return errors.New("获取用户失败"), nil + } + err = global.MG_DB.Model(&model.SysDictData{}).Where("type_code=?", "release_channel").Find(&dictData).Error + if err != nil { + return errors.New("获取用户失败"), nil + } + platformsC := make([]request.Platform, 0) + for i := 0; i < len(dictData); i++ { + platformsC = append(platformsC, request.Platform{ + Platform: dictData[i].Value, + Label: dictData[i].Label, + }) + } + if user.Platform != "" { + var platforms []request.Platform + err = json.Unmarshal([]byte(user.Platform), &platforms) + fmt.Println(err) + for i := 0; i < len(platforms); i++ { + for j := 0; j < len(platformsC); j++ { + if platforms[i].Platform == platformsC[j].Platform { + platformsC[j].IsAuth = platforms[i].IsAuth + platformsC[j].Url = platforms[i].Url + platformsC[j].Image = platforms[i].Image + } + } + } + user.Platforms = platformsC + } else { + user.Platforms = platformsC + } + return nil, &user +} + +func getTwitterUserInfo(provider model.Provider, aceessToken string) (model.ProviderUser, error) { + var result response.TripartiteTwitter + var user model.ProviderUser + req, err := http.NewRequest("GET", provider.UserInfoURI, nil) + if err != nil { + // handle error + return user, err + } + + req.Header.Add("Authorization", "Bearer "+aceessToken) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + // handle error + return user, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + // handle error + return user, err + } + fmt.Println("------twitter", string(body)) + err = json.Unmarshal(body, &result) + if err != nil { + // handle error + fmt.Println("------twitter", err) + return user, err + } + user.UserID = result.Data.ID + user.NickName = result.Data.Name + return user, err +} + +func UserLogOff(userID string) (err error) { + var ( + uMap = make(map[string]interface{}) + ) + uMap["id_forbidden"] = 1 + uMap["log_off_time"] = time.Now() + uMap["forbidden_time"] = time.Now() + uMap["forbidden_reason"] = "用户注销" + uMap["nick_name"] = "用户已注销" + uMap["avatar"] = "https://minio.sumweal.com/nft/221109/C82M980ZLumQCzt857yxur92iAsGdCc7271sDn8MPf666sk44V.png" + err = global.MG_DB.Model(&model.User{}).Where("uuid=?", userID).Updates(uMap).Error + if err != nil { + return errors.New("注销失败") + } + return nil +} diff --git a/service/version.go b/service/version.go new file mode 100644 index 0000000..ff229b3 --- /dev/null +++ b/service/version.go @@ -0,0 +1,58 @@ +package service + +import ( + "pure/global" + "pure/model" +) + +func CheckVersion(platform, version string) (model.VersionV, error) { + var ( + err error + current model.VersionV + result model.VersionV + ) + current, err = GetVersion(platform, version) + if err != nil { + return result, err + } + result, err = getNewestVersion(platform, current.Code) + if err != nil { + return result, err + } + if current.Status == 2 { + result.HideAndSeek = true + } + return result, nil +} + +func GetVersion(platform, version string) (model.VersionV, error) { + var ( + err error + result model.VersionV + ) + err = global.MG_DB.Model(&model.Version{}).Where("`type` = ? AND version = ? AND status IN (1,2)", platform, version). + Select("version,`code`,`type`,info,is_force,url,md5,tip,`status`").First(&result).Error + return result, err +} + +func getNewestVersion(platform string, code int64) (model.VersionV, error) { + var ( + err error + list []model.VersionV + result model.VersionV + ) + err = global.MG_DB.Model(&model.Version{}).Where("`type` = ? AND `code` > ? AND `status` = 1", platform, code). + Select("version,`code`,`type`,info,is_force,url,md5,tip,`status`").Order("`code` DESC").Find(&list).Error + if err != nil { + return result, err + } + if len(list) > 0 { + result = list[0] + for _, ver := range list { + if !result.IsForce && ver.IsForce { + result.IsForce = true + } + } + } + return result, err +} diff --git a/service/wallet.go b/service/wallet.go new file mode 100644 index 0000000..2e4f48d --- /dev/null +++ b/service/wallet.go @@ -0,0 +1,281 @@ +package service + +import ( + "errors" + "time" + + "pure/global" + "pure/model" + "pure/model/request" + "pure/utils" + + "gorm.io/gorm" +) + +func GetUserWalletDetail(userID string) (err error, userInfo *model.Wallet) { + var user model.Wallet + err = global.MG_DB.Model(&model.Wallet{}).Where("user_id = ?", userID).Find(&user).Error + if err != nil { + return errors.New("获取用户失败"), nil + } + return nil, &user +} + +func GetAccountList(userId string) ([]model.Account, error) { + var ( + err error + result []model.Account + ) + err = global.MG_DB.Model(&model.Account{}).Where("user_id = ?", userId).Order("created_at desc").Find(&result).Error + return result, err +} + +func AddAccount(userId string, info *request.AddAccount) error { + var ( + err error + checkAccount model.Account + ) + // 校验重复绑定 + if info.BankCard != "" { + err = global.MG_DB.Model(&model.Account{}).Where("platform = 'influencer' AND card_number = ?", info.BankCard).Find(&checkAccount).Error + if err != nil { + return err + } + } + if checkAccount.ID != 0 { + if checkAccount.UserID == userId { + return errors.New("the account already exists in yours account list") + } else { + //TODO 校验他人重复账户 + } + } + tx := global.MG_DB.Begin() + if info.IsDefault { + err = tx.Model(&model.Account{}).Where("user_id = ? AND platform = ?", userId, "influencer").UpdateColumn("is_default", "0").Error + if err != nil { + return err + } + } + var account model.Account + account.UserID = userId + if info.BankCard != "" { + account.Type = 2 + } + account.Platform = "influencer" + account.AccountName = info.AccountName + account.BankCode = info.BankCode + account.SwiftCode = info.SwiftCode + account.CardNumber = info.BankCard + account.Address = info.Address + account.Country = info.Country + account.Currency = info.Currency + account.IsDefault = info.IsDefault + err = tx.Create(&account).Error + if err != nil { + tx.Rollback() + return err + } + tx.Commit() + return nil +} + +func UpdateAccountIsDefault(userId string, info *request.IdReq) error { + var ( + err error + account model.Account + ) + tx := global.MG_DB.Begin() + err = tx.Model(&model.Account{}).Where("user_id = ? AND id = ?", userId, info.ID).First(&account).Error + if err != nil { + tx.Rollback() + return errors.New("get account failed") + } + if account.IsDefault { + err = tx.Model(&model.Account{}).Where("id = ?", account.ID).UpdateColumn("is_default", "0").Error + if err != nil { + tx.Rollback() + return err + } + } else { + err = tx.Model(&model.Account{}).Where("id != ?", account.ID).UpdateColumn("is_default", "0").Error + if err != nil { + tx.Rollback() + return err + } + err = tx.Model(&model.Account{}).Where("id = ?", account.ID).UpdateColumn("is_default", "1").Error + if err != nil { + tx.Rollback() + return err + } + } + tx.Commit() + return err +} + +func DeleteAccount(userId string, info *request.DeleteAccount) error { + // TODO 校验手机验证码 + + err := global.MG_DB.Model(&model.Account{}).Where("user_id=? and id=?", userId, info.ID).Delete(&model.Account{}).Error + return err +} + +func GetUserCommissionList(userID string, info *request.SearchCommission) (error, interface{}, int64) { + var ( + err error + data []model.Bill + limit int + offset int + total int64 + ) + limit = info.PageSize + offset = info.PageSize * (info.Page - 1) + db := global.MG_DB.Model(&model.Bill{}) + if info.Receipt != 0 { + db = db.Where("receipt=?", info.Receipt) + } + err = db.Count(&total).Error + if err != nil { + return errors.New("获取总数失败"), data, total + } + err = db.Where("user_id=? and type=1", userID).Offset(offset).Limit(limit).Find(&data).Error + if err != nil { + return errors.New("获取用户账单失败"), data, total + } + return nil, data, total +} + +func GetUserWithdrawalList(userID string, info *request.SearchWithdrawal) (error, interface{}, int64) { + var ( + err error + data []model.Bill + limit int + offset int + total int64 + ) + limit = info.PageSize + offset = info.PageSize * (info.Page - 1) + db := global.MG_DB.Model(&model.Bill{}) + if info.Status != 0 { + db = db.Where("receipt=?", info.Status) + } + err = db.Count(&total).Error + if err != nil { + return errors.New("获取总数失败"), data, total + } + err = db.Where("user_id=? and type=3", userID).Offset(offset).Limit(limit).Find(&data).Error + if err != nil { + return errors.New("获取用户账单失败"), data, total + } + return nil, data, total +} + +func Withdrawal(userId string, info *request.WithdrawalParams) (error, model.WithdrawalView) { + var ( + err error + user model.UserSimple + result model.WithdrawalView + ) + user, err = getUserSimple("influencer", userId) + if err != nil { + return errors.New("获取用户信息失败"), result + } + if user.Phone == "" { + return errors.New("please bind your phone number"), result + } + // 开始交易 + for { + ok, err := global.MG_REDIS.SetNX("withdrawal-"+userId, "used", 10*time.Second).Result() + if ok && err == nil { + // 获取成功 + break + } + } + defer func() { + // 释放锁 + _, _ = utils.RedisDel("withdrawal-" + userId) + }() + var ( + wallet model.Wallet + //check model.Withdrawal + ) + err = global.MG_DB.Model(&model.Wallet{}).Where("platform = 'influencer' AND user_id = ?", userId).First(&wallet).Error + if err != nil { + return err, result + } + if wallet.State != 0 { + return errors.New("account no withdrawal allowed"), result + } + //_ = global.MG_DB.Model(&model.Withdrawal{}).Where("platform = '1' AND user_id = ? AND status = '0'", userId).Find(&check).Error + //if check.ID != 0 { + // return errors.New("you have a withdrawal in progress"), result + //} + if wallet.Balance < info.Amount { + return errors.New("金额不足,无法提现"), result + } + var account model.Account + err = global.MG_DB.Model(&model.Account{}).Where("user_id = ? AND id = ?", userId, info.AccountID).First(&account).Error + if err != nil { + return errors.New("获取账户信息失败"), result + } + //if + tx := global.MG_DB.Begin() + err = tx.Model(&model.Wallet{}).Where("id = ?", wallet.ID).Updates(map[string]interface{}{"balance": gorm.Expr("balance - ?", info.Amount), "state": "1"}).Error + if err != nil { + tx.Rollback() + return errors.New("金额扣除失败,取消提现"), result + } + var withdrawal model.Withdrawal + withdrawal.Platform = "1" + withdrawal.WalletType = 1 + withdrawal.FlowNo = Generate() + withdrawal.BillNo = Generate() + withdrawal.AccountType = account.Type + withdrawal.BankCard = account.BankCard + withdrawal.CreateBy = userId + withdrawal.Amount = info.Amount + withdrawal.CheckStatus = "0" + withdrawal.Status = "0" + withdrawal.Title = "提现" + err = tx.Create(&withdrawal).Error + if err != nil { + tx.Rollback() + return errors.New("提交申请失败"), result + } + + var bill model.Bill + bill.UserID = userId + bill.Type = "3" + bill.WithdID = withdrawal.BillNo + bill.TransactionId = "B" + bill.WithdID + bill.Price = info.Amount + bill.Status = 1 + bill.Receipt = 2 + bill.WithdrawalStatus = 0 + bill.Platform = "influencer" + //bill.Account = account.PayPalName + bill.CheckStatus = "0" + bill.Title = "钱包提现" + err = tx.Create(&bill).Error + if err != nil { + tx.Rollback() + return errors.New("提现失败,请稍后再试"), result + } + tx.Commit() + + // 添加通知 + var notify model.Notify + notify.UserId = userId + notify.RelationType = "1" + notify.RelationId = withdrawal.FlowNo + notify.Title = "当前有一笔提现还在审核中,不可发起新的提现" + _ = global.MG_DB.Model(&model.Notify{}).Create(¬ify).Error + + result = model.WithdrawalView{ + FlowNo: withdrawal.FlowNo, + } + return nil, result +} + +//func addTransitReward(tx *gorm.DB) error { +// +//} diff --git a/service/withdrawal.go b/service/withdrawal.go new file mode 100644 index 0000000..4d99ae9 --- /dev/null +++ b/service/withdrawal.go @@ -0,0 +1,27 @@ +package service + +import ( + "pure/global" + "pure/model" + "pure/model/request" +) + +func GetWithdrawal(userId string, info *request.FlowNoParam) (error, model.Withdrawal) { + var ( + err error + result model.Withdrawal + ) + err = global.MG_DB.Model(&model.Withdrawal{}).Where("platform = '1' AND create_by = ? AND flow_no = ?", userId, info.FlowNo).First(&result).Error + return err, result +} +func GetWithdrawalList(userId string, info *request.PageInfo) (error, []model.Withdrawal) { + var ( + err error + result []model.Withdrawal + ) + limit := info.PageSize + offset := info.PageSize * (info.Page - 1) + err = global.MG_DB.Model(&model.Withdrawal{}).Where("platform = '1' AND create_by = ?", userId). + Order("id DESC").Offset(offset).Limit(limit).Find(&result).Error + return err, result +} diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..44b24fd --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,69 @@ +GOHOSTOS:=$(shell go env GOHOSTOS) +GOPATH:=$(shell go env GOPATH) +VERSION=$(shell git describe --tags --always) + +ifeq ($(GOHOSTOS), windows) + #the `find.exe` is different from `find` in bash/shell. + #to see https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/find. + #changed to use git-bash.exe to run find cli or other cli friendly, caused of every developer has a Git. + #Git_Bash= $(subst cmd\,bin\bash.exe,$(dir $(shell where git))) + Git_Bash=$(subst \,/,$(subst cmd\,bin\bash.exe,$(dir $(shell where git)))) + INTERNAL_PROTO_FILES=$(shell $(Git_Bash) -c "find internal -name *.proto") + API_PROTO_FILES=$(shell $(Git_Bash) -c "find api -name *.proto") +else + INTERNAL_PROTO_FILES=$(shell find internal -name *.proto) + API_PROTO_FILES=$(shell find api -name *.proto) + +endif + +.PHONY: init +# init env +init: + go install google.golang.org/protobuf/cmd/protoc-gen-go@latest + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest + go install github.com/go-kratos/kratos/cmd/kratos/v2@latest + go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest + go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest + go install github.com/google/wire/cmd/wire@latest + +.PHONY: config +# generate internal proto +config: + protoc --proto_path=./internal \ + --proto_path=./third_party \ + --go_out=paths=source_relative:./internal \ + $(INTERNAL_PROTO_FILES) + +.PHONY: api +# generate api proto +api: + protoc --proto_path=./api \ + --proto_path=./third_party \ + --go_out=paths=source_relative:./api \ + --go-http_out=paths=source_relative:./api \ + --go-grpc_out=paths=source_relative:./api \ + --openapi_out=fq_schema_naming=true,default_response=false:. \ + $(API_PROTO_FILES) + + ls ./api/*.pb.go | xargs -n1 -IX bash -c 'sed s/,omitempty// X > X.tmp && mv X{.tmp,}' + + + +# show help +help: + @echo '' + @echo 'Usage:' + @echo ' make [target]' + @echo '' + @echo 'Targets:' + @awk '/^[a-zA-Z\-\_0-9]+:/ { \ + helpMessage = match(lastLine, /^# (.*)/); \ + if (helpMessage) { \ + helpCommand = substr($$1, 0, index($$1, ":")); \ + helpMessage = substr(lastLine, RSTART + 2, RLENGTH); \ + printf "\033[36m%-22s\033[0m %s\n", helpCommand,helpMessage; \ + } \ + } \ + { lastLine = $$0 }' $(MAKEFILE_LIST) + +.DEFAULT_GOAL := help diff --git a/tests/api/recommender.proto b/tests/api/recommender.proto new file mode 100644 index 0000000..a4de3fe --- /dev/null +++ b/tests/api/recommender.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package api; + + + +import "google/api/annotations.proto"; +option go_package = "pure/tests/api"; + + +// The greeting service definition. + +// The greeting service definition. +service Recommender { + // Sends a greeting + rpc Ping (PingRequest) returns (PingReply) { + + } +} + +message PingRequest { + string name = 1; +} + + + +message PingReply { + string message = 1; +} + diff --git a/tests/grpc.go b/tests/grpc.go new file mode 100644 index 0000000..ca8701d --- /dev/null +++ b/tests/grpc.go @@ -0,0 +1 @@ +package tests diff --git a/tests/grpc_test.go b/tests/grpc_test.go new file mode 100644 index 0000000..ca8701d --- /dev/null +++ b/tests/grpc_test.go @@ -0,0 +1 @@ +package tests diff --git a/tests/openapi.yaml b/tests/openapi.yaml new file mode 100644 index 0000000..f8f3735 --- /dev/null +++ b/tests/openapi.yaml @@ -0,0 +1,10 @@ +# Generated with protoc-gen-openapi +# https://github.com/google/gnostic/tree/master/cmd/protoc-gen-openapi + +openapi: 3.0.3 +info: + title: "" + version: 0.0.1 +paths: {} +components: + schemas: {} diff --git a/utils/array.go b/utils/array.go new file mode 100644 index 0000000..d57e797 --- /dev/null +++ b/utils/array.go @@ -0,0 +1,19 @@ +package utils + +func ArrayStrRemove(old, loser []string) []string { + for j := 0; j < len(loser); j++ { + for i := 0; i < len(old); i++ { + if old[i] == loser[j] { //将元素剔除 + if old[i] == loser[j] { + if i == len(old)-1 { + old = old[:i] + } else { + old = append(old[:i], old[i+1:]...) + i-- + } + } + } + } + } + return old +} diff --git a/utils/breakpoint_continue.go b/utils/breakpoint_continue.go new file mode 100644 index 0000000..2dd003d --- /dev/null +++ b/utils/breakpoint_continue.go @@ -0,0 +1,102 @@ +package utils + +import ( + "io/ioutil" + "os" + "strconv" +) + +// 前端传来文件片与当前片为什么文件的第几片 +// 后端拿到以后比较次分片是否上传 或者是否为不完全片 +// 前端发送每片多大 +// 前端告知是否为最后一片且是否完成 + +const breakpointDir = "./breakpointDir/" +const finishDir = "./fileDir/" + +//@function: BreakPointContinue +//@description: 断点续传 +//@param: content []byte, fileName string, contentNumber int, contentTotal int, fileMd5 string +//@return: error, string + +func BreakPointContinue(content []byte, fileName string, contentNumber int, contentTotal int, fileMd5 string) (error, string) { + path := breakpointDir + fileMd5 + "/" + err := os.MkdirAll(path, os.ModePerm) + if err != nil { + return err, path + } + err, pathc := makeFileContent(content, fileName, path, contentNumber) + return err, pathc + +} + +//@function: CheckMd5 +//@description: 检查Md5 +//@param: content []byte, chunkMd5 string +//@return: CanUpload bool + +func CheckMd5(content []byte, chunkMd5 string) (CanUpload bool) { + fileMd5 := MD5V(content) + if fileMd5 == chunkMd5 { + return true // 可以继续上传 + } else { + return false // 切片不完整,废弃 + } +} + +//@function: makeFileContent +//@description: 创建切片内容 +//@param: content []byte, fileName string, FileDir string, contentNumber int +//@return: error, string + +func makeFileContent(content []byte, fileName string, FileDir string, contentNumber int) (error, string) { + path := FileDir + fileName + "_" + strconv.Itoa(contentNumber) + f, err := os.Create(path) + if err != nil { + return err, path + } else { + _, err = f.Write(content) + if err != nil { + return err, path + } + } + defer f.Close() + return nil, path +} + +//@function: makeFileContent +//@description: 创建切片文件 +//@param: fileName string, FileMd5 string +//@return: error, string + +func MakeFile(fileName string, FileMd5 string) (error, string) { + rd, err := ioutil.ReadDir(breakpointDir + FileMd5) + if err != nil { + return err, finishDir + fileName + } + _ = os.MkdirAll(finishDir, os.ModePerm) + fd, err := os.OpenFile(finishDir+fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + return err, finishDir + fileName + } + defer fd.Close() + for k := range rd { + content, _ := ioutil.ReadFile(breakpointDir + FileMd5 + "/" + fileName + "_" + strconv.Itoa(k)) + _, err = fd.Write(content) + if err != nil { + _ = os.Remove(finishDir + fileName) + return err, finishDir + fileName + } + } + return nil, finishDir + fileName +} + +//@function: RemoveChunk +//@description: 移除切片 +//@param: FileMd5 string +//@return: error + +func RemoveChunk(FileMd5 string) error { + err := os.RemoveAll(breakpointDir + FileMd5) + return err +} diff --git a/utils/constant.go b/utils/constant.go new file mode 100644 index 0000000..a8534e2 --- /dev/null +++ b/utils/constant.go @@ -0,0 +1,6 @@ +package utils + +const ( + ConfigEnv = "MG_CONFIG" + ConfigFile = "config.yaml" +) diff --git a/utils/cors.go b/utils/cors.go new file mode 100644 index 0000000..1fcc834 --- /dev/null +++ b/utils/cors.go @@ -0,0 +1,17 @@ +package utils + +import ( + uuid "github.com/satori/go.uuid" + "github.com/taskcluster/slugid-go/slugid" +) + +// Get22UUID ... +func Get22UUID() string { + return slugid.Nice() +} + +// GetUUIDv4 ... +func GetUUIDv4() string { + uid := uuid.NewV4() + return uid.String() +} diff --git a/utils/db_automation.go b/utils/db_automation.go new file mode 100644 index 0000000..60c082a --- /dev/null +++ b/utils/db_automation.go @@ -0,0 +1,28 @@ +package utils + +import ( + "errors" + "fmt" + "time" + + "gorm.io/gorm" +) + +//@function: ClearTable +//@description: 清理数据库表数据 +//@param: db(数据库对象) *gorm.DB, tableName(表名) string, compareField(比较字段) string, interval(间隔) string +//@return: error + +func ClearTable(db *gorm.DB, tableName string, compareField string, interval string) error { + if db == nil { + return errors.New("db Cannot be empty") + } + duration, err := time.ParseDuration(interval) + if err != nil { + return err + } + if duration < 0 { + return errors.New("parse duration < 0") + } + return db.Debug().Exec(fmt.Sprintf("DELETE FROM %s WHERE %s < ?", tableName, compareField), time.Now().Add(-duration)).Error +} diff --git a/utils/directory.go b/utils/directory.go new file mode 100644 index 0000000..3c995df --- /dev/null +++ b/utils/directory.go @@ -0,0 +1,46 @@ +package utils + +import ( + "os" + "pure/global" + + "go.uber.org/zap" +) + +//@function: PathExists +//@description: 文件目录是否存在 +//@param: path string +//@return: bool, error + +func PathExists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +//@function: CreateDir +//@description: 批量创建文件夹 +//@param: dirs ...string +//@return: err error + +func CreateDir(dirs ...string) (err error) { + for _, v := range dirs { + exist, err := PathExists(v) + if err != nil { + return err + } + if !exist { + global.MG_LOG.Debug("create directory" + v) + err = os.MkdirAll(v, os.ModePerm) + if err != nil { + global.MG_LOG.Error("create directory"+v, zap.Any(" error:", err)) + } + } + } + return err +} diff --git a/utils/email.go b/utils/email.go new file mode 100644 index 0000000..b0df43a --- /dev/null +++ b/utils/email.go @@ -0,0 +1,78 @@ +package utils + +import ( + "crypto/tls" + "fmt" + "net/smtp" + "strings" + + "pure/global" + + "github.com/jordan-wright/email" +) + +//@function: Email +//@description: Email发送方法 +//@param: subject string, body string +//@return: error + +func Email(subject string, body string) error { + to := strings.Split(global.MG_CONFIG.Email.To, ",") + return send(to, subject, body) +} + +//@function: ErrorToEmail +//@description: 给email中间件错误发送邮件到指定邮箱 +//@param: subject string, body string +//@return: error + +func ErrorToEmail(subject string, body string) error { + to := strings.Split(global.MG_CONFIG.Email.To, ",") + if to[len(to)-1] == "" { // 判断切片的最后一个元素是否为空,为空则移除 + to = to[:len(to)-1] + } + return send(to, subject, body) +} + +//@function: EmailTest +//@description: Email测试方法 +//@param: subject string, body string +//@return: error + +func EmailTest(subject string, body string) error { + to := []string{global.MG_CONFIG.Email.From} + return send(to, subject, body) +} + +//@function: send +//@description: Email发送方法 +//@param: subject string, body string +//@return: error + +func send(to []string, subject string, body string) error { + from := global.MG_CONFIG.Email.From + nickname := global.MG_CONFIG.Email.Nickname + secret := global.MG_CONFIG.Email.Secret + host := global.MG_CONFIG.Email.Host + port := global.MG_CONFIG.Email.Port + isSSL := global.MG_CONFIG.Email.IsSSL + + auth := smtp.PlainAuth("", from, secret, host) + e := email.NewEmail() + if nickname != "" { + e.From = fmt.Sprintf("%s <%s>", nickname, from) + } else { + e.From = from + } + e.To = to + e.Subject = subject + e.HTML = []byte(body) + var err error + hostAddr := fmt.Sprintf("%s:%d", host, port) + if isSSL { + err = e.SendWithTLS(hostAddr, auth, &tls.Config{ServerName: host}) + } else { + err = e.Send(hostAddr, auth) + } + return err +} diff --git a/utils/file_operations.go b/utils/file_operations.go new file mode 100644 index 0000000..9b217f0 --- /dev/null +++ b/utils/file_operations.go @@ -0,0 +1,63 @@ +package utils + +import ( + "os" + "path/filepath" + "reflect" + "strings" +) + +//@function: FileMove +//@description: 文件移动供外部调用 +//@param: src string, dst string(src: 源位置,绝对路径or相对路径, dst: 目标位置,绝对路径or相对路径,必须为文件夹) +//@return: err error + +func FileMove(src string, dst string) (err error) { + if dst == "" { + return nil + } + src, err = filepath.Abs(src) + if err != nil { + return err + } + dst, err = filepath.Abs(dst) + if err != nil { + return err + } + var revoke = false + dir := filepath.Dir(dst) +Redirect: + _, err = os.Stat(dir) + if err != nil { + err = os.MkdirAll(dir, 0755) + if err != nil { + return err + } + if !revoke { + revoke = true + goto Redirect + } + } + return os.Rename(src, dst) +} + +//@function: TrimSpace +//@description: 去除结构体空格 +//@param: target interface (target: 目标结构体,传入必须是指针类型) +//@return: null + +func TrimSpace(target interface{}) { + t := reflect.TypeOf(target) + if t.Kind() != reflect.Ptr { + return + } + t = t.Elem() + v := reflect.ValueOf(target).Elem() + for i := 0; i < t.NumField(); i++ { + switch v.Field(i).Kind() { + case reflect.String: + v.Field(i).SetString(strings.TrimSpace(v.Field(i).String())) + } + } + return +} diff --git a/utils/float.go b/utils/float.go new file mode 100644 index 0000000..57e0939 --- /dev/null +++ b/utils/float.go @@ -0,0 +1,28 @@ +package utils + +import ( + "fmt" + "math" + "strconv" +) + +func FormatFloat(num float64, decimal int) (float64, error) { + // 默认乘1 + d := float64(1) + if decimal > 0 { + // 10的N次方 + d = math.Pow10(decimal) + } + // math.trunc作用就是返回浮点数的整数部分 + // 再除回去,小数点后无效的0也就不存在了 + res := strconv.FormatFloat(math.Trunc(num*d)/d, 'f', -1, 64) + return strconv.ParseFloat(res, 64) +} + +func FormatFloatToString(num float64) string { + float, err := FormatFloat(num, 2) + if err != nil { + return "-" + } + return fmt.Sprintf("%v", float) +} diff --git a/utils/fmt_plus.go b/utils/fmt_plus.go new file mode 100644 index 0000000..e9258cc --- /dev/null +++ b/utils/fmt_plus.go @@ -0,0 +1,36 @@ +package utils + +import ( + "fmt" + "reflect" + "strings" +) + +//@function: StructToMap +//@description: 利用反射将结构体转化为map +//@param: obj interface{} +//@return: map[string]interface{} + +func StructToMap(obj interface{}) map[string]interface{} { + obj1 := reflect.TypeOf(obj) + obj2 := reflect.ValueOf(obj) + + var data = make(map[string]interface{}) + for i := 0; i < obj1.NumField(); i++ { + if obj1.Field(i).Tag.Get("mapstructure") != "" { + data[obj1.Field(i).Tag.Get("mapstructure")] = obj2.Field(i).Interface() + } else { + data[obj1.Field(i).Name] = obj2.Field(i).Interface() + } + } + return data +} + +//@function: ArrayToString +//@description: 将数组格式化为字符串 +//@param: array []interface{} +//@return: string + +func ArrayToString(array []interface{}) string { + return strings.Replace(strings.Trim(fmt.Sprint(array), "[]"), " ", ",", -1) +} diff --git a/utils/injectionCode.go b/utils/injectionCode.go new file mode 100644 index 0000000..aabacdd --- /dev/null +++ b/utils/injectionCode.go @@ -0,0 +1,142 @@ +package utils + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "io/ioutil" + "strings" +) + +//@function: AutoInjectionCode +//@description: 向文件中固定注释位置写入代码 +//@param: filepath string, funcName string, codeData string +//@return: error + +func AutoInjectionCode(filepath string, funcName string, codeData string) error { + startComment := "Code generated by pure Begin; DO NOT EDIT." + endComment := "Code generated by pure End; DO NOT EDIT." + srcData, err := ioutil.ReadFile(filepath) + if err != nil { + return err + } + srcDataLen := len(srcData) + fset := token.NewFileSet() + fparser, err := parser.ParseFile(fset, filepath, srcData, parser.ParseComments) + if err != nil { + return err + } + codeData = strings.TrimSpace(codeData) + var codeStartPos = -1 + var codeEndPos = srcDataLen + var expectedFunction *ast.FuncDecl + + var startCommentPos = -1 + var endCommentPos = srcDataLen + + // 如果指定了函数名,先寻找对应函数 + if funcName != "" { + for _, decl := range fparser.Decls { + if funDecl, ok := decl.(*ast.FuncDecl); ok && funDecl.Name.Name == funcName { + expectedFunction = funDecl + codeStartPos = int(funDecl.Body.Lbrace) + codeEndPos = int(funDecl.Body.Rbrace) + break + } + } + } + + // 遍历所有注释 + for _, comment := range fparser.Comments { + if int(comment.Pos()) > codeStartPos && int(comment.End()) <= codeEndPos { + if startComment != "" && strings.Contains(comment.Text(), startComment) { + startCommentPos = int(comment.Pos()) // Note: Pos is the second '/' + } + if endComment != "" && strings.Contains(comment.Text(), endComment) { + endCommentPos = int(comment.Pos()) // Note: Pos is the second '/' + } + } + } + + if endCommentPos == srcDataLen { + return fmt.Errorf("comment:%s not found", endComment) + } + + // 在指定函数名,且函数中startComment和endComment都存在时,进行区间查重 + if (codeStartPos != -1 && codeEndPos <= srcDataLen) && (startCommentPos != -1 && endCommentPos != srcDataLen) && expectedFunction != nil { + if exist := checkExist(&srcData, startCommentPos, endCommentPos, expectedFunction.Body, codeData); exist { + fmt.Printf("文件 %s 待插入数据 %s 已存在\n", filepath, codeData) + return nil // 这里不需要返回错误? + } + } + + // 两行注释中间没有换行时,会被认为是一条Comment + if startCommentPos == endCommentPos { + endCommentPos = startCommentPos + strings.Index(string(srcData[startCommentPos:]), endComment) + for srcData[endCommentPos] != '/' { + endCommentPos-- + } + } + + // 记录"//"之前的空字符,保持写入后的格式一致 + tmpSpace := make([]byte, 0, 10) + for tmp := endCommentPos - 2; tmp >= 0; tmp-- { + if srcData[tmp] != '\n' { + tmpSpace = append(tmpSpace, srcData[tmp]) + } else { + break + } + } + + reverseSpace := make([]byte, 0, len(tmpSpace)) + for index := len(tmpSpace) - 1; index >= 0; index-- { + reverseSpace = append(reverseSpace, tmpSpace[index]) + } + + // 插入数据 + indexPos := endCommentPos - 1 + insertData := []byte(append([]byte(codeData+"\n"), reverseSpace...)) + + remainData := append([]byte{}, srcData[indexPos:]...) + srcData = append(append(srcData[:indexPos], insertData...), remainData...) + + // 写回数据 + return ioutil.WriteFile(filepath, srcData, 0600) +} + +func checkExist(srcData *[]byte, startPos int, endPos int, blockStmt *ast.BlockStmt, target string) bool { + for _, list := range blockStmt.List { + switch stmt := list.(type) { + case *ast.ExprStmt: + if callExpr, ok := stmt.X.(*ast.CallExpr); ok && + int(callExpr.Pos()) > startPos && int(callExpr.End()) < endPos { + text := string((*srcData)[int(callExpr.Pos()-1):int(callExpr.End())]) + key := strings.TrimSpace(text) + if key == target { + return true + } + } + case *ast.BlockStmt: + if checkExist(srcData, startPos, endPos, stmt, target) { + return true + } + case *ast.AssignStmt: + // 为 model 中的代码进行检查 + if len(stmt.Rhs) > 0 { + if callExpr, ok := stmt.Rhs[0].(*ast.CallExpr); ok { + for _, arg := range callExpr.Args { + if int(arg.Pos()) > startPos && int(arg.End()) < endPos { + text := string((*srcData)[int(arg.Pos()-1):int(arg.End())]) + key := strings.TrimSpace(text) + if key == target { + return true + } + } + } + } + } + } + } + return false +} diff --git a/utils/international.go b/utils/international.go new file mode 100644 index 0000000..83285d6 --- /dev/null +++ b/utils/international.go @@ -0,0 +1,32 @@ +package utils + +import ( + "pure/global" + "pure/model" + "time" +) + +func InterTranslate(original, form, to string) string { + data := global.MG_Language.(map[string]model.Internationalization) + if data[original].En != "" { + return data[original].En + } + go func() { + var ( + data model.Internationalization + ) + ok, err := global.MG_REDIS.SetNX("internationalization-"+original, "used", 10*time.Second).Result() + if ok && err == nil { + global.MG_DB.Model(&model.Internationalization{}).Where("ch=?", original).Find(&data) + if data.ID == 0 { + data.Ch = original + global.MG_DB.Create(&data) + } else { + newData := global.MG_Language.(map[string]model.Internationalization) + newData[original] = data + global.MG_Language = newData + } + } + }() + return "" +} diff --git a/utils/jpush/model.go b/utils/jpush/model.go new file mode 100644 index 0000000..21b0b6f --- /dev/null +++ b/utils/jpush/model.go @@ -0,0 +1,23 @@ +package jpush + +type notificationBody struct { +} + +type cidList struct { + CidList []string `json:"cidlist"` +} + +type tags struct { + Tags []string `json:"tags"` +} + +type Error struct { + Code int `json:"code"` + Message string `json:"message"` +} + +type PushResult struct { + Sendno string `json:"sendno"` + MsgId string `json:"msg_id"` + Error Error `json:"error"` +} diff --git a/utils/jpush/push.go b/utils/jpush/push.go new file mode 100644 index 0000000..4951945 --- /dev/null +++ b/utils/jpush/push.go @@ -0,0 +1,202 @@ +package jpush + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "pure/global" + "strings" +) + +func createAuthorization(req *http.Request) *http.Request { + var ( + str string + ) + str = global.MG_CONFIG.JPush.Appkey + ":" + global.MG_CONFIG.JPush.Secret + req.Header.Add("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(str))) + return req +} + +//JiGuangPush ... +func JiGuangPush(reqParams map[string]interface{}) (result PushResult, err error) { + var ( + client *http.Client + req *http.Request + params []byte + cid string + resBody []byte + options map[string]interface{} + ) + options = make(map[string]interface{}) + options["time_to_live"] = 0 + if global.MG_CONFIG.System.Env == "mater" { + options["apns_production"] = true + } else { + options["apns_production"] = false + } + reqParams["options"] = options + cid, err = jiGuangCid() + if err != nil { + return + } + reqParams["cid"] = cid + params, err = json.Marshal(reqParams) + if err != nil { + return + } + client = &http.Client{} + req, err = http.NewRequest(http.MethodPost, "https://api.jpush.cn/v3/push", strings.NewReader(string(params))) + if err != nil { + return + } + req.Header.Add("Content-Type", "application/json") + createAuthorization(req) + resp, err := client.Do(req) + if err != nil { + return + } + defer resp.Body.Close() + resBody, err = ioutil.ReadAll(resp.Body) + if err != nil { + return + } + //fmt.Println(string(resBody)) + global.MG_LOG.Info(string(resBody)) + err = json.Unmarshal(resBody, &result) + if err != nil { + return + } + return +} + +func jiGuangCid() (string, error) { + var ( + err error + res string + client *http.Client + req *http.Request + resp *http.Response + resBody []byte + list cidList + ) + client = &http.Client{} + req, err = http.NewRequest(http.MethodGet, "https://api.jpush.cn/v3/push/cid?count=10&type=push", nil) + if err != nil { + return res, err + } + req.Header.Add("Content-Type", "application/json") + createAuthorization(req) + resp, err = client.Do(req) + if err != nil { + return res, err + } + defer resp.Body.Close() + resBody, err = ioutil.ReadAll(resp.Body) + if err != nil { + return res, err + } + err = json.Unmarshal(resBody, &list) + if err != nil || len(list.CidList) == 0 { + return "", err + } + return list.CidList[0], err +} + +func GetTagsList() (string, error) { + var ( + err error + res string + client *http.Client + req *http.Request + resp *http.Response + resBody []byte + list tags + ) + client = &http.Client{} + req, err = http.NewRequest(http.MethodGet, "https://device.jpush.cn/v3/tags/", nil) + if err != nil { + return res, err + } + req.Header.Add("Content-Type", "application/json") + createAuthorization(req) + resp, err = client.Do(req) + if err != nil { + return res, err + } + defer resp.Body.Close() + resBody, err = ioutil.ReadAll(resp.Body) + if err != nil { + return res, err + } + fmt.Println(string(resBody)) + err = json.Unmarshal(resBody, &list) + if err != nil || len(list.Tags) == 0 { + return "", err + } + return list.Tags[0], err +} + +func UpdateTags(tagValue string, registration map[string][]string) { + var ( + err error + client *http.Client + req *http.Request + params []byte + reqParams map[string]interface{} + resBody []byte + ) + reqParams = make(map[string]interface{}) + reqParams["registration_ids"] = registration + params, err = json.Marshal(reqParams) + if err != nil { + return + } + client = &http.Client{} + req, err = http.NewRequest(http.MethodPost, "https://device.jpush.cn/v3/tags/"+tagValue, strings.NewReader(string(params))) + if err != nil { + return + } + req.Header.Add("Content-Type", "application/json") + createAuthorization(req) + resp, err := client.Do(req) + if err != nil { + return + } + defer resp.Body.Close() + resBody, err = ioutil.ReadAll(resp.Body) + if err != nil { + return + } + fmt.Println(string(resBody)) + return +} + +func GetRegistrationInfo(registration string) { + var ( + err error + client *http.Client + req *http.Request + resp *http.Response + resBody []byte + ) + client = &http.Client{} + req, err = http.NewRequest(http.MethodGet, "https://device.jpush.cn/v3/tags/", nil) + if err != nil { + return + } + req.Header.Add("Content-Type", "application/json") + createAuthorization(req) + resp, err = client.Do(req) + if err != nil { + return + } + defer resp.Body.Close() + resBody, err = ioutil.ReadAll(resp.Body) + if err != nil { + return + } + fmt.Println(string(resBody)) + return +} diff --git a/utils/md5.go b/utils/md5.go new file mode 100644 index 0000000..e359dc9 --- /dev/null +++ b/utils/md5.go @@ -0,0 +1,17 @@ +package utils + +import ( + "crypto/md5" + "encoding/hex" +) + +//@function: MD5V +//@description: md5加密 +//@param: str []byte +//@return: string + +func MD5V(str []byte) string { + h := md5.New() + h.Write(str) + return hex.EncodeToString(h.Sum(nil)) +} diff --git a/utils/qiniu/model.go b/utils/qiniu/model.go new file mode 100644 index 0000000..d5fe9f2 --- /dev/null +++ b/utils/qiniu/model.go @@ -0,0 +1,83 @@ +package qiniu + +type VideoStreams struct { + Index int `json:"index"` + CodecName string `json:"codec_name"` + CodecLongName string `json:"codec_long_name"` + Profile string `json:"profile"` + CodecType string `json:"codec_type"` + CodecTimeBase string `json:"codec_time_base"` + CodecTagString string `json:"codec_tag_string"` + CodecTag string `json:"codec_tag"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + CodedWidth int `json:"coded_width,omitempty"` + CodedHeight int `json:"coded_height,omitempty"` + HasBFrames int `json:"has_b_frames,omitempty"` + SampleAspectRatio string `json:"sample_aspect_ratio,omitempty"` + DisplayAspectRatio string `json:"display_aspect_ratio,omitempty"` + PixFmt string `json:"pix_fmt,omitempty"` + Level int `json:"level,omitempty"` + ChromaLocation string `json:"chroma_location,omitempty"` + Refs int `json:"refs,omitempty"` + IsAvc string `json:"is_avc,omitempty"` + NalLengthSize string `json:"nal_length_size,omitempty"` + RFrameRate string `json:"r_frame_rate"` + AvgFrameRate string `json:"avg_frame_rate"` + TimeBase string `json:"time_base"` + StartPts int `json:"start_pts"` + StartTime string `json:"start_time"` + DurationTs int `json:"duration_ts"` + Duration string `json:"duration"` + BitRate string `json:"bit_rate"` + BitsPerRawSample string `json:"bits_per_raw_sample,omitempty"` + NbFrames string `json:"nb_frames"` + Disposition struct { + Default int `json:"default"` + Dub int `json:"dub"` + Original int `json:"original"` + Comment int `json:"comment"` + Lyrics int `json:"lyrics"` + Karaoke int `json:"karaoke"` + Forced int `json:"forced"` + HearingImpaired int `json:"hearing_impaired"` + VisualImpaired int `json:"visual_impaired"` + CleanEffects int `json:"clean_effects"` + AttachedPic int `json:"attached_pic"` + TimedThumbnails int `json:"timed_thumbnails"` + } `json:"disposition"` + Tags struct { + Language string `json:"language"` + HandlerName string `json:"handler_name"` + } `json:"tags"` + SampleFmt string `json:"sample_fmt,omitempty"` + SampleRate string `json:"sample_rate,omitempty"` + Channels int `json:"channels,omitempty"` + ChannelLayout string `json:"channel_layout,omitempty"` + BitsPerSample int `json:"bits_per_sample,omitempty"` + MaxBitRate string `json:"max_bit_rate,omitempty"` +} + +type VideoFormat struct { + NbStreams int `json:"nb_streams"` + NbPrograms int `json:"nb_programs"` + FormatName string `json:"format_name"` + FormatLongName string `json:"format_long_name"` + StartTime string `json:"start_time"` + Duration string `json:"duration"` + Size string `json:"size"` + BitRate string `json:"bit_rate"` + ProbeScore int `json:"probe_score"` + Tags struct { + MajorBrand string `json:"major_brand"` + MinorVersion string `json:"minor_version"` + CompatibleBrands string `json:"compatible_brands"` + Encoder string `json:"encoder"` + Description string `json:"description"` + } `json:"tags"` +} + +type VideoInfo struct { + Streams []VideoStreams `json:"streams"` + Format VideoFormat `json:"format"` +} diff --git a/utils/qiniu/video.go b/utils/qiniu/video.go new file mode 100644 index 0000000..0bb7af2 --- /dev/null +++ b/utils/qiniu/video.go @@ -0,0 +1,84 @@ +package qiniu + +import ( + "crypto/hmac" + "crypto/sha1" + "encoding/base64" + "encoding/json" + "io/ioutil" + "math" + "net/http" + "pure/global" + "strconv" + + "github.com/pili-engineering/pili-sdk-go.v2/pili" +) + +// 计算token并加入Header +func createAuthorization(req *http.Request, reqBody []byte) *http.Request { + var ( + str string + hashed []byte + ) + + str = req.Method + " " + req.URL.Path + if req.URL.RawQuery != "" { + str += "?" + req.URL.RawQuery + } + str += "\nHost: " + req.Host + if contentType := req.Header.Get("Content-Type"); contentType != "" { + str += "\nContent-Type: " + contentType + } + str += "\n\n" + if len(reqBody) != 0 { + str += string(reqBody) + } + key := []byte(global.MG_CONFIG.Qiniu.SecretKey) + mac := hmac.New(sha1.New, key) + mac.Write([]byte(str)) + hashed = mac.Sum(nil) + req.Header.Add("Authorization", "Qiniu "+global.MG_CONFIG.Qiniu.AccessKey+":"+base64.URLEncoding.EncodeToString(hashed)) + return req +} + +func getVideoInfo(url string) (result VideoInfo, err error) { + resp, err := http.Get(url + "?avinfo") + if err != nil { + return + } + defer resp.Body.Close() + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + return + } + //fmt.Println(string(resBody)) + global.MG_LOG.Info(string(resBody)) + err = json.Unmarshal(resBody, &result) + return +} + +func GetVideoLen(url string) int { + info, err := getVideoInfo(url) + if err != nil { + return 0 + } + f1, err := strconv.ParseFloat(info.Format.Duration, 64) + if err != nil { + return 0 + } + s1 := strconv.FormatFloat(math.Floor(f1), 'f', -1, 64) + i, _ := strconv.Atoi(s1) + return i +} + +func ReturnUrl2(key, zone, domain string, start, end int64) (string, error) { + mac := &pili.MAC{AccessKey: global.MG_CONFIG.Qiniu.AccessKey, SecretKey: []byte(global.MG_CONFIG.Qiniu.SecretKey)} + client := pili.New(mac, nil) + hub := client.Hub(zone) + stream := hub.Stream(key) + fName, err := stream.Save(start, end) + if err != nil { + return "", err + } + return "http://" + domain + "/" + fName, nil +} diff --git a/utils/redis.go b/utils/redis.go new file mode 100644 index 0000000..4c97ac4 --- /dev/null +++ b/utils/redis.go @@ -0,0 +1,321 @@ +package utils + +import ( + "fmt" + "pure/global" + + "time" + + "github.com/go-redis/redis" +) + +// RedisGet ... +func RedisGet(key string) string { + result, err := global.MG_REDIS.Get(key).Result() + if err != nil { + return "" + } + return result +} + +func RedisSet(key string, value interface{}, expiration time.Duration) string { + result, err := global.MG_REDIS.Set(key, value, expiration).Result() + if err != nil { + return "" + } + return result +} + +func RedisDel(key ...string) (int64, error) { + result, err := global.MG_REDIS.Del(key...).Result() + if err != nil { + return -1, err + } + return result, err +} + +func RedisLLen(key string) (int64, error) { + result, err := global.MG_REDIS.LLen(key).Result() + if err != nil { + return -1, err + } + return result, err +} + +// RedisHashSet 向key的hash中添加元素field的值 +func RedisHashSet(key, field string, data interface{}) error { + err := global.MG_REDIS.HSet(key, field, data).Err() + if err != nil { + return err + } + return nil +} + +// RedisBatchHashSet 批量向key的hash添加对应元素field的值 +func RedisBatchHashSet(key string, fields map[string]interface{}) (error, string) { + val, err := global.MG_REDIS.HMSet(key, fields).Result() + if err != nil { + return err, "" + } + return nil, val +} + +func RedisHDel(client *redis.Client, key string, fields ...string) (int64, string) { + result, err := client.HDel(key, fields...).Result() + if err != nil { + return 0, "" + } + return result, err.Error() +} + +func RedisHSet(key, field string, value interface{}) (error, bool) { + val, err := global.MG_REDIS.HSet(key, field, value).Result() + if err != nil { + return err, false + } + return nil, val +} + +func RedisSetNX(key string, value interface{}, expiration time.Duration) (error, bool) { + val, err := global.MG_REDIS.SetNX(key, value, expiration).Result() + if err != nil { + return err, false + } + return nil, val +} + +// RedisHashGet 通过key获取hash的元素值 +func RedisHashGet(key, field string) string { + val, err := global.MG_REDIS.HGet(key, field).Result() + if err != nil { + return "" + } + return val +} + +func RedisHashMGet(key string, fields ...string) []interface{} { + val, err := global.MG_REDIS.HMGet(key, fields...).Result() + if err != nil { + return nil + } + return val +} + +//HGetAll +func RedisHashGetAll(key string) map[string]string { + val, err := global.MG_REDIS.HGetAll(key).Result() + if err != nil { + return nil + } + return val +} + +// RedisBatchHashGet 批量获取key的hash中对应多元素值 +func RedisBatchHashGet(key string, fields ...string) map[string]interface{} { + resMap := make(map[string]interface{}) + for _, field := range fields { + val, err := global.MG_REDIS.HGet(key, fmt.Sprintf("%s", field)).Result() + if err == nil && val != "" { + resMap[field] = val + } + } + return resMap +} + +func RedisLPush(key string, values ...interface{}) (int64, error) { + result, err := global.MG_REDIS.LPush(key, values...).Result() + if err != nil { + return 0, err + } + return result, nil +} + +func RedisLPop(key string) (error, string) { + result, err := global.MG_REDIS.LPop(key).Result() + if err != nil { + return err, "" + } + return err, result +} + +// RedisSAdd 无序集合添加 +func RedisSAdd(key string, values ...interface{}) (int64, error) { + result, err := global.MG_REDIS.SAdd(key, values...).Result() + if err != nil { + return 0, err + } + return result, nil +} + +// RedisSMembers 从无序集合中获取数据 +func RedisSMembers(key string) ([]string, error) { + val, err := global.MG_REDIS.SMembers(key).Result() + if err != nil { + return nil, err + } + return val, nil +} + +// RedisZAdd 有序集合添加 +func RedisZAdd(key string, values map[float64]interface{}) (int64, error) { + var members []redis.Z + for scale, value := range values { + members = append(members, redis.Z{ + Score: scale, + Member: value, + }) + } + result, err := global.MG_REDIS.ZAdd(key, members...).Result() + if err != nil { + return 0, err + } + return result, nil +} + +func RedisZCard(key string) (int64, error) { + result, err := global.MG_REDIS.ZCard(key).Result() + if err != nil { + return 0, err + } + return result, nil +} + +func RedisZCount(key string, min, max string) (int64, error) { + result, err := global.MG_REDIS.ZCount(key, min, max).Result() + if err != nil { + return 0, err + } + return result, nil +} + +func RedisZRange(key string, start, stop int64, sort string) ([]interface{}, error) { + var val = make([]interface{}, 0) + if sort == "asc" { //scale 正序 + result, err := global.MG_REDIS.ZRangeWithScores(key, start, stop).Result() + if err != nil { + return val, err + } + for _, z := range result { + val = append(val, z.Member) + } + } else { //scale 倒序 + result, err := global.MG_REDIS.ZRevRange(key, start, stop).Result() + if err != nil { + return val, err + } + for _, z := range result { + val = append(val, z) + } + return val, nil + } + + return val, nil +} + +// RedisIncr 获取自增唯一ID +func RedisIncr(key string) int { + val, err := global.MG_REDIS.Incr(key).Result() + if err != nil { + } + return int(val) +} + +// RedisSetAdd 添加集合数据 +func RedisSetAdd(key, val string) { + global.MG_REDIS.SAdd(key, val) +} + +func RedisRename(key, newKey string) (string, error) { + result, err := global.MG_REDIS.Rename(key, newKey).Result() + if err != nil { + return "", err + } + return result, nil +} + +func RedisHashGet1(client *redis.Client, key, field string) string { + val, err := client.HGet(key, field).Result() + if err != nil { + return "" + } + return val +} + +func RedisDel1(client *redis.Client, key ...string) (int64, error) { + result, err := client.Del(key...).Result() + if err != nil { + return -1, err + } + return result, err +} + +func RedisBatchHashSet1(client *redis.Client, key string, fields map[string]interface{}) (error, string) { + val, err := client.HMSet(key, fields).Result() + if err != nil { + return err, "" + } + return nil, val +} + +func RedisZAdd1(client *redis.Client, key string, values map[float64]interface{}) (int64, error) { + var members []redis.Z + for scale, value := range values { + members = append(members, redis.Z{ + Score: scale, + Member: value, + }) + } + result, err := client.ZAdd(key, members...).Result() + if err != nil { + return 0, err + } + return result, nil +} + +func RedisZRange1(client *redis.Client, key string, start, stop int64, sort string) ([]interface{}, error) { + var val = make([]interface{}, 0) + if sort == "asc" { //scale 正序 + result, err := client.ZRangeWithScores(key, start, stop).Result() + if err != nil { + return val, err + } + for _, z := range result { + val = append(val, z.Member) + } + } else { //scale 倒序 + result, err := client.ZRevRange(key, start, stop).Result() + if err != nil { + return val, err + } + for _, z := range result { + val = append(val, z) + } + return val, nil + } + + return val, nil +} + +func RedisZRemRangeByRank(client *redis.Client, key string, start, stop int64) error { + _, err := client.ZRemRangeByRank(key, start, stop).Result() + if err != nil { + return err + } + return nil +} + +func RedisZCard1(client *redis.Client, key string) (int64, error) { + result, err := client.ZCard(key).Result() + if err != nil { + return 0, err + } + return result, nil +} + +func RedisScan(client *redis.Client) ([]string, error) { + result, _, err := client.Scan(0, "", 0).Result() + if err != nil { + return nil, err + } + return result, nil +} diff --git a/utils/redis_store.go b/utils/redis_store.go new file mode 100644 index 0000000..dfcd419 --- /dev/null +++ b/utils/redis_store.go @@ -0,0 +1,44 @@ +package utils + +import ( + "fmt" + "pure/global" + "strings" + "time" +) + +const CAPTCHA = "captcha:" + +type RedisStore struct{} + +func (e RedisStore) Set(id, value string) { + key := CAPTCHA + id + value = strings.ToLower(value) + err := global.MG_REDIS.Set(key, value, 2*time.Minute).Err() + if err != nil { + global.MG_LOG.Info(err.Error()) + } +} + +func (e RedisStore) Get(id string, clear bool) string { + key := CAPTCHA + id + val, err := global.MG_REDIS.Get(key).Result() + if err != nil { + fmt.Println(err) + return "" + } + if clear { + err := global.MG_REDIS.Del(key).Err() + if err != nil { + fmt.Println(err) + return "" + } + } + return val +} + +func (e RedisStore) Verify(id, answer string, clear bool) bool { + v := RedisStore{}.Get(id, clear) + //fmt.Println("key:"+id+";value:"+v+";answer:"+answer) + return v == answer +} diff --git a/utils/reload.go b/utils/reload.go new file mode 100644 index 0000000..de5499b --- /dev/null +++ b/utils/reload.go @@ -0,0 +1,18 @@ +package utils + +import ( + "errors" + "os" + "os/exec" + "runtime" + "strconv" +) + +func Reload() error { + if runtime.GOOS == "windows" { + return errors.New("系统不支持") + } + pid := os.Getpid() + cmd := exec.Command("kill", "-1", strconv.Itoa(pid)) + return cmd.Run() +} diff --git a/utils/rotatelogs_unix.go b/utils/rotatelogs_unix.go new file mode 100644 index 0000000..6b1fe53 --- /dev/null +++ b/utils/rotatelogs_unix.go @@ -0,0 +1,30 @@ +// +build !windows + +package utils + +import ( + "os" + "path" + "pure/global" + "time" + + zaprotatelogs "github.com/lestrrat-go/file-rotatelogs" + "go.uber.org/zap/zapcore" +) + +//@function: GetWriteSyncer +//@description: zap logger中加入file-rotatelogs +//@return: zapcore.WriteSyncer, error + +func GetWriteSyncer() (zapcore.WriteSyncer, error) { + fileWriter, err := zaprotatelogs.New( + path.Join(global.MG_CONFIG.Zap.Director, "%Y-%m-%d.log"), + zaprotatelogs.WithLinkName(global.MG_CONFIG.Zap.LinkName), + zaprotatelogs.WithMaxAge(7*24*time.Hour), + zaprotatelogs.WithRotationTime(24*time.Hour), + ) + if global.MG_CONFIG.Zap.LogInConsole { + return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(fileWriter)), err + } + return zapcore.AddSync(fileWriter), err +} diff --git a/utils/rotatelogs_windows.go b/utils/rotatelogs_windows.go new file mode 100644 index 0000000..0c3f70f --- /dev/null +++ b/utils/rotatelogs_windows.go @@ -0,0 +1,26 @@ +package utils + +import ( + zaprotatelogs "github.com/lestrrat-go/file-rotatelogs" + "go.uber.org/zap/zapcore" + "os" + "path" + "pure/global" + "time" +) + +//@function: GetWriteSyncer +//@description: zap logger中加入file-rotatelogs +//@return: zapcore.WriteSyncer, error + +func GetWriteSyncer() (zapcore.WriteSyncer, error) { + fileWriter, err := zaprotatelogs.New( + path.Join(global.MG_CONFIG.Zap.Director, "%Y-%m-%d.log"), + zaprotatelogs.WithMaxAge(7*24*time.Hour), + zaprotatelogs.WithRotationTime(24*time.Hour), + ) + if global.MG_CONFIG.Zap.LogInConsole { + return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(fileWriter)), err + } + return zapcore.AddSync(fileWriter), err +} diff --git a/utils/sendSms.go b/utils/sendSms.go new file mode 100644 index 0000000..b47b240 --- /dev/null +++ b/utils/sendSms.go @@ -0,0 +1,109 @@ +package utils + +import ( + "context" + "errors" + "pure/global" + "pure/initialize/api" +) + +func SendSms(phone, code string, types int) error { + var ( + reply *api.SendSmsReply + err error + ) + ctx := context.Background() + reply, err = global.SMS_CLIENT.SendMessage(ctx, &api.SendSmsRequest{ + Phone: phone, + SmsType: int32(types), + AreaCode: code, + }) + if err != nil { + return err + } + if reply.Code != 0 { + return errors.New(reply.Message) + } + return nil +} + +func SendEmail(email, types string) (string, error) { + var ( + reply *api.SendEmailReply + err error + ) + code := GetInvitation() + str := `To authorise your Login request , please use this One Time Password (OTP): ` + code + if types == "2" { + str = `To authorise your forgot password , please use this One Time Password (OTP): ` + code + } + body := ` + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + +
+ + + + +
+

Ouction NFT

+

` + str + `

+
+

Thank you.

+

Ouction Team

+
+
+ + + + +
+

+ © Ouction NFT +

+
+
+
+ + + ` + reply, err = global.EMAIL_CLIENT.SendEmail(context.Background(), &api.SendRequest{ + To: []string{email}, + Subject: "验证码", + Body: body, + }) + if err != nil { + return "", err + } + if reply.Code != 0 { + return "", errors.New(reply.Message) + } + return code, nil +} diff --git a/utils/server.go b/utils/server.go new file mode 100644 index 0000000..8f488fc --- /dev/null +++ b/utils/server.go @@ -0,0 +1,113 @@ +package utils + +import ( + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/disk" + "github.com/shirou/gopsutil/mem" + "runtime" + "time" +) + +const ( + B = 1 + KB = 1024 * B + MB = 1024 * KB + GB = 1024 * MB +) + +type Server struct { + Os Os `json:"os"` + Cpu Cpu `json:"cpu"` + Rrm Rrm `json:"ram"` + Disk Disk `json:"disk"` +} + +type Os struct { + GOOS string `json:"goos"` + NumCPU int `json:"numCpu"` + Compiler string `json:"compiler"` + GoVersion string `json:"goVersion"` + NumGoroutine int `json:"numGoroutine"` +} + +type Cpu struct { + Cpus []float64 `json:"cpus"` + Cores int `json:"cores"` +} + +type Rrm struct { + UsedMB int `json:"usedMb"` + TotalMB int `json:"totalMb"` + UsedPercent int `json:"usedPercent"` +} + +type Disk struct { + UsedMB int `json:"usedMb"` + UsedGB int `json:"usedGb"` + TotalMB int `json:"totalMb"` + TotalGB int `json:"totalGb"` + UsedPercent int `json:"usedPercent"` +} + +//@function: InitCPU +//@description: OS信息 +//@return: o Os, err error + +func InitOS() (o Os) { + o.GOOS = runtime.GOOS + o.NumCPU = runtime.NumCPU() + o.Compiler = runtime.Compiler + o.GoVersion = runtime.Version() + o.NumGoroutine = runtime.NumGoroutine() + return o +} + +//@function: InitCPU +//@description: CPU信息 +//@return: c Cpu, err error + +func InitCPU() (c Cpu, err error) { + if cores, err := cpu.Counts(false); err != nil { + return c, err + } else { + c.Cores = cores + } + if cpus, err := cpu.Percent(time.Duration(200)*time.Millisecond, true); err != nil { + return c, err + } else { + c.Cpus = cpus + } + return c, nil +} + +//@function: InitRAM +//@description: ARM信息 +//@return: r Rrm, err error + +func InitRAM() (r Rrm, err error) { + if u, err := mem.VirtualMemory(); err != nil { + return r, err + } else { + r.UsedMB = int(u.Used) / MB + r.TotalMB = int(u.Total) / MB + r.UsedPercent = int(u.UsedPercent) + } + return r, nil +} + +//@function: InitDisk +//@description: 硬盘信息 +//@return: d Disk, err error + +func InitDisk() (d Disk, err error) { + if u, err := disk.Usage("/"); err != nil { + return d, err + } else { + d.UsedMB = int(u.Used) / MB + d.UsedGB = int(u.Used) / GB + d.TotalMB = int(u.Total) / MB + d.TotalGB = int(u.Total) / GB + d.UsedPercent = int(u.UsedPercent) + } + return d, nil +} diff --git a/utils/string.go b/utils/string.go new file mode 100644 index 0000000..1d83c3a --- /dev/null +++ b/utils/string.go @@ -0,0 +1,69 @@ +package utils + +import ( + "math" + "math/rand" + "strconv" + "time" +) + +const ( + RegPhoneNumber = `^1[3456789]\d{9}$` + RegEmailNumber = `^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$` + RegNumberAndChar = `^\w+$` + RegVersionNumber = `^([1-9]\d|[1-9])(.([1-9]\d|\d)){2}$` +) + +func GetInvitation() string { + var bs = make([]byte, 6) + for i := 0; i < 6; i++ { + rand.Seed(time.Now().UnixNano()) + flag := rand.Intn(2) + if flag == 1 { + bs[i] = byte(rand.Float64()*10 + 48) + } else { + bs[i] = byte(rand.Float64()*26 + 65) + } + } + return string(bs) +} + +func GetInvitationLen(length int) string { + var bs = make([]byte, length) + for i := 0; i < length; i++ { + rand.Seed(time.Now().UnixNano()) + flag := rand.Intn(3) + if flag == 1 { + bs[i] = byte(rand.Float64()*10 + 48) + } else if flag == 0 { + bs[i] = byte(rand.Float64()*26 + 65) + } else { + bs[i] = byte(rand.Float64()*26 + 97) + } + } + return string(bs) +} + +func GetInvitationLowerLen(length int) string { + var bs = make([]byte, length) + for i := 0; i < length; i++ { + rand.Seed(time.Now().UnixNano()) + flag := rand.Intn(2) + if flag == 1 { + bs[i] = byte(rand.Float64()*10 + 48) + } else { + bs[i] = byte(rand.Float64()*26 + 97) + } + } + return string(bs) +} + +func StringFloat64ToInt(s string) int { + f1, err := strconv.ParseFloat(s, 64) + if err != nil { + return 0 + } + s1 := strconv.FormatFloat(math.Ceil(f1), 'f', -1, 64) + i, _ := strconv.Atoi(s1) + return i +} diff --git a/utils/time.go b/utils/time.go new file mode 100644 index 0000000..3880bb8 --- /dev/null +++ b/utils/time.go @@ -0,0 +1,13 @@ +package utils + +import "time" + +const ( + DateTimeFormat string = "2006-01-02 15:04:05" + DateTimeFormat2 string = "2006-01-02 15:04" + DateFormat string = "2006-01-02" +) + +func GetCurrentTime() time.Time { + return time.Now() +} diff --git a/utils/timer/timed_task.go b/utils/timer/timed_task.go new file mode 100644 index 0000000..881fdde --- /dev/null +++ b/utils/timer/timed_task.go @@ -0,0 +1,109 @@ +package timer + +import ( + "sync" + + "github.com/robfig/cron/v3" +) + +type Timer interface { + AddTaskByFunc(taskName string, spec string, task func()) (cron.EntryID, error) + AddTaskByJob(taskName string, spec string, job interface{ Run() }) (cron.EntryID, error) + FindCron(taskName string) (*cron.Cron, bool) + StartTask(taskName string) + StopTask(taskName string) + Remove(taskName string, id int) + Clear(taskName string) + Close() +} + +// timer 定时任务管理 +type timer struct { + taskList map[string]*cron.Cron + sync.Mutex +} + +// AddTaskByFunc 通过函数的方法添加任务 +func (t *timer) AddTaskByFunc(taskName string, spec string, task func()) (cron.EntryID, error) { + t.Lock() + defer t.Unlock() + if _, ok := t.taskList[taskName]; !ok { + t.taskList[taskName] = cron.New() + } + id, err := t.taskList[taskName].AddFunc(spec, task) + t.taskList[taskName].Start() + return id, err +} + +// AddTaskByJob 通过接口的方法添加任务 +func (t *timer) AddTaskByJob(taskName string, spec string, job interface{ Run() }) (cron.EntryID, error) { + t.Lock() + defer t.Unlock() + if _, ok := t.taskList[taskName]; !ok { + t.taskList[taskName] = cron.New() + } + id, err := t.taskList[taskName].AddJob(spec, job) + t.taskList[taskName].Start() + return id, err +} + +// FindCron 获取对应taskName的cron 可能会为空 +func (t *timer) FindCron(taskName string) (*cron.Cron, bool) { + t.Lock() + defer t.Unlock() + v, ok := t.taskList[taskName] + return v, ok +} + +// StartTask 开始任务 +func (t *timer) StartTask(taskName string) { + t.Lock() + defer t.Unlock() + if v, ok := t.taskList[taskName]; ok { + v.Start() + } + return +} + +// StopTask 停止任务 +func (t *timer) StopTask(taskName string) { + t.Lock() + defer t.Unlock() + if v, ok := t.taskList[taskName]; ok { + v.Stop() + } + return +} + +// Remove 从taskName 删除指定任务 +func (t *timer) Remove(taskName string, id int) { + t.Lock() + defer t.Unlock() + if v, ok := t.taskList[taskName]; ok { + v.Remove(cron.EntryID(id)) + } + return +} + +// Clear 清除任务 +func (t *timer) Clear(taskName string) { + t.Lock() + defer t.Unlock() + if v, ok := t.taskList[taskName]; ok { + v.Stop() + delete(t.taskList, taskName) + } +} + +// Close 释放资源 +func (t *timer) Close() { + t.Lock() + defer t.Unlock() + for _, v := range t.taskList { + v.Stop() + } +} + +func NewTimerTask() Timer { + return &timer{taskList: make(map[string]*cron.Cron)} +} diff --git a/utils/upload/aliyun_oss.go b/utils/upload/aliyun_oss.go new file mode 100644 index 0000000..c4fd850 --- /dev/null +++ b/utils/upload/aliyun_oss.go @@ -0,0 +1,75 @@ +package upload + +import ( + "errors" + "mime/multipart" + "path/filepath" + "pure/global" + "time" + + "github.com/aliyun/aliyun-oss-go-sdk/oss" + "go.uber.org/zap" +) + +type AliyunOSS struct{} + +func (*AliyunOSS) UploadFile(file *multipart.FileHeader) (string, string, error) { + bucket, err := NewBucket() + if err != nil { + global.MG_LOG.Error("function AliyunOSS.NewBucket() Failed", zap.Any("err", err.Error())) + return "", "", errors.New("function AliyunOSS.NewBucket() Failed, err:" + err.Error()) + } + + // 读取本地文件。 + f, openError := file.Open() + if openError != nil { + global.MG_LOG.Error("function file.Open() Failed", zap.Any("err", openError.Error())) + return "", "", errors.New("function file.Open() Failed, err:" + openError.Error()) + } + defer f.Close() // 创建文件 defer 关闭 + // 上传阿里云路径 文件名格式 自己可以改 建议保证唯一性 + yunFileTmpPath := filepath.Join("uploads", time.Now().Format("2006-01-02")) + "/" + file.Filename + + // 上传文件流。 + err = bucket.PutObject(yunFileTmpPath, f) + if err != nil { + global.MG_LOG.Error("function formUploader.Put() Failed", zap.Any("err", err.Error())) + return "", "", errors.New("function formUploader.Put() Failed, err:" + err.Error()) + } + + return global.MG_CONFIG.AliyunOSS.BucketUrl + "/" + yunFileTmpPath, yunFileTmpPath, nil +} + +func (*AliyunOSS) DeleteFile(key string) error { + bucket, err := NewBucket() + if err != nil { + global.MG_LOG.Error("function AliyunOSS.NewBucket() Failed", zap.Any("err", err.Error())) + return errors.New("function AliyunOSS.NewBucket() Failed, err:" + err.Error()) + } + + // 删除单个文件。objectName表示删除OSS文件时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 + // 如需删除文件夹,请将objectName设置为对应的文件夹名称。如果文件夹非空,则需要将文件夹下的所有object删除后才能删除该文件夹。 + err = bucket.DeleteObject(key) + if err != nil { + global.MG_LOG.Error("function bucketManager.Delete() Filed", zap.Any("err", err.Error())) + return errors.New("function bucketManager.Delete() Filed, err:" + err.Error()) + } + + return nil +} + +func NewBucket() (*oss.Bucket, error) { + // 创建OSSClient实例。 + client, err := oss.New(global.MG_CONFIG.AliyunOSS.Endpoint, global.MG_CONFIG.AliyunOSS.AccessKeyId, global.MG_CONFIG.AliyunOSS.AccessKeySecret) + if err != nil { + return nil, err + } + + // 获取存储空间。 + bucket, err := client.Bucket(global.MG_CONFIG.AliyunOSS.BucketName) + if err != nil { + return nil, err + } + + return bucket, nil +} diff --git a/utils/upload/local.go b/utils/upload/local.go new file mode 100644 index 0000000..80b83cd --- /dev/null +++ b/utils/upload/local.go @@ -0,0 +1,79 @@ +package upload + +import ( + "errors" + "io" + "mime/multipart" + "os" + "path" + "pure/global" + "pure/utils" + "strings" + "time" + + "go.uber.org/zap" +) + +type Local struct{} + +//@object: *Local +//@function: UploadFile +//@description: 上传文件 +//@param: file *multipart.FileHeader +//@return: string, string, error + +func (*Local) UploadFile(file *multipart.FileHeader) (string, string, error) { + // 读取文件后缀 + ext := path.Ext(file.Filename) + // 读取文件名并加密 + name := strings.TrimSuffix(file.Filename, ext) + name = utils.MD5V([]byte(name)) + // 拼接新文件名 + filename := name + "_" + time.Now().Format("20060102150405") + ext + // 尝试创建此路径 + mkdirErr := os.MkdirAll(global.MG_CONFIG.Local.Path, os.ModePerm) + if mkdirErr != nil { + global.MG_LOG.Error("function os.MkdirAll() Filed", zap.Any("err", mkdirErr.Error())) + return "", "", errors.New("function os.MkdirAll() Filed, err:" + mkdirErr.Error()) + } + // 拼接路径和文件名 + p := global.MG_CONFIG.Local.Path + "/" + filename + + f, openError := file.Open() // 读取文件 + if openError != nil { + global.MG_LOG.Error("function file.Open() Filed", zap.Any("err", openError.Error())) + return "", "", errors.New("function file.Open() Filed, err:" + openError.Error()) + } + defer f.Close() // 创建文件 defer 关闭 + + out, createErr := os.Create(p) + if createErr != nil { + global.MG_LOG.Error("function os.Create() Filed", zap.Any("err", createErr.Error())) + + return "", "", errors.New("function os.Create() Filed, err:" + createErr.Error()) + } + defer out.Close() // 创建文件 defer 关闭 + + _, copyErr := io.Copy(out, f) // 传输(拷贝)文件 + if copyErr != nil { + global.MG_LOG.Error("function io.Copy() Filed", zap.Any("err", copyErr.Error())) + return "", "", errors.New("function io.Copy() Filed, err:" + copyErr.Error()) + } + return p, filename, nil +} + +//@object: *Local +//@function: DeleteFile +//@description: 删除文件 +//@param: key string +//@return: error + +func (*Local) DeleteFile(key string) error { + p := global.MG_CONFIG.Local.Path + "/" + key + if strings.Contains(p, global.MG_CONFIG.Local.Path) { + if err := os.Remove(p); err != nil { + return errors.New("本地文件删除失败, err:" + err.Error()) + } + } + return nil +} diff --git a/utils/upload/minio.go b/utils/upload/minio.go new file mode 100644 index 0000000..830bfee --- /dev/null +++ b/utils/upload/minio.go @@ -0,0 +1,123 @@ +package upload + +import ( + "bytes" + "encoding/json" + "errors" + "io" + "io/ioutil" + "mime/multipart" + "net/http" + "strings" +) + +const ( + BaseUrl = "http://file-upload-test.mangguonews.com/upload" + ImgSuffix = "jpg,jpeg,png,gif,tif,tiff,bmp," + Type = "graph,video,doc," +) + +type Response struct { + Data struct { + File string `json:"file"` + Hash string `json:"hash"` + ScaleImage string `json:"scaleImage"` + UploadFileName string `json:"uploadFileName"` + BaseUrl string `json:"baseUrl"` //给前端返回另加的参数 + } `json:"data"` + Message struct { + Desc string `json:"desc"` + Error interface{} `json:"error"` + } `json:"message"` + Status bool `json:"status"` +} + +type ParamsUpload struct { + File *multipart.FileHeader `form:"file"` //文件 + Type string `form:"type"` //类型 img:图片 + ParamsGet +} + +type ParamsGet struct { + Width string `form:"width"` + Height string `form:"height"` + Scale string `form:"scale"` +} + +func createMgNewsUploadRequest(file multipart.File, params map[string]string, fileName string) (*http.Request, error) { + var ( + err error + body *bytes.Buffer + w *multipart.Writer + writer io.Writer + req *http.Request + contentType string + ) + body = &bytes.Buffer{} + w = multipart.NewWriter(body) + contentType = w.FormDataContentType() + for key, val := range params { + _ = w.WriteField(key, val) + } + if file != nil { + writer, err = w.CreateFormFile("file", fileName) + _, err = io.Copy(writer, file) + if err != nil { + return nil, err + } + } + w.Close() + req, err = http.NewRequest(http.MethodPost, BaseUrl, body) + req.Header.Set("Content-Type", contentType) + return req, err +} + +func MgNewsUpload(file multipart.File, pm map[string]string, fileName string) (respData Response, err error) { + var ( + client *http.Client + req *http.Request + resp *http.Response + resBody []byte + ) + client = &http.Client{} + req, err = createMgNewsUploadRequest(file, pm, fileName) + if err != nil { + return + } + resp, _ = client.Do(req) + defer resp.Body.Close() + resBody, err = ioutil.ReadAll(resp.Body) + if err != nil { + return + } + if resp.StatusCode != 200 { + err = errors.New("上传失败") + return + } + //fmt.Println(string(resBody)) + err = json.Unmarshal(resBody, &respData) + if err != nil { + return + } + return +} + +func CheckType(t string) bool { + if strings.Index(Type, strings.ToLower(t)+",") >= 0 { + return true + } + return false +} + +func CheckFileSuffix(fileName string, t string) bool { + var suffix string + suffix = fileName[(strings.LastIndex(fileName, "."))+1:] + if t == "graph" { + if strings.Index(ImgSuffix, strings.ToLower(suffix)+",") >= 0 { + return true + } + } else { + return false + } + return false +} diff --git a/utils/upload/tencent_cos.go b/utils/upload/tencent_cos.go new file mode 100644 index 0000000..0ad3843 --- /dev/null +++ b/utils/upload/tencent_cos.go @@ -0,0 +1,60 @@ +package upload + +import ( + "context" + "errors" + "fmt" + "mime/multipart" + "net/http" + "net/url" + "pure/global" + "time" + + "github.com/tencentyun/cos-go-sdk-v5" + "go.uber.org/zap" +) + +type TencentCOS struct{} + +// UploadFile upload file to COS +func (*TencentCOS) UploadFile(file *multipart.FileHeader) (string, string, error) { + client := NewClient() + f, openError := file.Open() + if openError != nil { + global.MG_LOG.Error("function file.Open() Filed", zap.Any("err", openError.Error())) + return "", "", errors.New("function file.Open() Filed, err:" + openError.Error()) + } + defer f.Close() // 创建文件 defer 关闭 + fileKey := fmt.Sprintf("%d%s", time.Now().Unix(), file.Filename) + + _, err := client.Object.Put(context.Background(), global.MG_CONFIG.TencentCOS.PathPrefix+"/"+fileKey, f, nil) + if err != nil { + panic(err) + } + return global.MG_CONFIG.TencentCOS.BaseURL + "/" + global.MG_CONFIG.TencentCOS.PathPrefix + "/" + fileKey, fileKey, nil +} + +// DeleteFile delete file form COS +func (*TencentCOS) DeleteFile(key string) error { + client := NewClient() + name := global.MG_CONFIG.TencentCOS.PathPrefix + "/" + key + _, err := client.Object.Delete(context.Background(), name) + if err != nil { + global.MG_LOG.Error("function bucketManager.Delete() Filed", zap.Any("err", err.Error())) + return errors.New("function bucketManager.Delete() Filed, err:" + err.Error()) + } + return nil +} + +// NewClient init COS client +func NewClient() *cos.Client { + urlStr, _ := url.Parse("https://" + global.MG_CONFIG.TencentCOS.Bucket + ".cos." + global.MG_CONFIG.TencentCOS.Region + ".myqcloud.com") + baseURL := &cos.BaseURL{BucketURL: urlStr} + client := cos.NewClient(baseURL, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: global.MG_CONFIG.TencentCOS.SecretID, + SecretKey: global.MG_CONFIG.TencentCOS.SecretKey, + }, + }) + return client +} diff --git a/utils/validator.go b/utils/validator.go new file mode 100644 index 0000000..b5c2415 --- /dev/null +++ b/utils/validator.go @@ -0,0 +1,368 @@ +package utils + +import ( + "bytes" + "errors" + "pure/model/request" + "reflect" + "strconv" + "strings" +) + +type Rules map[string][]string + +type RulesMap map[string]Rules + +var CustomizeMap = make(map[string]Rules) + +//@function: RegisterRule +//@description: 注册自定义规则方案建议在路由初始化层即注册 +//@param: key string, rule Rules +//@return: err error + +func RegisterRule(key string, rule Rules) (err error) { + if CustomizeMap[key] != nil { + return errors.New(key + "已注册,无法重复注册") + } else { + CustomizeMap[key] = rule + return nil + } +} + +//@function: NotEmpty +//@description: 非空 不能为其对应类型的0值 +//@return: string + +func NotEmpty() string { + return "notEmpty" +} + +//@function: Lt +//@description: 小于入参(<) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较 +//@param: mark string +//@return: string + +func Lt(mark string) string { + return "lt=" + mark +} + +//@function: Le +//@description: 小于等于入参(<=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较 +//@param: mark string +//@return: string + +func Le(mark string) string { + return "le=" + mark +} + +//@function: Eq +//@description: 等于入参(==) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较 +//@param: mark string +//@return: string + +func Eq(mark string) string { + return "eq=" + mark +} + +//@function: Ne +//@description: 不等于入参(!=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较 +//@param: mark string +//@return: string + +func Ne(mark string) string { + return "ne=" + mark +} + +//@function: Ge +//@description: 大于等于入参(>=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较 +//@param: mark string +//@return: string + +func Ge(mark string) string { + return "ge=" + mark +} + +//@function: Gt +//@description: 大于入参(>) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较 +//@param: mark string +//@return: string + +func Gt(mark string) string { + return "gt=" + mark +} + +func Ct(marks ...string) string { + var result bytes.Buffer + for _, value := range marks { + result.WriteString(value + ",") + } + return "ct=" + result.String() +} + +//@function: Verify +//@description: 校验方法 +//@param: st interface{}, roleMap Rules(入参实例,规则map) +//@return: err error + +func Verify(st interface{}, roleMap Rules) (err error) { + compareMap := map[string]bool{ + "lt": true, + "le": true, + "eq": true, + "ne": true, + "ge": true, + "gt": true, + } + + compareMap2 := map[string]bool{ + "ct": true, + } + + typ := reflect.TypeOf(st) + val := reflect.ValueOf(st) // 获取reflect.Type类型 + + kd := val.Kind() // 获取到st对应的类别 + if kd != reflect.Struct { + return errors.New("expect struct") + } + num := val.NumField() + // 遍历结构体的所有字段 + for i := 0; i < num; i++ { + tagVal := typ.Field(i) + val := val.Field(i) + if len(roleMap[tagVal.Name]) > 0 { + for _, v := range roleMap[tagVal.Name] { + switch { + case v == "notEmpty": + if isBlank(val) { + return errors.New(tagVal.Name + "值不能为空") + } + case compareMap[strings.Split(v, "=")[0]]: + if !compareVerify(val, v) { + return errors.New(tagVal.Name + "长度或值不在合法范围," + v) + } + case compareMap2[strings.Split(v, "=")[0]]: + if !compareVerify2(val, v) { + return errors.New(tagVal.Name + "取值不可用," + v) + } + } + } + } + } + return nil +} + +func Verify2(st request.StructParams, roleMap Rules) (err error) { + compareMap := map[string]bool{ + "lt": true, + "le": true, + "eq": true, + "ne": true, + "ge": true, + "gt": true, + } + compareMap2 := map[string]bool{ + "ct": true, + } + for stk, stv := range st { + val := reflect.ValueOf(stv) + if len(roleMap[stk]) > 0 { + for _, v := range roleMap[stk] { + switch { + case v == "notEmpty": + if isBlank(val) { + return errors.New(stk + "值不能为空") + } + case compareMap[strings.Split(v, "=")[0]]: + if !compareVerify(val, v) { + return errors.New(stk + "长度或值不在合法范围," + v) + } + case compareMap2[strings.Split(v, "=")[0]]: + if !compareVerify2(val, v) { + return errors.New(stk + "取值不可用," + v) + } + } + } + } + } + return nil +} + +//@function: compareVerify +//@description: 长度和数字的校验方法 根据类型自动校验 +//@param: value reflect.Value, VerifyStr string +//@return: bool + +func compareVerify(value reflect.Value, VerifyStr string) bool { + switch value.Kind() { + case reflect.String, reflect.Slice, reflect.Array: + return compare(value.Len(), VerifyStr) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return compare(value.Uint(), VerifyStr) + case reflect.Float32, reflect.Float64: + return compare(value.Float(), VerifyStr) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return compare(value.Int(), VerifyStr) + default: + return false + } +} + +func compareVerify2(value reflect.Value, VerifyStr string) bool { + if value.String() != "" { + v := value.String() + "," + if strings.Index(VerifyStr, v) > 0 { + return true + } + } + return false +} + +//@function: isBlank +//@description: 非空校验 +//@param: value reflect.Value +//@return: bool + +func isBlank(value reflect.Value) bool { + switch value.Kind() { + case reflect.String: + return value.Len() == 0 + case reflect.Bool: + return !value.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return value.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return value.Uint() == 0 + case reflect.Float32, reflect.Float64: + return value.Float() == 0 + case reflect.Interface, reflect.Ptr: + return value.IsNil() + } + return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface()) +} + +//@function: compare +//@description: 比较函数 +//@param: value interface{}, VerifyStr string +//@return: bool + +func compare(value interface{}, VerifyStr string) bool { + VerifyStrArr := strings.Split(VerifyStr, "=") + val := reflect.ValueOf(value) + switch val.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + VInt, VErr := strconv.ParseInt(VerifyStrArr[1], 10, 64) + if VErr != nil { + return false + } + switch { + case VerifyStrArr[0] == "lt": + return val.Int() < VInt + case VerifyStrArr[0] == "le": + return val.Int() <= VInt + case VerifyStrArr[0] == "eq": + return val.Int() == VInt + case VerifyStrArr[0] == "ne": + return val.Int() != VInt + case VerifyStrArr[0] == "ge": + return val.Int() >= VInt + case VerifyStrArr[0] == "gt": + return val.Int() > VInt + default: + return false + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + VInt, VErr := strconv.Atoi(VerifyStrArr[1]) + if VErr != nil { + return false + } + switch { + case VerifyStrArr[0] == "lt": + return val.Uint() < uint64(VInt) + case VerifyStrArr[0] == "le": + return val.Uint() <= uint64(VInt) + case VerifyStrArr[0] == "eq": + return val.Uint() == uint64(VInt) + case VerifyStrArr[0] == "ne": + return val.Uint() != uint64(VInt) + case VerifyStrArr[0] == "ge": + return val.Uint() >= uint64(VInt) + case VerifyStrArr[0] == "gt": + return val.Uint() > uint64(VInt) + default: + return false + } + case reflect.Float32, reflect.Float64: + VFloat, VErr := strconv.ParseFloat(VerifyStrArr[1], 64) + if VErr != nil { + return false + } + switch { + case VerifyStrArr[0] == "lt": + return val.Float() < VFloat + case VerifyStrArr[0] == "le": + return val.Float() <= VFloat + case VerifyStrArr[0] == "eq": + return val.Float() == VFloat + case VerifyStrArr[0] == "ne": + return val.Float() != VFloat + case VerifyStrArr[0] == "ge": + return val.Float() >= VFloat + case VerifyStrArr[0] == "gt": + return val.Float() > VFloat + default: + return false + } + default: + return false + } +} + +func Transform(st request.StructParams, fields ...string) map[string]interface{} { + var ( + fm = make(map[string]string) + res = make(map[string]interface{}) + ) + for _, v := range fields { + fm[v] = v + } + for k, v := range st { + if field, ok := fm[snakeString(k)]; ok { + res[field] = v + } + } + return res +} + +func TransformRuin(st request.StructParams, fields ...string) map[string]interface{} { + var ( + fm = make(map[string]string) + res = make(map[string]interface{}) + ) + for _, v := range fields { + fm[v] = v + } + for k, v := range st { + if _, ok := fm[snakeString(k)]; !ok { + res[snakeString(k)] = v + } + } + return res +} + +func snakeString(s string) string { + data := make([]byte, 0, len(s)*2) + j := false + num := len(s) + for i := 0; i < num; i++ { + d := s[i] + if i > 0 && d >= 'A' && d <= 'Z' && j { + data = append(data, '_') + } + if d != '_' { + j = true + } + data = append(data, d) + } + return strings.ToLower(string(data[:])) +} diff --git a/utils/verify.go b/utils/verify.go new file mode 100644 index 0000000..ef6717d --- /dev/null +++ b/utils/verify.go @@ -0,0 +1,27 @@ +package utils + +var ( + IdVerify = Rules{"ID": {NotEmpty()}} + SendMessageVerity = Rules{"Phone": {NotEmpty()}, "Type": {NotEmpty()}} + SendEmailVerify = Rules{"Email": {NotEmpty()}} + LoginVerify = Rules{"Appid": {NotEmpty()}, "Type": {NotEmpty()}} + LoginPhoneVerify = Rules{"Phone": {NotEmpty()}, "Code": {NotEmpty()}} + LoginEmailVerify = Rules{"Email": {NotEmpty()}, "Code": {NotEmpty()}} + RegisterVerify = Rules{"Email": {NotEmpty()}, "Code": {NotEmpty()}, "Appid": {NotEmpty()}, "Nickname": {NotEmpty()}, "Avatar": {NotEmpty()}} + BandPhoneVerify = Rules{"Phone": {NotEmpty()}, "Code": {NotEmpty()}} + PlatformAuthVerify = Rules{"Platform": {NotEmpty()}} + TypeVerify = Rules{"Type": {NotEmpty()}} + PageInfoVerify = Rules{"Page": {NotEmpty()}, "PageSize": {NotEmpty()}} + MissionClaimVerify = Rules{"MissionId": {NotEmpty()}, "AddressId": {NotEmpty()}} + MissionIdVerify = Rules{"MissionId": {NotEmpty()}} + SpuNoVerify = Rules{"SpuNo": {NotEmpty()}} + CustomerGoodsVerify = Rules{"SkuNo": {NotEmpty()}} + MissionClaimIdVerify = Rules{"MissionClaimId": {NotEmpty()}} + MissionCodeVerify = Rules{"Code": {NotEmpty()}} + DictDataVerity = Rules{"TypeCode": {NotEmpty()}} + BillListVerity = Rules{"Uint": {NotEmpty()}} + OrderIdVerity = Rules{"OrderID": {NotEmpty()}} + WithdrawalVerity = Rules{"Phone": {NotEmpty()}, "Code": {NotEmpty()}, "Amount": {NotEmpty()}, "AccountID": {NotEmpty()}} + FlowNoVerity = Rules{"FlowNo": {NotEmpty()}} + ChainVerify = Rules{"Hash": {NotEmpty()}} +) diff --git a/utils/zipfiles.go b/utils/zipfiles.go new file mode 100644 index 0000000..921c9b4 --- /dev/null +++ b/utils/zipfiles.go @@ -0,0 +1,71 @@ +package utils + +import ( + "archive/zip" + "io" + "os" + "strings" +) + +//@function: ZipFiles +//@description: 压缩文件 +//@param: filename string, files []string, oldForm, newForm string +//@return: error + +func ZipFiles(filename string, files []string, oldForm, newForm string) error { + + newZipFile, err := os.Create(filename) + if err != nil { + return err + } + defer func() { + _ = newZipFile.Close() + }() + + zipWriter := zip.NewWriter(newZipFile) + defer func() { + _ = zipWriter.Close() + }() + + // 把files添加到zip中 + for _, file := range files { + + err = func(file string) error { + zipFile, err := os.Open(file) + if err != nil { + return err + } + defer zipFile.Close() + // 获取file的基础信息 + info, err := zipFile.Stat() + if err != nil { + return err + } + + header, err := zip.FileInfoHeader(info) + if err != nil { + return err + } + + // 使用上面的FileInforHeader() 就可以把文件保存的路径替换成我们自己想要的了,如下面 + header.Name = strings.Replace(file, oldForm, newForm, -1) + + // 优化压缩 + // 更多参考see http://golang.org/pkg/archive/zip/#pkg-constants + header.Method = zip.Deflate + + writer, err := zipWriter.CreateHeader(header) + if err != nil { + return err + } + if _, err = io.Copy(writer, zipFile); err != nil { + return err + } + return nil + }(file) + if err != nil { + return err + } + } + return nil +} diff --git a/webhook.json b/webhook.json new file mode 100644 index 0000000..7682f1c --- /dev/null +++ b/webhook.json @@ -0,0 +1,546 @@ +//用户付款 +{ + "id": "WH-62W810145R7409724-8CH11354TY024302T", + "event_version": "1.0", + "create_time": "2022-10-21T06:42:32.606Z", + "resource_type": "checkout-order", + "resource_version": "2.0", + "event_type": "CHECKOUT.ORDER.APPROVED", + "summary": "An order has been approved by buyer", + "resource": { + "create_time": "2022-10-21T06:27:07Z", + "purchase_units": [ + { + "reference_id": "default", + "amount": { + "currency_code": "USD", + "value": "4999.81" + }, + "payee": { + "email_address": "sb-gsncy21794962@business.example.com", + "merchant_id": "3SQBR4YEWZ4BA" + }, + "shipping": { + "name": { + "full_name": "John Doe" + }, + "address": { + "address_line_1": "1 Main St", + "admin_area_2": "San Jose", + "admin_area_1": "CA", + "postal_code": "95131", + "country_code": "US" + } + } + } + ], + "links": [ + { + "href": "https://api.sandbox.paypal.com/v2/checkout/orders/9JL52742K01513702", + "rel": "self", + "method": "GET" + }, + { + "href": "https://api.sandbox.paypal.com/v2/checkout/orders/9JL52742K01513702", + "rel": "update", + "method": "PATCH" + }, + { + "href": "https://api.sandbox.paypal.com/v2/checkout/orders/9JL52742K01513702/capture", + "rel": "capture", + "method": "POST" + } + ], + "id": "9JL52742K01513702", + "payment_source": { + "paypal": {} + }, + "intent": "CAPTURE", + "payer": { + "name": { + "given_name": "John", + "surname": "Doe" + }, + "email_address": "sb-79rfq21745286@business.example.com", + "payer_id": "RCSNJCSEN36ZJ", + "address": { + "country_code": "US" + } + }, + "status": "APPROVED" + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-62W810145R7409724-8CH11354TY024302T", + "rel": "self", + "method": "GET" + }, + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-62W810145R7409724-8CH11354TY024302T/resend", + "rel": "resend", + "method": "POST" + } + ] +} +//确认收款 +{ + "id": "WH-4KR61645R81861232-4LN31734K5078982S", + "event_version": "1.0", + "create_time": "2022-10-21T06:46:50.303Z", + "resource_type": "capture", + "resource_version": "2.0", + "event_type": "PAYMENT.CAPTURE.COMPLETED", + "summary": "Payment completed for $ 4999.81 USD", + "resource": { + "amount": { + "value": "4999.81", + "currency_code": "USD" + }, + "seller_protection": { + "dispute_categories": [ + "ITEM_NOT_RECEIVED", + "UNAUTHORIZED_TRANSACTION" + ], + "status": "ELIGIBLE" + }, + "supplementary_data": { + "related_ids": { + "order_id": "9JL52742K01513702" + } + }, + "update_time": "2022-10-21T06:46:46Z", + "create_time": "2022-10-21T06:46:46Z", + "final_capture": true, + "seller_receivable_breakdown": { + "paypal_fee": { + "value": "195.29", + "currency_code": "USD" + }, + "gross_amount": { + "value": "4999.81", + "currency_code": "USD" + }, + "net_amount": { + "value": "4804.52", + "currency_code": "USD" + } + }, + "links": [ + { + "method": "GET", + "rel": "self", + "href": "https://api.sandbox.paypal.com/v2/payments/captures/5FH6806799924231W" + }, + { + "method": "POST", + "rel": "refund", + "href": "https://api.sandbox.paypal.com/v2/payments/captures/5FH6806799924231W/refund" + }, + { + "method": "GET", + "rel": "up", + "href": "https://api.sandbox.paypal.com/v2/checkout/orders/9JL52742K01513702" + } + ], + "id": "5FH6806799924231W", + "status": "COMPLETED" + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-4KR61645R81861232-4LN31734K5078982S", + "rel": "self", + "method": "GET" + }, + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-4KR61645R81861232-4LN31734K5078982S/resend", + "rel": "resend", + "method": "POST" + } + ] +} +//提现(提现失败回调) +{ + "id": "WH-5A19140561140630Y-2JL02815W4313754E", + "event_version": "1.0", + "create_time": "2022-10-21T07:14:45.696Z", + "resource_type": "payouts", + "event_type": "PAYMENT.PAYOUTSBATCH.DENIED", + "summary": "Payouts batch got denied.", + "resource": { + "batch_header": { + "payout_batch_id": "34MY452YBHPQW", + "batch_status": "DENIED", + "time_created": "2022-10-21T07:14:34Z", + "sender_batch_header": { + "sender_batch_id": "dsdsdsd" + }, + "funding_source": "BALANCE", + "amount": { + "currency": "USD", + "value": "0.00" + }, + "fees": { + "currency": "USD", + "value": "0.00" + }, + "payments": 1 + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/payments/payouts/34MY452YBHPQW", + "rel": "self", + "method": "GET", + "encType": "application/json" + } + ] + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-5A19140561140630Y-2JL02815W4313754E", + "rel": "self", + "method": "GET" + }, + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-5A19140561140630Y-2JL02815W4313754E/resend", + "rel": "resend", + "method": "POST" + } + ] +} +//转账成功 +{ + "id": "WH-27156021MJ807552P-9XF02986TA428514C", + "event_version": "1.0", + "create_time": "2022-10-21T07:34:58.791Z", + "resource_type": "payouts", + "event_type": "PAYMENT.PAYOUTSBATCH.SUCCESS", + "summary": "Payouts batch completed successfully.", + "resource": { + "batch_header": { + "payout_batch_id": "RLBRKVTX9W5JL", + "batch_status": "SUCCESS", + "time_created": "2022-10-21T07:34:44Z", + "time_completed": "2022-10-21T07:34:45Z", + "time_closed": "2022-10-21T07:34:45Z", + "sender_batch_header": { + "sender_batch_id": "dsdsdsd" + }, + "funding_source": "BALANCE", + "amount": { + "currency": "USD", + "value": "96.00" + }, + "fees": { + "currency": "USD", + "value": "1.92" + }, + "payments": 1 + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/payments/payouts/RLBRKVTX9W5JL", + "rel": "self", + "method": "GET", + "encType": "application/json" + } + ] + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-27156021MJ807552P-9XF02986TA428514C", + "rel": "self", + "method": "GET" + }, + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-27156021MJ807552P-9XF02986TA428514C/resend", + "rel": "resend", + "method": "POST" + } + ] +} +//取消支付(订单退款) +{ + "id": "WH-7GU47175YW005840T-0VM77075J61186502", + "event_version": "1.0", + "create_time": "2022-10-21T07:50:01.873Z", + "resource_type": "refund", + "resource_version": "2.0", + "event_type": "PAYMENT.CAPTURE.REFUNDED", + "summary": "A $ 4999.81 USD capture payment was refunded", + "resource": { + "seller_payable_breakdown": { + "total_refunded_amount": { + "value": "4999.81", + "currency_code": "USD" + }, + "paypal_fee": { + "value": "194.99", + "currency_code": "USD" + }, + "gross_amount": { + "value": "4999.81", + "currency_code": "USD" + }, + "net_amount": { + "value": "4804.82", + "currency_code": "USD" + } + }, + "amount": { + "value": "4999.81", + "currency_code": "USD" + }, + "update_time": "2022-10-21T00:49:57-07:00", + "create_time": "2022-10-21T00:49:57-07:00", + "links": [ + { + "method": "GET", + "rel": "self", + "href": "https://api.sandbox.paypal.com/v2/payments/refunds/9F317409RP583132H" + }, + { + "method": "GET", + "rel": "up", + "href": "https://api.sandbox.paypal.com/v2/payments/captures/5FH6806799924231W" + } + ], + "id": "9F317409RP583132H", + "status": "COMPLETED" + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-7GU47175YW005840T-0VM77075J61186502", + "rel": "self", + "method": "GET" + }, + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-7GU47175YW005840T-0VM77075J61186502/resend", + "rel": "resend", + "method": "POST" + } + ] +} +//转账item信息 +{ + "id": "WH-62214818PA778164H-6VJ474188Y3865907", + "event_version": "1.0", + "create_time": "2022-10-21T07:14:45.699Z", + "resource_type": "payouts_item", + "event_type": "PAYMENT.PAYOUTS-ITEM.FAILED", + "summary": "A payout item has failed", + "resource": { + "payout_item_fee": { + "currency": "USD", + "value": "0.00" + }, + "transaction_status": "FAILED", + "sender_batch_id": "dsdsdsd", + "time_processed": "2022-10-21T07:14:34Z", + "payout_item": { + "recipient_type": "EMAIL", + "amount": { + "currency": "USD", + "value": "0.00" + }, + "note": "打款", + "receiver": "sb-e37dy21833133@personal.example.com", + "recipient_wallet": "PAYPAL" + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/payments/payouts-item/C67WB53FB6BAW", + "rel": "self", + "method": "GET", + "encType": "application/json" + }, + { + "href": "https://api.sandbox.paypal.com/v1/payments/payouts/34MY452YBHPQW", + "rel": "batch", + "method": "GET", + "encType": "application/json" + } + ], + "payout_item_id": "C67WB53FB6BAW", + "payout_batch_id": "34MY452YBHPQW", + "errors": { + "name": "ZERO_AMOUNT", + "message": "The Payout can't be done without any amount. You must enter a valid amount that's greater than zero.", + "information_link": "https://developer.paypal.com/docs/api/payments.payouts-batch/#errors", + "details": [], + "links": [] + } + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-62214818PA778164H-6VJ474188Y3865907", + "rel": "self", + "method": "GET" + }, + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-62214818PA778164H-6VJ474188Y3865907/resend", + "rel": "resend", + "method": "POST" + } + ] +} + +{ + "id": "WH-4CJ36714CJ204831L-9DY42878JG883501V", + "event_version": "1.0", + "create_time": "2022-10-21T07:34:58.765Z", + "resource_type": "payouts_item", + "event_type": "PAYMENT.PAYOUTS-ITEM.SUCCEEDED", + "summary": "A payout item has succeeded", + "resource": { + "transaction_id": "7X589343BN135035E", + "payout_item_fee": { + "currency": "USD", + "value": "1.92" + }, + "transaction_status": "SUCCESS", + "sender_batch_id": "dsdsdsd", + "time_processed": "2022-10-21T07:34:45Z", + "activity_id": "07S085733Y1996237", + "payout_item": { + "recipient_type": "EMAIL", + "amount": { + "currency": "USD", + "value": "96.00" + }, + "note": "打款", + "receiver": "sb-e37dy21833133@personal.example.com", + "recipient_wallet": "PAYPAL" + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/payments/payouts-item/RGQUU37L46TEQ", + "rel": "self", + "method": "GET", + "encType": "application/json" + }, + { + "href": "https://api.sandbox.paypal.com/v1/payments/payouts/RLBRKVTX9W5JL", + "rel": "batch", + "method": "GET", + "encType": "application/json" + } + ], + "payout_item_id": "RGQUU37L46TEQ", + "payout_batch_id": "RLBRKVTX9W5JL" + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-4CJ36714CJ204831L-9DY42878JG883501V", + "rel": "self", + "method": "GET" + }, + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-4CJ36714CJ204831L-9DY42878JG883501V/resend", + "rel": "resend", + "method": "POST" + } + ] +} + + + +{ + "id": "WH-2B088173KT8286923-7YM54303XB465773L", + "event_version": "1.0", + "create_time": "2022-11-03T13:58:49.707Z", + "resource_type": "payouts", + "event_type": "PAYMENT.PAYOUTSBATCH.PROCESSING", + "summary": "Payouts batch is getting processed.", + "resource": { + "batch_header": { + "payout_batch_id": "444ZSA7VMXR5L", + "batch_status": "PROCESSING", + "time_created": "2022-11-03T13:58:31Z", + "time_completed": "2022-11-03T13:58:33Z", + "time_closed": "2022-11-03T13:58:33Z", + "sender_batch_header": { + "sender_batch_id": "202211031358298010010001" + }, + "funding_source": "BALANCE", + "amount": { + "currency": "USD", + "value": "499.00" + }, + "fees": { + "currency": "USD", + "value": "9.98" + }, + "payments": 1 + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/payments/payouts/444ZSA7VMXR5L", + "rel": "self", + "method": "GET", + "encType": "application/json" + } + ] + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2B088173KT8286923-7YM54303XB465773L", + "rel": "self", + "method": "GET" + }, + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2B088173KT8286923-7YM54303XB465773L/resend", + "rel": "resend", + "method": "POST" + } + ] +} + +{ + "id": "WH-2PN47871N9299911D-36A939639Y5266517", + "event_version": "1.0", + "create_time": "2022-11-22T15:36:17.558Z", + "resource_type": "payouts", + "event_type": "PAYMENT.PAYOUTSBATCH.SUCCESS", + "summary": "Payouts batch completed successfully.", + "resource": { + "batch_header": { + "payout_batch_id": "7KD8ZC2WRXZYN", + "batch_status": "SUCCESS", + "time_created": "2022-11-22T15:36:02Z", + "time_completed": "2022-11-22T15:36:03Z", + "sender_batch_header": { + "sender_batch_id": "202211222335594910010002" + }, + "funding_source": "BALANCE", + "amount": { + "currency": "USD", + "value": "3000.00" + }, + "fees": { + "currency": "USD", + "value": "0.25" + }, + "payments": 1 + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/payments/payouts/7KD8ZC2WRXZYN", + "rel": "self", + "method": "GET", + "encType": "application/json" + } + ] + }, + "links": [ + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2PN47871N9299911D-36A939639Y5266517", + "rel": "self", + "method": "GET" + }, + { + "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2PN47871N9299911D-36A939639Y5266517/resend", + "rel": "resend", + "method": "POST" + } + ] +} \ No newline at end of file