diff --git a/app/user/cmd/api/etc/main.yaml b/app/user/cmd/api/etc/main.yaml new file mode 100644 index 0000000..50b7ef3 --- /dev/null +++ b/app/user/cmd/api/etc/main.yaml @@ -0,0 +1,42 @@ +Name: user +Host: 0.0.0.0 +Port: 8888 +DataSource: "qnc:5vg67b3UNHu8@tcp(127.0.0.1:20001)/qnc?charset=utf8mb4&parseTime=True&loc=Local" +CacheRedis: + - Host: "127.0.0.1:20002" + Pass: "3m3WsgyCKWqz" # Redis 密码,如果未设置则留空 + Type: "node" # 单节点模式 +JwtAuth: + AccessSecret: "WUvoIwL-FK0qnlxhvxR9tV6SjfOpeJMpKmY2QvT99lA" + AccessExpire: 86400 # JWT过期时间 + RefreshAfter: 43200 # 更新时间 +VerifyCode: + AccessKeyID: "LTAI5tKGB3TVJbMHSoZN3yr9" + AccessKeySecret: "OCQ30GWp4yENMjmfOAaagksE18bp65" + EndpointURL: "dysmsapi.aliyuncs.com" + SignName: "天远数据" + TemplateCode: "SMS_474525324" + ValidTime: 300 +Encrypt: + SecretKey: "ff83609b2b24fc73196aac3d3dfb874f" +WestConfig: + Url: "http://proxy.tianyuanapi.com/api/invoke" + Key: "121a1e41fc1690dd6b90afbcacd80cf4" + SecretId: "449159" + SecretSecondId: "296804" +Alipay: + AppID: "2021004165608254" + PrivateKey: "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCvo8TmTNnVguKwMYrX0z01PfUlSS+AqwwCH1+/P39q6No+09yO1bjhy4LowtDfwKX8F+IZLl5Cx06f1M8KzPvjQliBAfMJ1FuTEOOXPmtE1YLAYIUMLbltR6Crnp16T28eF41Uo0PUo2ple/oSjWhYgsTJjyBMXY04f6HM2uZlHOhG2aOUz2CDNbvkEhNddazuPMgo8Xl7vwENGDFTPa85HmSSoDppFowLdYfAw2Jl1ilKNg4sOPc6d507nXdgpMlUguwZxol6OQ2hBS6v9OjII5cJ1tyR/klJRapnIPmFaPvhDozYwjU6Z3jMvcbrByl0qNpLrbEFS4pn9hfRo4YrAgMBAAECggEAZAi0Ri6TCqXnEk7FMzMec0p8auYJ5hCFYFgaIkS5/1vroUjtH3TePcu5HXSHnkiMwM2hepIMIaB+SU3dNduVwtOwsJk5oOmP1m0SErv8QFISjBrs7AjGyVS4T8ahDl5bfRoQ5pmuMld4a6B2x0Y+ndqs1ddsn9HQctNOhexOuFsSjX1N3PZxFzfRTmGzxf7kwZGlXMN7G1r3Rp4koylYHVpqjXIK34Anc8SVljxFVkFOk62QvBdYcCucepymHNl0pYwPDCCylPH8OpIXOErmPldTflmoLRc+ywu9rw4I8UvkoPgTe+16he+jdi/N7cwbMTfixq+/Aeadjv2AgMuwkQKBgQDgLS3dRFAc6FMSJIA0FKgv5D/R3NZgWilbOAF11PtnE4AX4i0yZryGtLq+3NWCWYQF8iI60lIy3rEf9zWncwfadhWTEDUBjjrqqU46N2ddTzHsDw09I56TT2vrEwCdmJ2vh1hxPfgE3fSDnKbP4Wkl77JCTH7v0rA1jb65Plt8TwKBgQDIkrXqe/pVHDdxswoPL6em32TnKiaJ/R/UDDio20mgGG7FWEJAY5yYtu0y9Ug7W8PjJE7/cJ2/dwDSvHZm8R0iq8d6XkzN03Z+uvzGnMdUraXJZHSPZ5L/2ofysXjt/OtpA1Sox5++1+obiq6CZ6IYORLSxSf+it1JUbKXsNcVZQKBgQCTPzm7984DXtqJtS38h4D9jBgbWcn6Gd7GSuAyrIXBa76ccXSsgWzdskJjcZxQdUnRufyf1Fwni7yeOXullFoZNazwHxoh/nFWh4SZmqCrWoR5AF36xbW4HtfM3XtvCLqye90s7L5HPB8Kf8/WBcJSJ8JX5/UMw7/4PTWEaaAf4wKBgQCEXu7YVgIccYbV7wdQhm7q3rxFI7hTkU6UL4ylRDQPCJDyhREUValf0DozS1XkdueM3MWWJ8i0N+G/MsohnjdQTnZT+DBQFqM5eEai/Y1AAWpMw5N5oS2O1barIR1iU2053QzeZwCyfuTuUFRjk+mSevhFSgDfKN5qKRTor7kDUQKBgB3fC6jO8XCwimPvpsiGnuddNAq/w8iqSjSwuSvbI0Q7Lq6rvAIw2AmkC5t4kW4JcZLUgDvAs4GFoPDYhoL73vc1e2c35VTNck6IxZSQzzQ9pfXFiLtTe6eqggN4EOPGHKLd92CMAgoeySsp3NydpGSx2N/NUqp8BkoFLQ/k2W9o" + AlipayPublicKey: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2CqoCp95w/JV3RT/gzF4/8QmVT1HQNaeW7yUp+mA7x9AbjvlTW/+eRn6oGAL/XhZLjvHD0XjKLVKX0MJVS1aUQHEHEbOJN4Eu8II45OavD4iZISa7Kp9V6AM+i4qTyaeV2wNDnGxHQBaLVUGCfMR+56EK2YpORdE1H9uy72SSQseVb3bmpsV9EW/IJNmcVL/ut3uA1JWAoRmzlQ7ekxg7p8AYXzYPEHQr1tl7W+M4zv9wO9GKZCxIqMA8U3RP5npPfRaCfIRGzXzCqFEEUvWuidOB7frsvN4jiPD07qpL2Bi9LM1X/ee2kC/oM8Uhd7ERZhG8MbZfijZKxgrsDKBcwIDAQAB" + IsProduction: true + NotifyUrl: "https://6m4685017o.goho.co/api/v1/pay/alipay/callback" +Wxpay: + AppID: "1682635136" + MchID: "1682635136" + MchCertificateSerialNumber: "5369B8AEEBDCF7AF274510252E6A8C0659C30F61" + MchApiv3Key: "e3ea4cf0765f1e71b01bb387dfcdbc9f" + MchPrivateKeyPath: "merchant/apiclient_key.pem" + NotifyUrl: "https://6m4685017o.goho.co/api/v1/pay/wechat/callback" + RefundNotifyUrl: "https://6m4685017o.goho.co/api/v1/wechat/refund_callback" +Ali: + Code: "d55b58829efb41c8aa8e86769cba4844" \ No newline at end of file diff --git a/app/user/cmd/api/internal/handler/auth/sendsmshandler.go b/app/user/cmd/api/internal/handler/auth/sendsmshandler.go new file mode 100644 index 0000000..02b65e3 --- /dev/null +++ b/app/user/cmd/api/internal/handler/auth/sendsmshandler.go @@ -0,0 +1,29 @@ +package auth + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/auth" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func SendSmsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.SendSmsReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := auth.NewSendSmsLogic(r.Context(), svcCtx) + err := l.SendSms(&req) + result.HttpResult(r, w, nil, err) + } +} diff --git a/app/user/cmd/api/internal/handler/pay/alipaycallbackhandler.go b/app/user/cmd/api/internal/handler/pay/alipaycallbackhandler.go new file mode 100644 index 0000000..6ddda20 --- /dev/null +++ b/app/user/cmd/api/internal/handler/pay/alipaycallbackhandler.go @@ -0,0 +1,17 @@ +package pay + +import ( + "net/http" + + "qnc-server/app/user/cmd/api/internal/logic/pay" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/common/result" +) + +func AlipayCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := pay.NewAlipayCallbackLogic(r.Context(), svcCtx) + err := l.AlipayCallback(w, r) + result.HttpResult(r, w, nil, err) + } +} diff --git a/app/user/cmd/api/internal/handler/pay/wechatpaycallbackhandler.go b/app/user/cmd/api/internal/handler/pay/wechatpaycallbackhandler.go new file mode 100644 index 0000000..68397d0 --- /dev/null +++ b/app/user/cmd/api/internal/handler/pay/wechatpaycallbackhandler.go @@ -0,0 +1,17 @@ +package pay + +import ( + "net/http" + + "qnc-server/app/user/cmd/api/internal/logic/pay" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/common/result" +) + +func WechatPayCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := pay.NewWechatPayCallbackLogic(r.Context(), svcCtx) + err := l.WechatPayCallback(w, r) + result.HttpResult(r, w, nil, err) + } +} diff --git a/app/user/cmd/api/internal/handler/pay/wechatpayrefundcallbackhandler.go b/app/user/cmd/api/internal/handler/pay/wechatpayrefundcallbackhandler.go new file mode 100644 index 0000000..b9bfa0a --- /dev/null +++ b/app/user/cmd/api/internal/handler/pay/wechatpayrefundcallbackhandler.go @@ -0,0 +1,17 @@ +package pay + +import ( + "net/http" + + "qnc-server/app/user/cmd/api/internal/logic/pay" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/common/result" +) + +func WechatPayRefundCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := pay.NewWechatPayRefundCallbackLogic(r.Context(), svcCtx) + err := l.WechatPayRefundCallback(w, r) + result.HttpResult(r, w, nil, err) + } +} diff --git a/app/user/cmd/api/internal/handler/product/getproductbyenhandler.go b/app/user/cmd/api/internal/handler/product/getproductbyenhandler.go new file mode 100644 index 0000000..c972025 --- /dev/null +++ b/app/user/cmd/api/internal/handler/product/getproductbyenhandler.go @@ -0,0 +1,29 @@ +package product + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/product" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func GetProductByEnHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.GetProductByEnRequest + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := product.NewGetProductByEnLogic(r.Context(), svcCtx) + resp, err := l.GetProductByEn(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/product/getproductbyidhandler.go b/app/user/cmd/api/internal/handler/product/getproductbyidhandler.go new file mode 100644 index 0000000..f772005 --- /dev/null +++ b/app/user/cmd/api/internal/handler/product/getproductbyidhandler.go @@ -0,0 +1,29 @@ +package product + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/product" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func GetProductByIDHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.GetProductByIDRequest + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := product.NewGetProductByIDLogic(r.Context(), svcCtx) + resp, err := l.GetProductByID(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/backgroundcheckhandler.go b/app/user/cmd/api/internal/handler/query/backgroundcheckhandler.go new file mode 100644 index 0000000..8c1c9bd --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/backgroundcheckhandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func BackgroundCheckHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewBackgroundCheckLogic(r.Context(), svcCtx) + resp, err := l.BackgroundCheck(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/companyinfohandler.go b/app/user/cmd/api/internal/handler/query/companyinfohandler.go new file mode 100644 index 0000000..8665ab7 --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/companyinfohandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func CompanyInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewCompanyInfoLogic(r.Context(), svcCtx) + resp, err := l.CompanyInfo(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/homeservicehandler.go b/app/user/cmd/api/internal/handler/query/homeservicehandler.go new file mode 100644 index 0000000..37c58bb --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/homeservicehandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func HomeServiceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewHomeServiceLogic(r.Context(), svcCtx) + resp, err := l.HomeService(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/marriagehandler.go b/app/user/cmd/api/internal/handler/query/marriagehandler.go new file mode 100644 index 0000000..c6077ed --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/marriagehandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func MarriageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewMarriageLogic(r.Context(), svcCtx) + resp, err := l.Marriage(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/preloanbackgroundcheckhandler.go b/app/user/cmd/api/internal/handler/query/preloanbackgroundcheckhandler.go new file mode 100644 index 0000000..e73556e --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/preloanbackgroundcheckhandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func PreLoanBackgroundCheckHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewPreLoanBackgroundCheckLogic(r.Context(), svcCtx) + resp, err := l.PreLoanBackgroundCheck(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/querydetailbyorderidhandler.go b/app/user/cmd/api/internal/handler/query/querydetailbyorderidhandler.go new file mode 100644 index 0000000..7f221c7 --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/querydetailbyorderidhandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func QueryDetailByOrderIdHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryDetailByOrderIdReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewQueryDetailByOrderIdLogic(r.Context(), svcCtx) + resp, err := l.QueryDetailByOrderId(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/querydetailhandler.go b/app/user/cmd/api/internal/handler/query/querydetailhandler.go new file mode 100644 index 0000000..718c9cb --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/querydetailhandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func QueryDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryDetailReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewQueryDetailLogic(r.Context(), svcCtx) + resp, err := l.QueryDetail(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/queryexamplehandler.go b/app/user/cmd/api/internal/handler/query/queryexamplehandler.go new file mode 100644 index 0000000..2285e79 --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/queryexamplehandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func QueryExampleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryExampleReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewQueryExampleLogic(r.Context(), svcCtx) + resp, err := l.QueryExample(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/querylisthandler.go b/app/user/cmd/api/internal/handler/query/querylisthandler.go new file mode 100644 index 0000000..e35089c --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/querylisthandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func QueryListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryListReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewQueryListLogic(r.Context(), svcCtx) + resp, err := l.QueryList(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/queryretryhandler.go b/app/user/cmd/api/internal/handler/query/queryretryhandler.go new file mode 100644 index 0000000..57972a5 --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/queryretryhandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func QueryRetryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryRetryReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewQueryRetryLogic(r.Context(), svcCtx) + resp, err := l.QueryRetry(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/rentalinfohandler.go b/app/user/cmd/api/internal/handler/query/rentalinfohandler.go new file mode 100644 index 0000000..a14ec19 --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/rentalinfohandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func RentalInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewRentalInfoLogic(r.Context(), svcCtx) + resp, err := l.RentalInfo(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/riskassessmenthandler.go b/app/user/cmd/api/internal/handler/query/riskassessmenthandler.go new file mode 100644 index 0000000..df87e33 --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/riskassessmenthandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/query" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func RiskAssessmentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := query.NewRiskAssessmentLogic(r.Context(), svcCtx) + resp, err := l.RiskAssessment(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/user/detailhandler.go b/app/user/cmd/api/internal/handler/user/detailhandler.go new file mode 100644 index 0000000..109adc1 --- /dev/null +++ b/app/user/cmd/api/internal/handler/user/detailhandler.go @@ -0,0 +1,17 @@ +package user + +import ( + "net/http" + + "qnc-server/app/user/cmd/api/internal/logic/user" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/common/result" +) + +func DetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := user.NewDetailLogic(r.Context(), svcCtx) + resp, err := l.Detail() + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/user/mobilecodeloginhandler.go b/app/user/cmd/api/internal/handler/user/mobilecodeloginhandler.go new file mode 100644 index 0000000..e38c606 --- /dev/null +++ b/app/user/cmd/api/internal/handler/user/mobilecodeloginhandler.go @@ -0,0 +1,29 @@ +package user + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/user" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func MobileCodeLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.MobileCodeLoginReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := user.NewMobileCodeLoginLogic(r.Context(), svcCtx) + resp, err := l.MobileCodeLogin(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/user/mobileloginhandler.go b/app/user/cmd/api/internal/handler/user/mobileloginhandler.go new file mode 100644 index 0000000..2559263 --- /dev/null +++ b/app/user/cmd/api/internal/handler/user/mobileloginhandler.go @@ -0,0 +1,29 @@ +package user + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/user" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func MobileLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.MobileLoginReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := user.NewMobileLoginLogic(r.Context(), svcCtx) + resp, err := l.MobileLogin(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/user/registerhandler.go b/app/user/cmd/api/internal/handler/user/registerhandler.go new file mode 100644 index 0000000..12db94e --- /dev/null +++ b/app/user/cmd/api/internal/handler/user/registerhandler.go @@ -0,0 +1,29 @@ +package user + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/user" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func RegisterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.RegisterReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := user.NewRegisterLogic(r.Context(), svcCtx) + resp, err := l.Register(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/user/wxminiauthhandler.go b/app/user/cmd/api/internal/handler/user/wxminiauthhandler.go new file mode 100644 index 0000000..d53d5fe --- /dev/null +++ b/app/user/cmd/api/internal/handler/user/wxminiauthhandler.go @@ -0,0 +1,29 @@ +package user + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "qnc-server/app/user/cmd/api/internal/logic/user" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/result" + "qnc-server/pkg/lzkit/validator" +) + +func WxMiniAuthHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.WXMiniAuthReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := user.NewWxMiniAuthLogic(r.Context(), svcCtx) + resp, err := l.WxMiniAuth(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/logic/pay/alipaycallbacklogic.go b/app/user/cmd/api/internal/logic/pay/alipaycallbacklogic.go new file mode 100644 index 0000000..9e001e1 --- /dev/null +++ b/app/user/cmd/api/internal/logic/pay/alipaycallbacklogic.go @@ -0,0 +1,74 @@ +package pay + +import ( + "context" + "github.com/smartwalle/alipay/v3" + "net/http" + "qnc-server/pkg/lzkit/lzUtils" + "time" + + "github.com/zeromicro/go-zero/core/logx" + "qnc-server/app/user/cmd/api/internal/svc" +) + +type AlipayCallbackLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewAlipayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AlipayCallbackLogic { + return &AlipayCallbackLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *AlipayCallbackLogic) AlipayCallback(w http.ResponseWriter, r *http.Request) error { + notification, err := l.svcCtx.AlipayService.HandleAliPaymentNotification(r) + if err != nil { + logx.Errorf("支付宝支付回调,%+v", err) + return nil + } + order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, notification.OutTradeNo) + if findOrderErr != nil { + logx.Errorf("支付宝支付回调,查找订单失败: %+v", findOrderErr) + return nil + } + if order.Status != "pending" { + alipay.ACKNotification(w) + return nil + } + amount := lzUtils.ToAlipayAmount(order.Amount) + // 确保订单金额和状态正确,防止重复更新 + if amount != notification.TotalAmount { + logx.Errorf("支付宝支付回调,金额不一致") + return nil + } + if order.Status != "pending" { + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte("success")) // 确保只写入一次响应 + return nil + } + switch notification.TradeStatus { + case alipay.TradeStatusSuccess: + order.Status = "paid" + order.PayTime = lzUtils.TimeToNullTime(time.Now()) + default: + return nil + } + order.PlatformOrderId = lzUtils.StringToNullString(notification.OutTradeNo) + if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil { + logx.Errorf("支付宝支付回调,修改订单信息失败: %+v", updateErr) + return nil + } + if order.Status == "paid" { + if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil { + logx.Errorf("异步任务调度失败: %v", asyncErr) + return asyncErr + } + } + alipay.ACKNotification(w) + return nil +} diff --git a/app/user/cmd/api/internal/logic/pay/wechatpaycallbacklogic.go b/app/user/cmd/api/internal/logic/pay/wechatpaycallbacklogic.go new file mode 100644 index 0000000..46f775b --- /dev/null +++ b/app/user/cmd/api/internal/logic/pay/wechatpaycallbacklogic.go @@ -0,0 +1,78 @@ +package pay + +import ( + "context" + "net/http" + "qnc-server/app/user/cmd/api/internal/service" + "qnc-server/pkg/lzkit/lzUtils" + "time" + + "github.com/zeromicro/go-zero/core/logx" + "qnc-server/app/user/cmd/api/internal/svc" +) + +type WechatPayCallbackLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewWechatPayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatPayCallbackLogic { + return &WechatPayCallbackLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *WechatPayCallbackLogic) WechatPayCallback(w http.ResponseWriter, r *http.Request) error { + notification, err := l.svcCtx.WechatPayService.HandleWechatPayNotification(l.ctx, r) + if err != nil { + logx.Errorf("微信支付回调,%+v", err) + return nil + } + order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo) + if findOrderErr != nil { + logx.Errorf("微信支付回调,查找订单信息失败: %+v", findOrderErr) + return nil + } + + amount := lzUtils.ToWechatAmount(order.Amount) + if &amount != notification.Amount.Total { + logx.Errorf("微信支付回调,金额不一致") + return nil + } + if order.Status != "pending" { + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte("success")) // 确保只写入一次响应 + return nil + } + switch *notification.TradeState { + case service.TradeStateSuccess: + order.Status = "paid" + order.PayTime = lzUtils.TimeToNullTime(time.Now()) + case service.TradeStateClosed: + order.Status = "closed" + order.CloseTime = lzUtils.TimeToNullTime(time.Now()) + case service.TradeStateRevoked: + order.Status = "failed" + default: + return nil + } + order.PlatformOrderId = lzUtils.StringToNullString(*notification.TransactionId) + if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil { + logx.Errorf("微信支付回调,更新订单失败%+v", updateErr) + return nil + } + if order.Status == "paid" { + if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil { + logx.Errorf("异步任务调度失败: %v", asyncErr) + return asyncErr + } + } + + // 响应微信回调成功 + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte("success")) // 确保只写入一次响应 + return nil +} diff --git a/app/user/cmd/api/internal/logic/pay/wechatpayrefundcallbacklogic.go b/app/user/cmd/api/internal/logic/pay/wechatpayrefundcallbacklogic.go new file mode 100644 index 0000000..54cf99a --- /dev/null +++ b/app/user/cmd/api/internal/logic/pay/wechatpayrefundcallbacklogic.go @@ -0,0 +1,54 @@ +package pay + +import ( + "context" + "github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic" + "github.com/zeromicro/go-zero/core/logx" + "net/http" + "qnc-server/app/user/cmd/api/internal/svc" +) + +type WechatPayRefundCallbackLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewWechatPayRefundCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatPayRefundCallbackLogic { + return &WechatPayRefundCallbackLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *WechatPayRefundCallbackLogic) WechatPayRefundCallback(w http.ResponseWriter, r *http.Request) error { + notification, err := l.svcCtx.WechatPayService.HandleRefundNotification(l.ctx, r) + if err != nil { + logx.Errorf("微信退款回调,%+v", err) + return nil + } + order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo) + if findOrderErr != nil { + logx.Errorf("微信退款回调,查找订单信息失败: %+v", findOrderErr) + return nil + } + + switch *notification.Status { + case refunddomestic.STATUS_SUCCESS: + order.Status = "refunded" + case refunddomestic.STATUS_ABNORMAL: + // 异常 + return nil + default: + return nil + } + if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil { + logx.Errorf("微信退款回调,更新订单失败%+v", updateErr) + return nil + } + // 响应微信回调成功 + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte("success")) // 确保只写入一次响应 + return nil +} diff --git a/app/user/cmd/api/internal/logic/product/getproductbyenlogic.go b/app/user/cmd/api/internal/logic/product/getproductbyenlogic.go new file mode 100644 index 0000000..85576a4 --- /dev/null +++ b/app/user/cmd/api/internal/logic/product/getproductbyenlogic.go @@ -0,0 +1,74 @@ +package product + +import ( + "context" + "github.com/Masterminds/squirrel" + "github.com/jinzhu/copier" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/mr" + "qnc-server/app/user/model" + "qnc-server/common/xerr" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetProductByEnLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetProductByEnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductByEnLogic { + return &GetProductByEnLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetProductByEnLogic) GetProductByEn(req *types.GetProductByEnRequest) (resp *types.ProductResponse, err error) { + productModel, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, req.ProductEn) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "产品查询, 查找产品错误: %+v", err) + } + + build := l.svcCtx.ProductFeatureModel.SelectBuilder().Where(squirrel.Eq{ + "product_id": productModel.Id, + }) + productFeatureAll, err := l.svcCtx.ProductFeatureModel.FindAll(l.ctx, build, "") + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "产品查询, 查找产品关联错误: %+v", err) + } + var product types.Product + err = copier.Copy(&product, productModel) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 用户信息结构体复制失败, %+v", err) + } + mr.MapReduceVoid(func(source chan<- interface{}) { + for _, productFeature := range productFeatureAll { + source <- productFeature.FeatureId + } + }, func(item interface{}, writer mr.Writer[*model.Feature], cancel func(error)) { + id := item.(int64) + + feature, findFeatureErr := l.svcCtx.FeatureModel.FindOne(l.ctx, id) + if findFeatureErr != nil { + logx.WithContext(l.ctx).Errorf("产品查询, 查找关联feature错误: %d, err:%v", id, findFeatureErr) + return + } + if feature != nil && feature.Id > 0 { + writer.Write(feature) + } + }, func(pipe <-chan *model.Feature, cancel func(error)) { + for item := range pipe { + var feature types.Feature + _ = copier.Copy(&feature, item) + product.Features = append(product.Features, feature) + } + }) + + return &types.ProductResponse{Product: product}, nil +} diff --git a/app/user/cmd/api/internal/logic/product/getproductbyidlogic.go b/app/user/cmd/api/internal/logic/product/getproductbyidlogic.go new file mode 100644 index 0000000..17382d1 --- /dev/null +++ b/app/user/cmd/api/internal/logic/product/getproductbyidlogic.go @@ -0,0 +1,30 @@ +package product + +import ( + "context" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetProductByIDLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetProductByIDLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductByIDLogic { + return &GetProductByIDLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetProductByIDLogic) GetProductByID(req *types.GetProductByIDRequest) (resp *types.ProductResponse, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/app/user/cmd/api/internal/logic/query/backgroundchecklogic.go b/app/user/cmd/api/internal/logic/query/backgroundchecklogic.go new file mode 100644 index 0000000..50d116b --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/backgroundchecklogic.go @@ -0,0 +1,153 @@ +package query + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "qnc-server/app/user/cmd/api/internal/service" + "qnc-server/app/user/model" + "qnc-server/common/ctxdata" + "qnc-server/common/xerr" + "qnc-server/pkg/lzkit/crypto" + "qnc-server/pkg/lzkit/validator" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type BackgroundCheckLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewBackgroundCheckLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackgroundCheckLogic { + return &BackgroundCheckLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *BackgroundCheckLogic) BackgroundCheck(req *types.QueryReq) (resp *types.QueryResp, err error) { + userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx) + if getUidErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 获取用户信息失败, %+v", getUidErr) + } + // 1、AES解密 + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 密钥获取失败: %+v", decodeErr) + } + decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key) + if aesDecryptErr != nil || len(decryptData) == 0 { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 解密失败: %+v", decodeErr) + } + + // 2、校验 + var data types.BackgroundCheckReq + if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 解密后的数据格式不正确: %+v", unmarshalErr) + } + + if validatorErr := validator.Validate(data); validatorErr != nil { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "人事背调, 参数不正确: %+v", validatorErr) + } + + // 校验验证码 + codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile) + cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey) + if err != nil { + if errors.Is(err, redis.Nil) { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "人事背调, 验证码过期: %s", data.Mobile) + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "人事背调, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err) + } + if cacheCode != data.Code { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "人事背调, 验证码不正确: %s", data.Mobile) + } + + // 3、二要素三要素核验 + twoVerification := service.TwoFactorVerificationRequest{ + Name: data.Name, + IDCard: data.IDCard, + } + verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 二要素验证失败: %+v", err) + } + if !verification.Passed { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "人事背调, 二要素验证不通过: %+v", err) + } + product, findProductErr := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, "backgroundcheck") + if findProductErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 查找婚姻产品错误: %+v", findProductErr) + } + jsonData, marshalErr := json.Marshal(data) + if marshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 序列化参数失败: %+v", marshalErr) + } + + outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo() + redisKey := fmt.Sprintf("%s:%d:%s", "backgroundcheck", userID, outTradeNo) + cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), 1800) + if cacheErr != nil { + return nil, cacheErr + } + + var prepayID string + var createOrderErr error + if data.PayMethod == "wechatpay" { + prepayID, createOrderErr = l.svcCtx.WechatPayService.CreateWechatAppOrder(l.ctx, product.SellPrice, product.Description, outTradeNo) + } else { + prepayID, createOrderErr = l.svcCtx.AlipayService.CreateAlipayAppOrder(product.SellPrice, product.Description, outTradeNo) + } + if createOrderErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 创建支付订单失败: %+v", createOrderErr) + } + var orderID int64 + transErr := l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { + order := model.Order{ + OrderNo: outTradeNo, + UserId: userID, + ProductId: product.Id, + PaymentPlatform: data.PayMethod, + PaymentScene: "app", + Amount: product.SellPrice, + Status: "pending", + } + orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(ctx, session, &order) + if insertOrderErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 保存订单失败: %+v", insertOrderErr) + } + insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId() + if lastInsertIdErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 获取保存订单ID失败: %+v", lastInsertIdErr) + } + orderID = insertedOrderID + query := model.Query{ + OrderId: orderID, + UserId: userID, + ProductId: product.Id, + QueryParams: req.Data, + QueryState: "pending", + } + _, insertQueryErr := l.svcCtx.QueryModel.Insert(l.ctx, session, &query) + if insertQueryErr != nil { + return insertQueryErr + } + return nil + }) + if transErr != nil { + return nil, transErr + } + + return &types.QueryResp{PrepayID: prepayID, OrderID: orderID}, nil +} diff --git a/app/user/cmd/api/internal/logic/query/companyinfologic.go b/app/user/cmd/api/internal/logic/query/companyinfologic.go new file mode 100644 index 0000000..ec7a859 --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/companyinfologic.go @@ -0,0 +1,153 @@ +package query + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "qnc-server/app/user/cmd/api/internal/service" + "qnc-server/app/user/model" + "qnc-server/common/ctxdata" + "qnc-server/common/xerr" + "qnc-server/pkg/lzkit/crypto" + "qnc-server/pkg/lzkit/validator" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CompanyInfoLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCompanyInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CompanyInfoLogic { + return &CompanyInfoLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *CompanyInfoLogic) CompanyInfo(req *types.QueryReq) (resp *types.QueryResp, err error) { + userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx) + if getUidErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 获取用户信息失败, %+v", getUidErr) + } + // 1、AES解密 + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 密钥获取失败: %+v", decodeErr) + } + decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key) + if aesDecryptErr != nil || len(decryptData) == 0 { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 解密失败: %+v", decodeErr) + } + + // 2、校验 + var data types.CompanyInfoReq + if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 解密后的数据格式不正确: %+v", unmarshalErr) + } + + if validatorErr := validator.Validate(data); validatorErr != nil { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "企业报告, 参数不正确: %+v", validatorErr) + } + + // 校验验证码 + codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile) + cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey) + if err != nil { + if errors.Is(err, redis.Nil) { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "企业报告, 验证码过期: %s", data.Mobile) + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "企业报告, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err) + } + if cacheCode != data.Code { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "企业报告, 验证码不正确: %s", data.Mobile) + } + + // 3、二要素三要素核验 + twoVerification := service.TwoFactorVerificationRequest{ + Name: data.Name, + IDCard: data.IDCard, + } + verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 二要素验证失败: %+v", err) + } + if !verification.Passed { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "企业报告, 二要素验证不通过: %+v", err) + } + product, findProductErr := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, "companyinfo") + if findProductErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 查找婚姻产品错误: %+v", findProductErr) + } + jsonData, marshalErr := json.Marshal(data) + if marshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 序列化参数失败: %+v", marshalErr) + } + + outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo() + redisKey := fmt.Sprintf("%s:%d:%s", "companyinfo", userID, outTradeNo) + cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), 1800) + if cacheErr != nil { + return nil, cacheErr + } + + var prepayID string + var createOrderErr error + if data.PayMethod == "wechatpay" { + prepayID, createOrderErr = l.svcCtx.WechatPayService.CreateWechatAppOrder(l.ctx, product.SellPrice, product.Description, outTradeNo) + } else { + prepayID, createOrderErr = l.svcCtx.AlipayService.CreateAlipayAppOrder(product.SellPrice, product.Description, outTradeNo) + } + if createOrderErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 创建支付订单失败: %+v", createOrderErr) + } + var orderID int64 + transErr := l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { + order := model.Order{ + OrderNo: outTradeNo, + UserId: userID, + ProductId: product.Id, + PaymentPlatform: data.PayMethod, + PaymentScene: "app", + Amount: product.SellPrice, + Status: "pending", + } + orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(ctx, session, &order) + if insertOrderErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 保存订单失败: %+v", insertOrderErr) + } + insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId() + if lastInsertIdErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 获取保存订单ID失败: %+v", lastInsertIdErr) + } + orderID = insertedOrderID + query := model.Query{ + OrderId: orderID, + UserId: userID, + ProductId: product.Id, + QueryParams: req.Data, + QueryState: "pending", + } + _, insertQueryErr := l.svcCtx.QueryModel.Insert(l.ctx, session, &query) + if insertQueryErr != nil { + return insertQueryErr + } + return nil + }) + if transErr != nil { + return nil, transErr + } + + return &types.QueryResp{PrepayID: prepayID, OrderID: orderID}, nil +} diff --git a/app/user/cmd/api/internal/logic/query/homeservicelogic.go b/app/user/cmd/api/internal/logic/query/homeservicelogic.go new file mode 100644 index 0000000..c8a2f24 --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/homeservicelogic.go @@ -0,0 +1,153 @@ +package query + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "qnc-server/app/user/cmd/api/internal/service" + "qnc-server/app/user/model" + "qnc-server/common/ctxdata" + "qnc-server/common/xerr" + "qnc-server/pkg/lzkit/crypto" + "qnc-server/pkg/lzkit/validator" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type HomeServiceLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewHomeServiceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *HomeServiceLogic { + return &HomeServiceLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *HomeServiceLogic) HomeService(req *types.QueryReq) (resp *types.QueryResp, err error) { + userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx) + if getUidErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 获取用户信息失败, %+v", getUidErr) + } + // 1、AES解密 + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 密钥获取失败: %+v", decodeErr) + } + decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key) + if aesDecryptErr != nil || len(decryptData) == 0 { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 解密失败: %+v", decodeErr) + } + + // 2、校验 + var data types.HomeServiceReq + if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 解密后的数据格式不正确: %+v", unmarshalErr) + } + + if validatorErr := validator.Validate(data); validatorErr != nil { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "家政服务, 参数不正确: %+v", validatorErr) + } + + // 校验验证码 + codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile) + cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey) + if err != nil { + if errors.Is(err, redis.Nil) { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "家政服务, 验证码过期: %s", data.Mobile) + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "家政服务, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err) + } + if cacheCode != data.Code { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "家政服务, 验证码不正确: %s", data.Mobile) + } + + // 3、二要素三要素核验 + twoVerification := service.TwoFactorVerificationRequest{ + Name: data.Name, + IDCard: data.IDCard, + } + verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 二要素验证失败: %+v", err) + } + if !verification.Passed { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "家政服务, 二要素验证不通过: %+v", err) + } + product, findProductErr := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, "homeservice") + if findProductErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 查找婚姻产品错误: %+v", findProductErr) + } + jsonData, marshalErr := json.Marshal(data) + if marshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 序列化参数失败: %+v", marshalErr) + } + + outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo() + redisKey := fmt.Sprintf("%s:%d:%s", "homeservice", userID, outTradeNo) + cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), 1800) + if cacheErr != nil { + return nil, cacheErr + } + + var prepayID string + var createOrderErr error + if data.PayMethod == "wechatpay" { + prepayID, createOrderErr = l.svcCtx.WechatPayService.CreateWechatAppOrder(l.ctx, product.SellPrice, product.Description, outTradeNo) + } else { + prepayID, createOrderErr = l.svcCtx.AlipayService.CreateAlipayAppOrder(product.SellPrice, product.Description, outTradeNo) + } + if createOrderErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 创建支付订单失败: %+v", createOrderErr) + } + var orderID int64 + transErr := l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { + order := model.Order{ + OrderNo: outTradeNo, + UserId: userID, + ProductId: product.Id, + PaymentPlatform: data.PayMethod, + PaymentScene: "app", + Amount: product.SellPrice, + Status: "pending", + } + orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(ctx, session, &order) + if insertOrderErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 保存订单失败: %+v", insertOrderErr) + } + insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId() + if lastInsertIdErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 获取保存订单ID失败: %+v", lastInsertIdErr) + } + orderID = insertedOrderID + query := model.Query{ + OrderId: orderID, + UserId: userID, + ProductId: product.Id, + QueryParams: req.Data, + QueryState: "pending", + } + _, insertQueryErr := l.svcCtx.QueryModel.Insert(l.ctx, session, &query) + if insertQueryErr != nil { + return insertQueryErr + } + return nil + }) + if transErr != nil { + return nil, transErr + } + + return &types.QueryResp{PrepayID: prepayID, OrderID: orderID}, nil +} diff --git a/app/user/cmd/api/internal/logic/query/marriagelogic.go b/app/user/cmd/api/internal/logic/query/marriagelogic.go new file mode 100644 index 0000000..3ba3786 --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/marriagelogic.go @@ -0,0 +1,153 @@ +package query + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "qnc-server/app/user/cmd/api/internal/service" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/app/user/model" + "qnc-server/common/ctxdata" + "qnc-server/common/xerr" + "qnc-server/pkg/lzkit/crypto" + "qnc-server/pkg/lzkit/validator" +) + +type MarriageLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewMarriageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MarriageLogic { + return &MarriageLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +const MERRIAGE = "marriage" + +func (l *MarriageLogic) Marriage(req *types.QueryReq) (resp *types.QueryResp, err error) { + userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx) + if getUidErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 获取用户信息失败, %+v", getUidErr) + } + // 1、AES解密 + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 密钥获取失败: %+v", decodeErr) + } + decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key) + if aesDecryptErr != nil || len(decryptData) == 0 { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 解密失败: %+v", decodeErr) + } + + // 2、校验 + var data types.MarriageReq + if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 解密后的数据格式不正确: %+v", unmarshalErr) + } + + if validatorErr := validator.Validate(data); validatorErr != nil { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "婚恋评估, 参数不正确: %+v", validatorErr) + } + + // 校验验证码 + codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile) + cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey) + if err != nil { + if errors.Is(err, redis.Nil) { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "婚恋评估, 验证码过期: %s", data.Mobile) + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "婚恋评估, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err) + } + if cacheCode != data.Code { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "婚恋评估, 验证码不正确: %s", data.Mobile) + } + + // 3、二要素三要素核验 + twoVerification := service.TwoFactorVerificationRequest{ + Name: data.Name, + IDCard: data.IDCard, + } + verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 二要素验证失败: %+v", err) + } + if !verification.Passed { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "婚恋评估, 二要素验证不通过: %+v", err) + } + product, findProductErr := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, MERRIAGE) + if findProductErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 查找婚姻产品错误: %+v", findProductErr) + } + jsonData, marshalErr := json.Marshal(data) + if marshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 序列化参数失败: %+v", marshalErr) + } + + outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo() + redisKey := fmt.Sprintf("%s:%d:%s", MERRIAGE, userID, outTradeNo) + cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), 1800) + if cacheErr != nil { + return nil, cacheErr + } + + var prepayID string + var createOrderErr error + if data.PayMethod == "wechatpay" { + prepayID, createOrderErr = l.svcCtx.WechatPayService.CreateWechatAppOrder(l.ctx, product.SellPrice, product.Description, outTradeNo) + } else { + prepayID, createOrderErr = l.svcCtx.AlipayService.CreateAlipayAppOrder(product.SellPrice, product.Description, outTradeNo) + } + if createOrderErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 创建支付订单失败: %+v", createOrderErr) + } + var orderID int64 + transErr := l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { + order := model.Order{ + OrderNo: outTradeNo, + UserId: userID, + ProductId: product.Id, + PaymentPlatform: data.PayMethod, + PaymentScene: "app", + Amount: product.SellPrice, + Status: "pending", + } + orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(ctx, session, &order) + if insertOrderErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 保存订单失败: %+v", insertOrderErr) + } + insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId() + if lastInsertIdErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 获取保存订单ID失败: %+v", lastInsertIdErr) + } + orderID = insertedOrderID + query := model.Query{ + OrderId: orderID, + UserId: userID, + ProductId: product.Id, + QueryParams: req.Data, + QueryState: "pending", + } + _, insertQueryErr := l.svcCtx.QueryModel.Insert(l.ctx, session, &query) + if insertQueryErr != nil { + return insertQueryErr + } + return nil + }) + if transErr != nil { + return nil, transErr + } + + return &types.QueryResp{PrepayID: prepayID, OrderID: orderID}, nil +} diff --git a/app/user/cmd/api/internal/logic/query/preloanbackgroundchecklogic.go b/app/user/cmd/api/internal/logic/query/preloanbackgroundchecklogic.go new file mode 100644 index 0000000..98a4c6a --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/preloanbackgroundchecklogic.go @@ -0,0 +1,153 @@ +package query + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "qnc-server/app/user/cmd/api/internal/service" + "qnc-server/app/user/model" + "qnc-server/common/ctxdata" + "qnc-server/common/xerr" + "qnc-server/pkg/lzkit/crypto" + "qnc-server/pkg/lzkit/validator" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type PreLoanBackgroundCheckLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewPreLoanBackgroundCheckLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PreLoanBackgroundCheckLogic { + return &PreLoanBackgroundCheckLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *PreLoanBackgroundCheckLogic) PreLoanBackgroundCheck(req *types.QueryReq) (resp *types.QueryResp, err error) { + userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx) + if getUidErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 获取用户信息失败, %+v", getUidErr) + } + // 1、AES解密 + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 密钥获取失败: %+v", decodeErr) + } + decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key) + if aesDecryptErr != nil || len(decryptData) == 0 { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 解密失败: %+v", decodeErr) + } + + // 2、校验 + var data types.PreLoanBackgroundCheckReq + if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 解密后的数据格式不正确: %+v", unmarshalErr) + } + + if validatorErr := validator.Validate(data); validatorErr != nil { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "贷前背调, 参数不正确: %+v", validatorErr) + } + + // 校验验证码 + codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile) + cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey) + if err != nil { + if errors.Is(err, redis.Nil) { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "贷前背调, 验证码过期: %s", data.Mobile) + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "贷前背调, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err) + } + if cacheCode != data.Code { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "贷前背调, 验证码不正确: %s", data.Mobile) + } + + // 3、二要素三要素核验 + twoVerification := service.TwoFactorVerificationRequest{ + Name: data.Name, + IDCard: data.IDCard, + } + verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 二要素验证失败: %+v", err) + } + if !verification.Passed { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "贷前背调, 二要素验证不通过: %+v", err) + } + product, findProductErr := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, "preloanbackgroundcheck") + if findProductErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 查找婚姻产品错误: %+v", findProductErr) + } + jsonData, marshalErr := json.Marshal(data) + if marshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 序列化参数失败: %+v", marshalErr) + } + + outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo() + redisKey := fmt.Sprintf("%s:%d:%s", "preloanbackgroundcheck", userID, outTradeNo) + cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), 1800) + if cacheErr != nil { + return nil, cacheErr + } + + var prepayID string + var createOrderErr error + if data.PayMethod == "wechatpay" { + prepayID, createOrderErr = l.svcCtx.WechatPayService.CreateWechatAppOrder(l.ctx, product.SellPrice, product.Description, outTradeNo) + } else { + prepayID, createOrderErr = l.svcCtx.AlipayService.CreateAlipayAppOrder(product.SellPrice, product.Description, outTradeNo) + } + if createOrderErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 创建支付订单失败: %+v", createOrderErr) + } + var orderID int64 + transErr := l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { + order := model.Order{ + OrderNo: outTradeNo, + UserId: userID, + ProductId: product.Id, + PaymentPlatform: data.PayMethod, + PaymentScene: "app", + Amount: product.SellPrice, + Status: "pending", + } + orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(ctx, session, &order) + if insertOrderErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 保存订单失败: %+v", insertOrderErr) + } + insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId() + if lastInsertIdErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 获取保存订单ID失败: %+v", lastInsertIdErr) + } + orderID = insertedOrderID + query := model.Query{ + OrderId: orderID, + UserId: userID, + ProductId: product.Id, + QueryParams: req.Data, + QueryState: "pending", + } + _, insertQueryErr := l.svcCtx.QueryModel.Insert(l.ctx, session, &query) + if insertQueryErr != nil { + return insertQueryErr + } + return nil + }) + if transErr != nil { + return nil, transErr + } + + return &types.QueryResp{PrepayID: prepayID, OrderID: orderID}, nil +} diff --git a/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go b/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go new file mode 100644 index 0000000..4ca1018 --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go @@ -0,0 +1,153 @@ +package query + +import ( + "context" + "database/sql" + "encoding/hex" + "encoding/json" + "github.com/jinzhu/copier" + "github.com/pkg/errors" + "qnc-server/common/xerr" + "qnc-server/pkg/lzkit/crypto" + "qnc-server/pkg/lzkit/delay" + "qnc-server/pkg/lzkit/lzUtils" + "time" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type QueryDetailByOrderIdLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewQueryDetailByOrderIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryDetailByOrderIdLogic { + return &QueryDetailByOrderIdLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailByOrderIdReq) (resp *types.QueryDetailByOrderIdResp, err error) { + // 获取订单信息 + order, err := l.svcCtx.OrderModel.FindOne(l.ctx, req.OrderId) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err) + } + + // 创建渐进式延迟策略实例 + progressiveDelayOrder, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %+v", err) + } + + // 等待订单状态变为 "paid" + startTime := time.Now() + for order.Status == "pending" { + if time.Since(startTime) > 10*time.Second { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_WAIT, ""), "") + } + + // 使用渐进式延迟,获取下次延迟时间 + nextDelay, _ := progressiveDelayOrder.NextDelay() + + // 等待一段时间后再查一次订单状态 + time.Sleep(nextDelay) + + // 再次查找订单 + order, err = l.svcCtx.OrderModel.FindOne(l.ctx, req.OrderId) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找订单错误: %+v", err) + } + } + if order.Status != "paid" { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_WAIT, ""), "") + } + // 获取报告信息 + queryModel, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, req.OrderId) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err) + } + + // 创建渐进式延迟实例 + progressiveDelayQuery, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %+v", err) + } + + // 等待 queryModel.QueryState 不再是 "pending" + startTime = time.Now() + for queryModel.QueryState == "pending" { + if time.Since(startTime) > 10*time.Second { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询超时,查询状态长时间为 'pending'") + } + + // 使用渐进式延迟,获取下次延迟时间 + nextDelay, _ := progressiveDelayQuery.NextDelay() + + // 每隔一段时间检查一次查询状态 + time.Sleep(nextDelay) + + // 再次查询 report 状态 + queryModel, err = l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, req.OrderId) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err) + } + } + + // 根据 QueryState 做后续处理 + if queryModel.QueryState == "failed" { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_ERROR, ""), "") + } + + var query types.Query + query.CreateTime = queryModel.CreateTime.Format("2006-01-02 15:04:05") + query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05") + + // 解密查询数据 + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取AES解密解药失败, %+v", err) + } + + processErr := ProcessQueryData(queryModel.QueryData, &query.QueryData, key) + if processErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结果处理失败: %v", processErr) + } + // 复制报告数据 + err = copier.Copy(&query, queryModel) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %+v", err) + } + + return &types.QueryDetailByOrderIdResp{ + Query: query, + }, nil +} + +// ProcessQueryData 解密和反序列化 QueryData +func ProcessQueryData(queryData sql.NullString, target *[]map[string]interface{}, key []byte) error { + queryDataStr := lzUtils.NullStringToString(queryData) + if queryDataStr == "" { + return nil + } + // 解密 queryData + decryptedData, decryptErr := crypto.AesDecrypt(queryDataStr, key) + if decryptErr != nil { + return decryptErr + } + + // 反序列化解密后的数据 + unmarshalErr := json.Unmarshal(decryptedData, target) + if unmarshalErr != nil { + return unmarshalErr + } + + return nil +} diff --git a/app/user/cmd/api/internal/logic/query/querydetaillogic.go b/app/user/cmd/api/internal/logic/query/querydetaillogic.go new file mode 100644 index 0000000..a82166d --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/querydetaillogic.go @@ -0,0 +1,64 @@ +package query + +import ( + "context" + "encoding/hex" + "encoding/json" + "github.com/jinzhu/copier" + "github.com/pkg/errors" + "qnc-server/common/xerr" + "qnc-server/pkg/lzkit/crypto" + "qnc-server/pkg/lzkit/lzUtils" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type QueryDetailLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewQueryDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryDetailLogic { + return &QueryDetailLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *QueryDetailLogic) QueryDetail(req *types.QueryDetailReq) (resp *types.QueryDetailResp, err error) { + queryModel, err := l.svcCtx.QueryModel.FindOne(l.ctx, req.Id) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err) + } + + var query types.Query + query.CreateTime = queryModel.CreateTime.Format("2006-01-02 15:04:05") + query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05") + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取AES解密解药失败, %+v", err) + } + if lzUtils.NullStringToString(queryModel.QueryData) != "" { + queryData, decryptErr := crypto.AesDecrypt(lzUtils.NullStringToString(queryModel.QueryData), key) + if decryptErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结果解密失败, %+v", decryptErr) + } + unmarshalErr := json.Unmarshal(queryData, &query.QueryData) + if unmarshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体处理失败, %+v", unmarshalErr) + } + } + err = copier.Copy(&query, queryModel) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %+v", err) + } + return &types.QueryDetailResp{ + Query: query, + }, nil +} diff --git a/app/user/cmd/api/internal/logic/query/queryexamplelogic.go b/app/user/cmd/api/internal/logic/query/queryexamplelogic.go new file mode 100644 index 0000000..83fd624 --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/queryexamplelogic.go @@ -0,0 +1,57 @@ +package query + +import ( + "context" + "encoding/hex" + "github.com/jinzhu/copier" + "github.com/pkg/errors" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/xerr" + + "github.com/zeromicro/go-zero/core/logx" +) + +type QueryExampleLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewQueryExampleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryExampleLogic { + return &QueryExampleLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *QueryExampleLogic) QueryExample(req *types.QueryExampleReq) (resp *types.QueryExampleResp, err error) { + var exampleID int64 = 8 + queryModel, err := l.svcCtx.QueryModel.FindOne(l.ctx, exampleID) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "示例报告, 获取示例报告失败: %v", err) + } + var query types.Query + query.CreateTime = queryModel.CreateTime.Format("2006-01-02 15:04:05") + query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05") + + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取AES解密解药失败, %+v", err) + } + + processErr := ProcessQueryData(queryModel.QueryData, &query.QueryData, key) + if processErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 报告结果处理失败: %v", processErr) + } + + copyErr := copier.Copy(&query, queryModel) + if copyErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 示例报告结构体复制失败, %+v", err) + } + return &types.QueryExampleResp{ + Query: query, + }, nil +} diff --git a/app/user/cmd/api/internal/logic/query/querylistlogic.go b/app/user/cmd/api/internal/logic/query/querylistlogic.go new file mode 100644 index 0000000..1588a0a --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/querylistlogic.go @@ -0,0 +1,61 @@ +package query + +import ( + "context" + "github.com/Masterminds/squirrel" + "github.com/jinzhu/copier" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/logx" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/common/ctxdata" + "qnc-server/common/xerr" +) + +type QueryListLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewQueryListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryListLogic { + return &QueryListLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *QueryListLogic) QueryList(req *types.QueryListReq) (resp *types.QueryListResp, err error) { + userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx) + if getUidErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告列表查询, 获取用户信息失败, %+v", getUidErr) + + } + build := l.svcCtx.QueryModel.SelectBuilder().Where(squirrel.Eq{ + "user_id": userID, + }) + queryList, total, err := l.svcCtx.QueryModel.FindPageListByPageWithTotal(l.ctx, build, req.Page, req.PageSize, "create_time DESC") + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告列表查询, 查找报告列表错误, %+v", err) + } + + var list []types.Query + if len(queryList) > 0 { + for _, queryModel := range queryList { + var query types.Query + query.CreateTime = queryModel.CreateTime.Format("2006-01-02 15:04:05") + query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05") + copyErr := copier.Copy(&query, queryModel) + if copyErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告列表查询, 报告结构体复制失败, %+v", err) + } + list = append(list, query) + } + } + + return &types.QueryListResp{ + Total: total, + List: list, + }, nil +} diff --git a/app/user/cmd/api/internal/logic/query/queryretrylogic.go b/app/user/cmd/api/internal/logic/query/queryretrylogic.go new file mode 100644 index 0000000..6fd1b57 --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/queryretrylogic.go @@ -0,0 +1,43 @@ +package query + +import ( + "context" + "github.com/pkg/errors" + "qnc-server/common/xerr" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type QueryRetryLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewQueryRetryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryRetryLogic { + return &QueryRetryLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *QueryRetryLogic) QueryRetry(req *types.QueryRetryReq) (resp *types.QueryRetryResp, err error) { + + query, err := l.svcCtx.QueryModel.FindOne(l.ctx, req.Id) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询重试, 查找报告失败, %+v", err) + } + if query.QueryState == "success" { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIN_FAILED, "该报告不能重试"), "报告查询重试, 该报告不能重试, %d", query.Id) + } + + if asyncErr := l.svcCtx.AsynqService.SendQueryTask(query.OrderId); asyncErr != nil { + logx.Errorf("异步任务调度失败: %v", asyncErr) + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询重试, 异步任务调度失败, %+v", asyncErr) + } + return +} diff --git a/app/user/cmd/api/internal/logic/query/rentalinfologic.go b/app/user/cmd/api/internal/logic/query/rentalinfologic.go new file mode 100644 index 0000000..f920838 --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/rentalinfologic.go @@ -0,0 +1,153 @@ +package query + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "qnc-server/app/user/cmd/api/internal/service" + "qnc-server/app/user/model" + "qnc-server/common/ctxdata" + "qnc-server/common/xerr" + "qnc-server/pkg/lzkit/crypto" + "qnc-server/pkg/lzkit/validator" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type RentalInfoLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewRentalInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RentalInfoLogic { + return &RentalInfoLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *RentalInfoLogic) RentalInfo(req *types.QueryReq) (resp *types.QueryResp, err error) { + userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx) + if getUidErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 获取用户信息失败, %+v", getUidErr) + } + // 1、AES解密 + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 密钥获取失败: %+v", decodeErr) + } + decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key) + if aesDecryptErr != nil || len(decryptData) == 0 { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 解密失败: %+v", decodeErr) + } + + // 2、校验 + var data types.RentalInfoReq + if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 解密后的数据格式不正确: %+v", unmarshalErr) + } + + if validatorErr := validator.Validate(data); validatorErr != nil { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "租赁服务, 参数不正确: %+v", validatorErr) + } + + // 校验验证码 + codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile) + cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey) + if err != nil { + if errors.Is(err, redis.Nil) { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "租赁服务, 验证码过期: %s", data.Mobile) + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "租赁服务, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err) + } + if cacheCode != data.Code { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "租赁服务, 验证码不正确: %s", data.Mobile) + } + + // 3、二要素三要素核验 + twoVerification := service.TwoFactorVerificationRequest{ + Name: data.Name, + IDCard: data.IDCard, + } + verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 二要素验证失败: %+v", err) + } + if !verification.Passed { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "租赁服务, 二要素验证不通过: %+v", err) + } + product, findProductErr := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, "rentalinfo") + if findProductErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 查找婚姻产品错误: %+v", findProductErr) + } + jsonData, marshalErr := json.Marshal(data) + if marshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 序列化参数失败: %+v", marshalErr) + } + + outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo() + redisKey := fmt.Sprintf("%s:%d:%s", "rentalinfo", userID, outTradeNo) + cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), 1800) + if cacheErr != nil { + return nil, cacheErr + } + + var prepayID string + var createOrderErr error + if data.PayMethod == "wechatpay" { + prepayID, createOrderErr = l.svcCtx.WechatPayService.CreateWechatAppOrder(l.ctx, product.SellPrice, product.Description, outTradeNo) + } else { + prepayID, createOrderErr = l.svcCtx.AlipayService.CreateAlipayAppOrder(product.SellPrice, product.Description, outTradeNo) + } + if createOrderErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 创建支付订单失败: %+v", createOrderErr) + } + var orderID int64 + transErr := l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { + order := model.Order{ + OrderNo: outTradeNo, + UserId: userID, + ProductId: product.Id, + PaymentPlatform: data.PayMethod, + PaymentScene: "app", + Amount: product.SellPrice, + Status: "pending", + } + orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(ctx, session, &order) + if insertOrderErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 保存订单失败: %+v", insertOrderErr) + } + insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId() + if lastInsertIdErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 获取保存订单ID失败: %+v", lastInsertIdErr) + } + orderID = insertedOrderID + query := model.Query{ + OrderId: orderID, + UserId: userID, + ProductId: product.Id, + QueryParams: req.Data, + QueryState: "pending", + } + _, insertQueryErr := l.svcCtx.QueryModel.Insert(l.ctx, session, &query) + if insertQueryErr != nil { + return insertQueryErr + } + return nil + }) + if transErr != nil { + return nil, transErr + } + + return &types.QueryResp{PrepayID: prepayID, OrderID: orderID}, nil +} diff --git a/app/user/cmd/api/internal/logic/query/riskassessmentlogic.go b/app/user/cmd/api/internal/logic/query/riskassessmentlogic.go new file mode 100644 index 0000000..f8d74c8 --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/riskassessmentlogic.go @@ -0,0 +1,153 @@ +package query + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "qnc-server/app/user/cmd/api/internal/service" + "qnc-server/app/user/model" + "qnc-server/common/ctxdata" + "qnc-server/common/xerr" + "qnc-server/pkg/lzkit/crypto" + "qnc-server/pkg/lzkit/validator" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type RiskAssessmentLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewRiskAssessmentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RiskAssessmentLogic { + return &RiskAssessmentLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *RiskAssessmentLogic) RiskAssessment(req *types.QueryReq) (resp *types.QueryResp, err error) { + userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx) + if getUidErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 获取用户信息失败, %+v", getUidErr) + } + // 1、AES解密 + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 密钥获取失败: %+v", decodeErr) + } + decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key) + if aesDecryptErr != nil || len(decryptData) == 0 { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 解密失败: %+v", decodeErr) + } + + // 2、校验 + var data types.RiskAssessmentReq + if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 解密后的数据格式不正确: %+v", unmarshalErr) + } + + if validatorErr := validator.Validate(data); validatorErr != nil { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "个人风险, 参数不正确: %+v", validatorErr) + } + + // 校验验证码 + codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile) + cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey) + if err != nil { + if errors.Is(err, redis.Nil) { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "个人风险, 验证码过期: %s", data.Mobile) + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "个人风险, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err) + } + if cacheCode != data.Code { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "个人风险, 验证码不正确: %s", data.Mobile) + } + + // 3、二要素三要素核验 + twoVerification := service.TwoFactorVerificationRequest{ + Name: data.Name, + IDCard: data.IDCard, + } + verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 二要素验证失败: %+v", err) + } + if !verification.Passed { + return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "个人风险, 二要素验证不通过: %+v", err) + } + product, findProductErr := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, "riskassessment") + if findProductErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 查找婚姻产品错误: %+v", findProductErr) + } + jsonData, marshalErr := json.Marshal(data) + if marshalErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 序列化参数失败: %+v", marshalErr) + } + + outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo() + redisKey := fmt.Sprintf("%s:%d:%s", "riskassessment", userID, outTradeNo) + cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), 1800) + if cacheErr != nil { + return nil, cacheErr + } + + var prepayID string + var createOrderErr error + if data.PayMethod == "wechatpay" { + prepayID, createOrderErr = l.svcCtx.WechatPayService.CreateWechatAppOrder(l.ctx, product.SellPrice, product.Description, outTradeNo) + } else { + prepayID, createOrderErr = l.svcCtx.AlipayService.CreateAlipayAppOrder(product.SellPrice, product.Description, outTradeNo) + } + if createOrderErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 创建支付订单失败: %+v", createOrderErr) + } + var orderID int64 + transErr := l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { + order := model.Order{ + OrderNo: outTradeNo, + UserId: userID, + ProductId: product.Id, + PaymentPlatform: data.PayMethod, + PaymentScene: "app", + Amount: product.SellPrice, + Status: "pending", + } + orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(ctx, session, &order) + if insertOrderErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 保存订单失败: %+v", insertOrderErr) + } + insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId() + if lastInsertIdErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 获取保存订单ID失败: %+v", lastInsertIdErr) + } + orderID = insertedOrderID + query := model.Query{ + OrderId: orderID, + UserId: userID, + ProductId: product.Id, + QueryParams: req.Data, + QueryState: "pending", + } + _, insertQueryErr := l.svcCtx.QueryModel.Insert(l.ctx, session, &query) + if insertQueryErr != nil { + return insertQueryErr + } + return nil + }) + if transErr != nil { + return nil, transErr + } + + return &types.QueryResp{PrepayID: prepayID, OrderID: orderID}, nil +} diff --git a/app/user/cmd/api/internal/logic/user/mobilecodeloginlogic.go b/app/user/cmd/api/internal/logic/user/mobilecodeloginlogic.go new file mode 100644 index 0000000..09f3528 --- /dev/null +++ b/app/user/cmd/api/internal/logic/user/mobilecodeloginlogic.go @@ -0,0 +1,87 @@ +package user + +import ( + "context" + "fmt" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + "qnc-server/app/user/model" + jwtx "qnc-server/common/jwt" + "qnc-server/common/xerr" + + "github.com/zeromicro/go-zero/core/logx" +) + +type MobileCodeLoginLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewMobileCodeLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MobileCodeLoginLogic { + return &MobileCodeLoginLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *MobileCodeLoginLogic) MobileCodeLogin(req *types.MobileCodeLoginReq) (resp *types.MobileCodeLoginResp, err error) { + // 检查手机号是否在一分钟内已发送过验证码 + redisKey := fmt.Sprintf("%s:%s", "login", req.Mobile) + cacheCode, err := l.svcCtx.Redis.Get(redisKey) + if err != nil { + if errors.Is(err, redis.Nil) { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "手机登录, 验证码过期: %s", req.Mobile) + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取验证码redis缓存失败, mobile: %s, err: %+v", req.Mobile, err) + } + if cacheCode != req.Code { + return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确: %s", req.Mobile) + } + user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, req.Mobile) + if findUserErr != nil && findUserErr != model.ErrNotFound { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile: %s, err: %+v", req.Mobile, err) + } + if user == nil { + if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { + user.Mobile = req.Mobile + if len(user.Nickname) == 0 { + user.Nickname = req.Mobile + } + insertResult, userInsertErr := l.svcCtx.UserModel.Insert(ctx, session, user) + if userInsertErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入新用户失败, mobile%s, err: %+v", req.Mobile, err) + } + lastId, lastInsertIdErr := insertResult.LastInsertId() + if lastInsertIdErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 获取新用户ID失败, err:%+v, user:%+v", lastInsertIdErr, user) + } + user.Id = lastId + + userAuth := new(model.UserAuth) + userAuth.UserId = lastId + userAuth.AuthKey = req.Mobile + userAuth.AuthType = model.UserAuthTypeAppMobile + if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, userAuth); userAuthInsertErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入用户认证失败, err:%+v", userAuthInsertErr) + } + return nil + }); transErr != nil { + return nil, transErr + } + } + token, generaErr := jwtx.GenerateJwtToken(user.Id, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) + if generaErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 生成token失败 : %d", user.Id) + } + + return &types.MobileCodeLoginResp{ + AccessToken: token, + AccessExpire: l.svcCtx.Config.JwtAuth.AccessExpire, + RefreshAfter: l.svcCtx.Config.JwtAuth.RefreshAfter, + }, nil +} diff --git a/app/user/cmd/api/internal/logic/user/mobileloginlogic.go b/app/user/cmd/api/internal/logic/user/mobileloginlogic.go new file mode 100644 index 0000000..6db4815 --- /dev/null +++ b/app/user/cmd/api/internal/logic/user/mobileloginlogic.go @@ -0,0 +1,54 @@ +package user + +import ( + "context" + "github.com/pkg/errors" + "qnc-server/app/user/model" + jwtx "qnc-server/common/jwt" + "qnc-server/common/tool" + "qnc-server/common/xerr" + "qnc-server/pkg/lzkit/lzUtils" + + "qnc-server/app/user/cmd/api/internal/svc" + "qnc-server/app/user/cmd/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type MobileLoginLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewMobileLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MobileLoginLogic { + return &MobileLoginLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *MobileLoginLogic) MobileLogin(req *types.MobileLoginReq) (resp *types.MobileCodeLoginResp, err error) { + user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, req.Mobile) + if findUserErr != nil && findUserErr != model.ErrNotFound { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile%s, err: %+v", req.Mobile, err) + } + if user == nil { + return nil, errors.Wrapf(xerr.NewErrMsg("手机号码未注册"), "手机登录, 手机号未注册:%s", req.Mobile) + } + if !(tool.Md5ByString(req.Password) == lzUtils.NullStringToString(user.Password)) { + return nil, errors.Wrapf(xerr.NewErrMsg("密码不正确"), "手机登录, 密码匹配不正确%s", req.Mobile) + } + + token, generaErr := jwtx.GenerateJwtToken(user.Id, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) + if generaErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 生成token失败 : %d", user.Id) + } + + return &types.MobileCodeLoginResp{ + AccessToken: token, + AccessExpire: l.svcCtx.Config.JwtAuth.AccessExpire, + RefreshAfter: l.svcCtx.Config.JwtAuth.RefreshAfter, + }, nil +} diff --git a/app/user/cmd/api/main.go b/app/user/cmd/api/main.go new file mode 100644 index 0000000..ba3eee0 --- /dev/null +++ b/app/user/cmd/api/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "context" + "flag" + "fmt" + "github.com/zeromicro/go-zero/core/logx" + "os" + "qnc-server/app/user/cmd/api/internal/config" + "qnc-server/app/user/cmd/api/internal/handler" + "qnc-server/app/user/cmd/api/internal/queue" + "qnc-server/app/user/cmd/api/internal/svc" + + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/rest" +) + +var configFile = flag.String("f", "etc/main.yaml", "the config file") + +func main() { + flag.Parse() + + var c config.Config + conf.MustLoad(*configFile, &c) + + svcContext := svc.NewServiceContext(c) + defer svcContext.Close() + + // 启动 asynq 消费者 + go func() { + ctx := context.Background() + // 初始化 cron job 或异步任务队列 + asynq := queue.NewCronJob(ctx, svcContext) + mux := asynq.Register() + + // 启动 asynq 消费者 + if err := svcContext.AsynqServer.Run(mux); err != nil { + logx.WithContext(ctx).Errorf("异步任务启动失败: %+v", err) + os.Exit(1) + } + }() + + server := rest.MustNewServer(c.RestConf) + defer server.Stop() + + handler.RegisterHandlers(server, svcContext) + + fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) + server.Start() +} diff --git a/app/user/model/featureModel.go b/app/user/model/featureModel.go new file mode 100644 index 0000000..b27565e --- /dev/null +++ b/app/user/model/featureModel.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ FeatureModel = (*customFeatureModel)(nil) + +type ( + // FeatureModel is an interface to be customized, add more methods here, + // and implement the added methods in customFeatureModel. + FeatureModel interface { + featureModel + } + + customFeatureModel struct { + *defaultFeatureModel + } +) + +// NewFeatureModel returns a model for the database table. +func NewFeatureModel(conn sqlx.SqlConn, c cache.CacheConf) FeatureModel { + return &customFeatureModel{ + defaultFeatureModel: newFeatureModel(conn, c), + } +} diff --git a/app/user/model/featureModel_gen.go b/app/user/model/featureModel_gen.go new file mode 100644 index 0000000..4879a0e --- /dev/null +++ b/app/user/model/featureModel_gen.go @@ -0,0 +1,408 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "database/sql" + "fmt" + "qnc-server/deploy/script/model" + "strings" + + "time" + + "github.com/Masterminds/squirrel" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" + "qnc-server/common/globalkey" +) + +var ( + featureFieldNames = builder.RawFieldNames(&Feature{}) + featureRows = strings.Join(featureFieldNames, ",") + featureRowsExpectAutoSet = strings.Join(stringx.Remove(featureFieldNames, "`id`", "`create_time`", "`update_time`"), ",") + featureRowsWithPlaceHolder = strings.Join(stringx.Remove(featureFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + + cacheQncFeatureIdPrefix = "cache:qnc:feature:id:" + cacheQncFeatureApiIdPrefix = "cache:qnc:feature:apiId:" +) + +type ( + featureModel interface { + Insert(ctx context.Context, session sqlx.Session, data *Feature) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*Feature, error) + FindOneByApiId(ctx context.Context, apiId string) (*Feature, error) + Update(ctx context.Context, session sqlx.Session, data *Feature) (sql.Result, error) + UpdateWithVersion(ctx context.Context, session sqlx.Session, data *Feature) error + Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error + SelectBuilder() squirrel.SelectBuilder + DeleteSoft(ctx context.Context, session sqlx.Session, data *Feature) error + FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error) + FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error) + FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*Feature, error) + FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Feature, error) + FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Feature, int64, error) + FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*Feature, error) + FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*Feature, error) + Delete(ctx context.Context, session sqlx.Session, id int64) error + } + + defaultFeatureModel struct { + sqlc.CachedConn + table string + } + + Feature struct { + Id int64 `db:"id"` // 主键ID + CreateTime time.Time `db:"create_time"` // 创建时间 + UpdateTime time.Time `db:"update_time"` // 更新时间 + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + DelState int64 `db:"del_state"` // 删除状态 + Version int64 `db:"version"` // 版本号 + ApiId string `db:"api_id"` // API标识 + Name string `db:"name"` // 描述 + } +) + +func newFeatureModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultFeatureModel { + return &defaultFeatureModel{ + CachedConn: sqlc.NewConn(conn, c), + table: "`feature`", + } +} + +func (m *defaultFeatureModel) Insert(ctx context.Context, session sqlx.Session, data *Feature) (sql.Result, error) { + data.DelState = globalkey.DelStateNo + qncFeatureApiIdKey := fmt.Sprintf("%s%v", cacheQncFeatureApiIdPrefix, data.ApiId) + qncFeatureIdKey := fmt.Sprintf("%s%v", cacheQncFeatureIdPrefix, data.Id) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?)", m.table, featureRowsExpectAutoSet) + if session != nil { + return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ApiId, data.Name) + } + return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ApiId, data.Name) + }, qncFeatureApiIdKey, qncFeatureIdKey) +} + +func (m *defaultFeatureModel) FindOne(ctx context.Context, id int64) (*Feature, error) { + qncFeatureIdKey := fmt.Sprintf("%s%v", cacheQncFeatureIdPrefix, id) + var resp Feature + err := m.QueryRowCtx(ctx, &resp, qncFeatureIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", featureRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultFeatureModel) FindOneByApiId(ctx context.Context, apiId string) (*Feature, error) { + qncFeatureApiIdKey := fmt.Sprintf("%s%v", cacheQncFeatureApiIdPrefix, apiId) + var resp Feature + err := m.QueryRowIndexCtx(ctx, &resp, qncFeatureApiIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `api_id` = ? AND del_state = ? limit 1", featureRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, apiId, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultFeatureModel) Update(ctx context.Context, session sqlx.Session, newData *Feature) (sql.Result, error) { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return nil, err + } + qncFeatureApiIdKey := fmt.Sprintf("%s%v", cacheQncFeatureApiIdPrefix, data.ApiId) + qncFeatureIdKey := fmt.Sprintf("%s%v", cacheQncFeatureIdPrefix, data.Id) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, featureRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.Name, newData.Id) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.Name, newData.Id) + }, qncFeatureApiIdKey, qncFeatureIdKey) +} + +func (m *defaultFeatureModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *Feature) error { + + oldVersion := newData.Version + newData.Version += 1 + + var sqlResult sql.Result + var err error + + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + qncFeatureApiIdKey := fmt.Sprintf("%s%v", cacheQncFeatureApiIdPrefix, data.ApiId) + qncFeatureIdKey := fmt.Sprintf("%s%v", cacheQncFeatureIdPrefix, data.Id) + sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ? AND version = ? ", m.table, featureRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.Name, newData.Id, oldVersion) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.Name, newData.Id, oldVersion) + }, qncFeatureApiIdKey, qncFeatureIdKey) + if err != nil { + return err + } + updateCount, err := sqlResult.RowsAffected() + if err != nil { + return err + } + if updateCount == 0 { + return model.ErrNoRowsUpdate + } + + return nil +} + +func (m *defaultFeatureModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *Feature) error { + data.DelState = globalkey.DelStateYes + data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true} + if err := m.UpdateWithVersion(ctx, session, data); err != nil { + return errors.Wrapf(errors.New("delete soft failed "), "FeatureModel delete err : %+v", err) + } + return nil +} + +func (m *defaultFeatureModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field") + } + + builder = builder.Columns("IFNULL(SUM(" + field + "),0)") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp float64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultFeatureModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field") + } + + builder = builder.Columns("COUNT(" + field + ")") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp int64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultFeatureModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*Feature, error) { + + builder = builder.Columns(featureRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return nil, err + } + + var resp []*Feature + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultFeatureModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Feature, error) { + + builder = builder.Columns(featureRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Feature + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultFeatureModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Feature, int64, error) { + + total, err := m.FindCount(ctx, builder, "id") + if err != nil { + return nil, 0, err + } + + builder = builder.Columns(featureRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, total, err + } + + var resp []*Feature + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, total, nil + default: + return nil, total, err + } +} + +func (m *defaultFeatureModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*Feature, error) { + + builder = builder.Columns(featureRows) + + if preMinId > 0 { + builder = builder.Where(" id < ? ", preMinId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Feature + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultFeatureModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*Feature, error) { + + builder = builder.Columns(featureRows) + + if preMaxId > 0 { + builder = builder.Where(" id > ? ", preMaxId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Feature + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultFeatureModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error { + + return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { + return fn(ctx, session) + }) + +} + +func (m *defaultFeatureModel) SelectBuilder() squirrel.SelectBuilder { + return squirrel.Select().From(m.table) +} +func (m *defaultFeatureModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + qncFeatureApiIdKey := fmt.Sprintf("%s%v", cacheQncFeatureApiIdPrefix, data.ApiId) + qncFeatureIdKey := fmt.Sprintf("%s%v", cacheQncFeatureIdPrefix, id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("DELETE FROM %s WHERE `id` = ?", m.table) + if session != nil { + return session.ExecCtx(ctx, query, id) + } + return conn.ExecCtx(ctx, query, id) + }, qncFeatureApiIdKey, qncFeatureIdKey) + return err +} +func (m *defaultFeatureModel) formatPrimary(primary interface{}) string { + return fmt.Sprintf("%s%v", cacheQncFeatureIdPrefix, primary) +} +func (m *defaultFeatureModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", featureRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo) +} + +func (m *defaultFeatureModel) tableName() string { + return m.table +} diff --git a/app/user/model/orderModel.go b/app/user/model/orderModel.go new file mode 100644 index 0000000..6bf505c --- /dev/null +++ b/app/user/model/orderModel.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ OrderModel = (*customOrderModel)(nil) + +type ( + // OrderModel is an interface to be customized, add more methods here, + // and implement the added methods in customOrderModel. + OrderModel interface { + orderModel + } + + customOrderModel struct { + *defaultOrderModel + } +) + +// NewOrderModel returns a model for the database table. +func NewOrderModel(conn sqlx.SqlConn, c cache.CacheConf) OrderModel { + return &customOrderModel{ + defaultOrderModel: newOrderModel(conn, c), + } +} diff --git a/app/user/model/orderModel_gen.go b/app/user/model/orderModel_gen.go new file mode 100644 index 0000000..6586cd2 --- /dev/null +++ b/app/user/model/orderModel_gen.go @@ -0,0 +1,417 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "database/sql" + "fmt" + "qnc-server/deploy/script/model" + "strings" + + "time" + + "github.com/Masterminds/squirrel" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" + "qnc-server/common/globalkey" +) + +var ( + orderFieldNames = builder.RawFieldNames(&Order{}) + orderRows = strings.Join(orderFieldNames, ",") + orderRowsExpectAutoSet = strings.Join(stringx.Remove(orderFieldNames, "`id`", "`create_time`", "`update_time`"), ",") + orderRowsWithPlaceHolder = strings.Join(stringx.Remove(orderFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + + cacheQncOrderIdPrefix = "cache:qnc:order:id:" + cacheQncOrderOrderNoPrefix = "cache:qnc:order:orderNo:" +) + +type ( + orderModel interface { + Insert(ctx context.Context, session sqlx.Session, data *Order) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*Order, error) + FindOneByOrderNo(ctx context.Context, orderNo string) (*Order, error) + Update(ctx context.Context, session sqlx.Session, data *Order) (sql.Result, error) + UpdateWithVersion(ctx context.Context, session sqlx.Session, data *Order) error + Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error + SelectBuilder() squirrel.SelectBuilder + DeleteSoft(ctx context.Context, session sqlx.Session, data *Order) error + FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error) + FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error) + FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*Order, error) + FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Order, error) + FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Order, int64, error) + FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*Order, error) + FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*Order, error) + Delete(ctx context.Context, session sqlx.Session, id int64) error + } + + defaultOrderModel struct { + sqlc.CachedConn + table string + } + + Order struct { + Id int64 `db:"id"` // 主键ID + OrderNo string `db:"order_no"` // 自生成的订单号 + UserId int64 `db:"user_id"` // 用户ID + ProductId int64 `db:"product_id"` // 产品ID(软关联到产品表) + PaymentPlatform string `db:"payment_platform"` // 支付平台(支付宝、微信、其他) + PaymentScene string `db:"payment_scene"` // 支付场景(App、H5、微信小程序、公众号) + PlatformOrderId sql.NullString `db:"platform_order_id"` // 支付平台订单号 + Amount float64 `db:"amount"` // 支付金额 + Status string `db:"status"` // 支付状态 + DelState int64 `db:"del_state"` // 删除状态 + Version int64 `db:"version"` // 版本号 + CreateTime time.Time `db:"create_time"` // 创建时间 + UpdateTime time.Time `db:"update_time"` // 更新时间 + PayTime sql.NullTime `db:"pay_time"` // 支付时间 + RefundTime sql.NullTime `db:"refund_time"` // 退款时间 + CloseTime sql.NullTime `db:"close_time"` // 订单关闭时间 + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + } +) + +func newOrderModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultOrderModel { + return &defaultOrderModel{ + CachedConn: sqlc.NewConn(conn, c), + table: "`order`", + } +} + +func (m *defaultOrderModel) Insert(ctx context.Context, session sqlx.Session, data *Order) (sql.Result, error) { + data.DelState = globalkey.DelStateNo + qncOrderIdKey := fmt.Sprintf("%s%v", cacheQncOrderIdPrefix, data.Id) + qncOrderOrderNoKey := fmt.Sprintf("%s%v", cacheQncOrderOrderNoPrefix, data.OrderNo) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, orderRowsExpectAutoSet) + if session != nil { + return session.ExecCtx(ctx, query, data.OrderNo, data.UserId, data.ProductId, data.PaymentPlatform, data.PaymentScene, data.PlatformOrderId, data.Amount, data.Status, data.DelState, data.Version, data.PayTime, data.RefundTime, data.CloseTime, data.DeleteTime) + } + return conn.ExecCtx(ctx, query, data.OrderNo, data.UserId, data.ProductId, data.PaymentPlatform, data.PaymentScene, data.PlatformOrderId, data.Amount, data.Status, data.DelState, data.Version, data.PayTime, data.RefundTime, data.CloseTime, data.DeleteTime) + }, qncOrderIdKey, qncOrderOrderNoKey) +} + +func (m *defaultOrderModel) FindOne(ctx context.Context, id int64) (*Order, error) { + qncOrderIdKey := fmt.Sprintf("%s%v", cacheQncOrderIdPrefix, id) + var resp Order + err := m.QueryRowCtx(ctx, &resp, qncOrderIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", orderRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultOrderModel) FindOneByOrderNo(ctx context.Context, orderNo string) (*Order, error) { + qncOrderOrderNoKey := fmt.Sprintf("%s%v", cacheQncOrderOrderNoPrefix, orderNo) + var resp Order + err := m.QueryRowIndexCtx(ctx, &resp, qncOrderOrderNoKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `order_no` = ? AND del_state = ? limit 1", orderRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, orderNo, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultOrderModel) Update(ctx context.Context, session sqlx.Session, newData *Order) (sql.Result, error) { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return nil, err + } + qncOrderIdKey := fmt.Sprintf("%s%v", cacheQncOrderIdPrefix, data.Id) + qncOrderOrderNoKey := fmt.Sprintf("%s%v", cacheQncOrderOrderNoPrefix, data.OrderNo) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, orderRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id) + } + return conn.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id) + }, qncOrderIdKey, qncOrderOrderNoKey) +} + +func (m *defaultOrderModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *Order) error { + + oldVersion := newData.Version + newData.Version += 1 + + var sqlResult sql.Result + var err error + + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + qncOrderIdKey := fmt.Sprintf("%s%v", cacheQncOrderIdPrefix, data.Id) + qncOrderOrderNoKey := fmt.Sprintf("%s%v", cacheQncOrderOrderNoPrefix, data.OrderNo) + sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ? AND version = ? ", m.table, orderRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id, oldVersion) + } + return conn.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id, oldVersion) + }, qncOrderIdKey, qncOrderOrderNoKey) + if err != nil { + return err + } + updateCount, err := sqlResult.RowsAffected() + if err != nil { + return err + } + if updateCount == 0 { + return model.ErrNoRowsUpdate + } + + return nil +} + +func (m *defaultOrderModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *Order) error { + data.DelState = globalkey.DelStateYes + data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true} + if err := m.UpdateWithVersion(ctx, session, data); err != nil { + return errors.Wrapf(errors.New("delete soft failed "), "OrderModel delete err : %+v", err) + } + return nil +} + +func (m *defaultOrderModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field") + } + + builder = builder.Columns("IFNULL(SUM(" + field + "),0)") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp float64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultOrderModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field") + } + + builder = builder.Columns("COUNT(" + field + ")") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp int64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultOrderModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*Order, error) { + + builder = builder.Columns(orderRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return nil, err + } + + var resp []*Order + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultOrderModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Order, error) { + + builder = builder.Columns(orderRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Order + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultOrderModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Order, int64, error) { + + total, err := m.FindCount(ctx, builder, "id") + if err != nil { + return nil, 0, err + } + + builder = builder.Columns(orderRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, total, err + } + + var resp []*Order + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, total, nil + default: + return nil, total, err + } +} + +func (m *defaultOrderModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*Order, error) { + + builder = builder.Columns(orderRows) + + if preMinId > 0 { + builder = builder.Where(" id < ? ", preMinId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Order + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultOrderModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*Order, error) { + + builder = builder.Columns(orderRows) + + if preMaxId > 0 { + builder = builder.Where(" id > ? ", preMaxId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Order + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultOrderModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error { + + return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { + return fn(ctx, session) + }) + +} + +func (m *defaultOrderModel) SelectBuilder() squirrel.SelectBuilder { + return squirrel.Select().From(m.table) +} +func (m *defaultOrderModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + qncOrderIdKey := fmt.Sprintf("%s%v", cacheQncOrderIdPrefix, id) + qncOrderOrderNoKey := fmt.Sprintf("%s%v", cacheQncOrderOrderNoPrefix, data.OrderNo) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("DELETE FROM %s WHERE `id` = ?", m.table) + if session != nil { + return session.ExecCtx(ctx, query, id) + } + return conn.ExecCtx(ctx, query, id) + }, qncOrderIdKey, qncOrderOrderNoKey) + return err +} +func (m *defaultOrderModel) formatPrimary(primary interface{}) string { + return fmt.Sprintf("%s%v", cacheQncOrderIdPrefix, primary) +} +func (m *defaultOrderModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", orderRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo) +} + +func (m *defaultOrderModel) tableName() string { + return m.table +} diff --git a/app/user/model/productFeatureModel.go b/app/user/model/productFeatureModel.go new file mode 100644 index 0000000..5b77422 --- /dev/null +++ b/app/user/model/productFeatureModel.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ ProductFeatureModel = (*customProductFeatureModel)(nil) + +type ( + // ProductFeatureModel is an interface to be customized, add more methods here, + // and implement the added methods in customProductFeatureModel. + ProductFeatureModel interface { + productFeatureModel + } + + customProductFeatureModel struct { + *defaultProductFeatureModel + } +) + +// NewProductFeatureModel returns a model for the database table. +func NewProductFeatureModel(conn sqlx.SqlConn, c cache.CacheConf) ProductFeatureModel { + return &customProductFeatureModel{ + defaultProductFeatureModel: newProductFeatureModel(conn, c), + } +} diff --git a/app/user/model/productFeatureModel_gen.go b/app/user/model/productFeatureModel_gen.go new file mode 100644 index 0000000..5066b15 --- /dev/null +++ b/app/user/model/productFeatureModel_gen.go @@ -0,0 +1,408 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "database/sql" + "fmt" + "qnc-server/deploy/script/model" + "strings" + + "time" + + "github.com/Masterminds/squirrel" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" + "qnc-server/common/globalkey" +) + +var ( + productFeatureFieldNames = builder.RawFieldNames(&ProductFeature{}) + productFeatureRows = strings.Join(productFeatureFieldNames, ",") + productFeatureRowsExpectAutoSet = strings.Join(stringx.Remove(productFeatureFieldNames, "`id`", "`create_time`", "`update_time`"), ",") + productFeatureRowsWithPlaceHolder = strings.Join(stringx.Remove(productFeatureFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + + cacheQncProductFeatureIdPrefix = "cache:qnc:productFeature:id:" + cacheQncProductFeatureProductIdFeatureIdPrefix = "cache:qnc:productFeature:productId:featureId:" +) + +type ( + productFeatureModel interface { + Insert(ctx context.Context, session sqlx.Session, data *ProductFeature) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*ProductFeature, error) + FindOneByProductIdFeatureId(ctx context.Context, productId int64, featureId int64) (*ProductFeature, error) + Update(ctx context.Context, session sqlx.Session, data *ProductFeature) (sql.Result, error) + UpdateWithVersion(ctx context.Context, session sqlx.Session, data *ProductFeature) error + Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error + SelectBuilder() squirrel.SelectBuilder + DeleteSoft(ctx context.Context, session sqlx.Session, data *ProductFeature) error + FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error) + FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error) + FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*ProductFeature, error) + FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*ProductFeature, error) + FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*ProductFeature, int64, error) + FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*ProductFeature, error) + FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*ProductFeature, error) + Delete(ctx context.Context, session sqlx.Session, id int64) error + } + + defaultProductFeatureModel struct { + sqlc.CachedConn + table string + } + + ProductFeature struct { + Id int64 `db:"id"` // 主键ID + ProductId int64 `db:"product_id"` // 产品ID + FeatureId int64 `db:"feature_id"` // 功能ID + CreateTime time.Time `db:"create_time"` // 创建时间 + UpdateTime time.Time `db:"update_time"` // 更新时间 + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + DelState int64 `db:"del_state"` // 删除状态 + Version int64 `db:"version"` // 版本号 + } +) + +func newProductFeatureModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultProductFeatureModel { + return &defaultProductFeatureModel{ + CachedConn: sqlc.NewConn(conn, c), + table: "`product_feature`", + } +} + +func (m *defaultProductFeatureModel) Insert(ctx context.Context, session sqlx.Session, data *ProductFeature) (sql.Result, error) { + data.DelState = globalkey.DelStateNo + qncProductFeatureIdKey := fmt.Sprintf("%s%v", cacheQncProductFeatureIdPrefix, data.Id) + qncProductFeatureProductIdFeatureIdKey := fmt.Sprintf("%s%v:%v", cacheQncProductFeatureProductIdFeatureIdPrefix, data.ProductId, data.FeatureId) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?)", m.table, productFeatureRowsExpectAutoSet) + if session != nil { + return session.ExecCtx(ctx, query, data.ProductId, data.FeatureId, data.DeleteTime, data.DelState, data.Version) + } + return conn.ExecCtx(ctx, query, data.ProductId, data.FeatureId, data.DeleteTime, data.DelState, data.Version) + }, qncProductFeatureIdKey, qncProductFeatureProductIdFeatureIdKey) +} + +func (m *defaultProductFeatureModel) FindOne(ctx context.Context, id int64) (*ProductFeature, error) { + qncProductFeatureIdKey := fmt.Sprintf("%s%v", cacheQncProductFeatureIdPrefix, id) + var resp ProductFeature + err := m.QueryRowCtx(ctx, &resp, qncProductFeatureIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", productFeatureRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultProductFeatureModel) FindOneByProductIdFeatureId(ctx context.Context, productId int64, featureId int64) (*ProductFeature, error) { + qncProductFeatureProductIdFeatureIdKey := fmt.Sprintf("%s%v:%v", cacheQncProductFeatureProductIdFeatureIdPrefix, productId, featureId) + var resp ProductFeature + err := m.QueryRowIndexCtx(ctx, &resp, qncProductFeatureProductIdFeatureIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `product_id` = ? AND `feature_id` = ? AND del_state = ? limit 1", productFeatureRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, productId, featureId, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultProductFeatureModel) Update(ctx context.Context, session sqlx.Session, newData *ProductFeature) (sql.Result, error) { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return nil, err + } + qncProductFeatureIdKey := fmt.Sprintf("%s%v", cacheQncProductFeatureIdPrefix, data.Id) + qncProductFeatureProductIdFeatureIdKey := fmt.Sprintf("%s%v:%v", cacheQncProductFeatureProductIdFeatureIdPrefix, data.ProductId, data.FeatureId) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, productFeatureRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.ProductId, newData.FeatureId, newData.DeleteTime, newData.DelState, newData.Version, newData.Id) + } + return conn.ExecCtx(ctx, query, newData.ProductId, newData.FeatureId, newData.DeleteTime, newData.DelState, newData.Version, newData.Id) + }, qncProductFeatureIdKey, qncProductFeatureProductIdFeatureIdKey) +} + +func (m *defaultProductFeatureModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *ProductFeature) error { + + oldVersion := newData.Version + newData.Version += 1 + + var sqlResult sql.Result + var err error + + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + qncProductFeatureIdKey := fmt.Sprintf("%s%v", cacheQncProductFeatureIdPrefix, data.Id) + qncProductFeatureProductIdFeatureIdKey := fmt.Sprintf("%s%v:%v", cacheQncProductFeatureProductIdFeatureIdPrefix, data.ProductId, data.FeatureId) + sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ? AND version = ? ", m.table, productFeatureRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.ProductId, newData.FeatureId, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion) + } + return conn.ExecCtx(ctx, query, newData.ProductId, newData.FeatureId, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion) + }, qncProductFeatureIdKey, qncProductFeatureProductIdFeatureIdKey) + if err != nil { + return err + } + updateCount, err := sqlResult.RowsAffected() + if err != nil { + return err + } + if updateCount == 0 { + return model.ErrNoRowsUpdate + } + + return nil +} + +func (m *defaultProductFeatureModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *ProductFeature) error { + data.DelState = globalkey.DelStateYes + data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true} + if err := m.UpdateWithVersion(ctx, session, data); err != nil { + return errors.Wrapf(errors.New("delete soft failed "), "ProductFeatureModel delete err : %+v", err) + } + return nil +} + +func (m *defaultProductFeatureModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field") + } + + builder = builder.Columns("IFNULL(SUM(" + field + "),0)") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp float64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultProductFeatureModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field") + } + + builder = builder.Columns("COUNT(" + field + ")") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp int64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultProductFeatureModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*ProductFeature, error) { + + builder = builder.Columns(productFeatureRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return nil, err + } + + var resp []*ProductFeature + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultProductFeatureModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*ProductFeature, error) { + + builder = builder.Columns(productFeatureRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*ProductFeature + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultProductFeatureModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*ProductFeature, int64, error) { + + total, err := m.FindCount(ctx, builder, "id") + if err != nil { + return nil, 0, err + } + + builder = builder.Columns(productFeatureRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, total, err + } + + var resp []*ProductFeature + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, total, nil + default: + return nil, total, err + } +} + +func (m *defaultProductFeatureModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*ProductFeature, error) { + + builder = builder.Columns(productFeatureRows) + + if preMinId > 0 { + builder = builder.Where(" id < ? ", preMinId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*ProductFeature + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultProductFeatureModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*ProductFeature, error) { + + builder = builder.Columns(productFeatureRows) + + if preMaxId > 0 { + builder = builder.Where(" id > ? ", preMaxId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*ProductFeature + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultProductFeatureModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error { + + return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { + return fn(ctx, session) + }) + +} + +func (m *defaultProductFeatureModel) SelectBuilder() squirrel.SelectBuilder { + return squirrel.Select().From(m.table) +} +func (m *defaultProductFeatureModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + qncProductFeatureIdKey := fmt.Sprintf("%s%v", cacheQncProductFeatureIdPrefix, id) + qncProductFeatureProductIdFeatureIdKey := fmt.Sprintf("%s%v:%v", cacheQncProductFeatureProductIdFeatureIdPrefix, data.ProductId, data.FeatureId) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("DELETE FROM %s WHERE `id` = ?", m.table) + if session != nil { + return session.ExecCtx(ctx, query, id) + } + return conn.ExecCtx(ctx, query, id) + }, qncProductFeatureIdKey, qncProductFeatureProductIdFeatureIdKey) + return err +} +func (m *defaultProductFeatureModel) formatPrimary(primary interface{}) string { + return fmt.Sprintf("%s%v", cacheQncProductFeatureIdPrefix, primary) +} +func (m *defaultProductFeatureModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", productFeatureRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo) +} + +func (m *defaultProductFeatureModel) tableName() string { + return m.table +} diff --git a/app/user/model/productModel.go b/app/user/model/productModel.go new file mode 100644 index 0000000..df18c7a --- /dev/null +++ b/app/user/model/productModel.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ ProductModel = (*customProductModel)(nil) + +type ( + // ProductModel is an interface to be customized, add more methods here, + // and implement the added methods in customProductModel. + ProductModel interface { + productModel + } + + customProductModel struct { + *defaultProductModel + } +) + +// NewProductModel returns a model for the database table. +func NewProductModel(conn sqlx.SqlConn, c cache.CacheConf) ProductModel { + return &customProductModel{ + defaultProductModel: newProductModel(conn, c), + } +} diff --git a/app/user/model/productModel_gen.go b/app/user/model/productModel_gen.go new file mode 100644 index 0000000..45b41e0 --- /dev/null +++ b/app/user/model/productModel_gen.go @@ -0,0 +1,438 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "database/sql" + "fmt" + "qnc-server/deploy/script/model" + "strings" + + "time" + + "github.com/Masterminds/squirrel" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" + "qnc-server/common/globalkey" +) + +var ( + productFieldNames = builder.RawFieldNames(&Product{}) + productRows = strings.Join(productFieldNames, ",") + productRowsExpectAutoSet = strings.Join(stringx.Remove(productFieldNames, "`id`", "`create_time`", "`update_time`"), ",") + productRowsWithPlaceHolder = strings.Join(stringx.Remove(productFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + + cacheQncProductIdPrefix = "cache:qnc:product:id:" + cacheQncProductProductEnPrefix = "cache:qnc:product:productEn:" + cacheQncProductProductNamePrefix = "cache:qnc:product:productName:" +) + +type ( + productModel interface { + Insert(ctx context.Context, session sqlx.Session, data *Product) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*Product, error) + FindOneByProductEn(ctx context.Context, productEn string) (*Product, error) + FindOneByProductName(ctx context.Context, productName string) (*Product, error) + Update(ctx context.Context, session sqlx.Session, data *Product) (sql.Result, error) + UpdateWithVersion(ctx context.Context, session sqlx.Session, data *Product) error + Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error + SelectBuilder() squirrel.SelectBuilder + DeleteSoft(ctx context.Context, session sqlx.Session, data *Product) error + FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error) + FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error) + FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*Product, error) + FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Product, error) + FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Product, int64, error) + FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*Product, error) + FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*Product, error) + Delete(ctx context.Context, session sqlx.Session, id int64) error + } + + defaultProductModel struct { + sqlc.CachedConn + table string + } + + Product struct { + Id int64 `db:"id"` // 主键ID + CreateTime time.Time `db:"create_time"` // 创建时间 + UpdateTime time.Time `db:"update_time"` // 更新时间 + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + DelState int64 `db:"del_state"` // 删除状态 + Version int64 `db:"version"` // 版本号 + ProductName string `db:"product_name"` // 服务名 + ProductEn string `db:"product_en"` // 英文名 + Description string `db:"description"` // 描述 + Notes sql.NullString `db:"notes"` // 备注 + CostPrice float64 `db:"cost_price"` // 成本 + SellPrice float64 `db:"sell_price"` // 售价 + } +) + +func newProductModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultProductModel { + return &defaultProductModel{ + CachedConn: sqlc.NewConn(conn, c), + table: "`product`", + } +} + +func (m *defaultProductModel) Insert(ctx context.Context, session sqlx.Session, data *Product) (sql.Result, error) { + data.DelState = globalkey.DelStateNo + qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, data.Id) + qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn) + qncProductProductNameKey := fmt.Sprintf("%s%v", cacheQncProductProductNamePrefix, data.ProductName) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, productRowsExpectAutoSet) + if session != nil { + return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ProductName, data.ProductEn, data.Description, data.Notes, data.CostPrice, data.SellPrice) + } + return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ProductName, data.ProductEn, data.Description, data.Notes, data.CostPrice, data.SellPrice) + }, qncProductIdKey, qncProductProductEnKey, qncProductProductNameKey) +} + +func (m *defaultProductModel) FindOne(ctx context.Context, id int64) (*Product, error) { + qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, id) + var resp Product + err := m.QueryRowCtx(ctx, &resp, qncProductIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", productRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultProductModel) FindOneByProductEn(ctx context.Context, productEn string) (*Product, error) { + qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, productEn) + var resp Product + err := m.QueryRowIndexCtx(ctx, &resp, qncProductProductEnKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `product_en` = ? AND del_state = ? limit 1", productRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, productEn, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultProductModel) FindOneByProductName(ctx context.Context, productName string) (*Product, error) { + qncProductProductNameKey := fmt.Sprintf("%s%v", cacheQncProductProductNamePrefix, productName) + var resp Product + err := m.QueryRowIndexCtx(ctx, &resp, qncProductProductNameKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `product_name` = ? AND del_state = ? limit 1", productRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, productName, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultProductModel) Update(ctx context.Context, session sqlx.Session, newData *Product) (sql.Result, error) { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return nil, err + } + qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, data.Id) + qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn) + qncProductProductNameKey := fmt.Sprintf("%s%v", cacheQncProductProductNamePrefix, data.ProductName) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, productRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id) + }, qncProductIdKey, qncProductProductEnKey, qncProductProductNameKey) +} + +func (m *defaultProductModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *Product) error { + + oldVersion := newData.Version + newData.Version += 1 + + var sqlResult sql.Result + var err error + + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, data.Id) + qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn) + qncProductProductNameKey := fmt.Sprintf("%s%v", cacheQncProductProductNamePrefix, data.ProductName) + sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ? AND version = ? ", m.table, productRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id, oldVersion) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id, oldVersion) + }, qncProductIdKey, qncProductProductEnKey, qncProductProductNameKey) + if err != nil { + return err + } + updateCount, err := sqlResult.RowsAffected() + if err != nil { + return err + } + if updateCount == 0 { + return model.ErrNoRowsUpdate + } + + return nil +} + +func (m *defaultProductModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *Product) error { + data.DelState = globalkey.DelStateYes + data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true} + if err := m.UpdateWithVersion(ctx, session, data); err != nil { + return errors.Wrapf(errors.New("delete soft failed "), "ProductModel delete err : %+v", err) + } + return nil +} + +func (m *defaultProductModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field") + } + + builder = builder.Columns("IFNULL(SUM(" + field + "),0)") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp float64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultProductModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field") + } + + builder = builder.Columns("COUNT(" + field + ")") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp int64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultProductModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*Product, error) { + + builder = builder.Columns(productRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return nil, err + } + + var resp []*Product + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultProductModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Product, error) { + + builder = builder.Columns(productRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Product + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultProductModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Product, int64, error) { + + total, err := m.FindCount(ctx, builder, "id") + if err != nil { + return nil, 0, err + } + + builder = builder.Columns(productRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, total, err + } + + var resp []*Product + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, total, nil + default: + return nil, total, err + } +} + +func (m *defaultProductModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*Product, error) { + + builder = builder.Columns(productRows) + + if preMinId > 0 { + builder = builder.Where(" id < ? ", preMinId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Product + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultProductModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*Product, error) { + + builder = builder.Columns(productRows) + + if preMaxId > 0 { + builder = builder.Where(" id > ? ", preMaxId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Product + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultProductModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error { + + return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { + return fn(ctx, session) + }) + +} + +func (m *defaultProductModel) SelectBuilder() squirrel.SelectBuilder { + return squirrel.Select().From(m.table) +} +func (m *defaultProductModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, id) + qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn) + qncProductProductNameKey := fmt.Sprintf("%s%v", cacheQncProductProductNamePrefix, data.ProductName) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("DELETE FROM %s WHERE `id` = ?", m.table) + if session != nil { + return session.ExecCtx(ctx, query, id) + } + return conn.ExecCtx(ctx, query, id) + }, qncProductIdKey, qncProductProductEnKey, qncProductProductNameKey) + return err +} +func (m *defaultProductModel) formatPrimary(primary interface{}) string { + return fmt.Sprintf("%s%v", cacheQncProductIdPrefix, primary) +} +func (m *defaultProductModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", productRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo) +} + +func (m *defaultProductModel) tableName() string { + return m.table +} diff --git a/app/user/model/queryModel.go b/app/user/model/queryModel.go new file mode 100644 index 0000000..88486c7 --- /dev/null +++ b/app/user/model/queryModel.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ QueryModel = (*customQueryModel)(nil) + +type ( + // QueryModel is an interface to be customized, add more methods here, + // and implement the added methods in customQueryModel. + QueryModel interface { + queryModel + } + + customQueryModel struct { + *defaultQueryModel + } +) + +// NewQueryModel returns a model for the database table. +func NewQueryModel(conn sqlx.SqlConn, c cache.CacheConf) QueryModel { + return &customQueryModel{ + defaultQueryModel: newQueryModel(conn, c), + } +} diff --git a/app/user/model/queryModel_gen.go b/app/user/model/queryModel_gen.go new file mode 100644 index 0000000..f8a7ccf --- /dev/null +++ b/app/user/model/queryModel_gen.go @@ -0,0 +1,412 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "database/sql" + "fmt" + "qnc-server/deploy/script/model" + "strings" + + "time" + + "github.com/Masterminds/squirrel" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" + "qnc-server/common/globalkey" +) + +var ( + queryFieldNames = builder.RawFieldNames(&Query{}) + queryRows = strings.Join(queryFieldNames, ",") + queryRowsExpectAutoSet = strings.Join(stringx.Remove(queryFieldNames, "`id`", "`create_time`", "`update_time`"), ",") + queryRowsWithPlaceHolder = strings.Join(stringx.Remove(queryFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + + cacheQncQueryIdPrefix = "cache:qnc:query:id:" + cacheQncQueryOrderIdPrefix = "cache:qnc:query:orderId:" +) + +type ( + queryModel interface { + Insert(ctx context.Context, session sqlx.Session, data *Query) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*Query, error) + FindOneByOrderId(ctx context.Context, orderId int64) (*Query, error) + Update(ctx context.Context, session sqlx.Session, data *Query) (sql.Result, error) + UpdateWithVersion(ctx context.Context, session sqlx.Session, data *Query) error + Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error + SelectBuilder() squirrel.SelectBuilder + DeleteSoft(ctx context.Context, session sqlx.Session, data *Query) error + FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error) + FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error) + FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*Query, error) + FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Query, error) + FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Query, int64, error) + FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*Query, error) + FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*Query, error) + Delete(ctx context.Context, session sqlx.Session, id int64) error + } + + defaultQueryModel struct { + sqlc.CachedConn + table string + } + + Query struct { + Id int64 `db:"id"` // 主键ID + OrderId int64 `db:"order_id"` // 订单ID(软关联到订单表) + UserId int64 `db:"user_id"` // 用户ID(直接关联到用户) + ProductId int64 `db:"product_id"` // 产品ID(直接关联到产品) + QueryParams string `db:"query_params"` // 查询params数据 + QueryData sql.NullString `db:"query_data"` // 查询结果数据 + QueryState string `db:"query_state"` // 查询状态 + DelState int64 `db:"del_state"` // 删除状态 + Version int64 `db:"version"` // 版本号 + CreateTime time.Time `db:"create_time"` // 创建时间 + UpdateTime time.Time `db:"update_time"` // 更新时间 + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + } +) + +func newQueryModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultQueryModel { + return &defaultQueryModel{ + CachedConn: sqlc.NewConn(conn, c), + table: "`query`", + } +} + +func (m *defaultQueryModel) Insert(ctx context.Context, session sqlx.Session, data *Query) (sql.Result, error) { + data.DelState = globalkey.DelStateNo + qncQueryIdKey := fmt.Sprintf("%s%v", cacheQncQueryIdPrefix, data.Id) + qncQueryOrderIdKey := fmt.Sprintf("%s%v", cacheQncQueryOrderIdPrefix, data.OrderId) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, queryRowsExpectAutoSet) + if session != nil { + return session.ExecCtx(ctx, query, data.OrderId, data.UserId, data.ProductId, data.QueryParams, data.QueryData, data.QueryState, data.DelState, data.Version, data.DeleteTime) + } + return conn.ExecCtx(ctx, query, data.OrderId, data.UserId, data.ProductId, data.QueryParams, data.QueryData, data.QueryState, data.DelState, data.Version, data.DeleteTime) + }, qncQueryIdKey, qncQueryOrderIdKey) +} + +func (m *defaultQueryModel) FindOne(ctx context.Context, id int64) (*Query, error) { + qncQueryIdKey := fmt.Sprintf("%s%v", cacheQncQueryIdPrefix, id) + var resp Query + err := m.QueryRowCtx(ctx, &resp, qncQueryIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", queryRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultQueryModel) FindOneByOrderId(ctx context.Context, orderId int64) (*Query, error) { + qncQueryOrderIdKey := fmt.Sprintf("%s%v", cacheQncQueryOrderIdPrefix, orderId) + var resp Query + err := m.QueryRowIndexCtx(ctx, &resp, qncQueryOrderIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `order_id` = ? AND del_state = ? limit 1", queryRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, orderId, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultQueryModel) Update(ctx context.Context, session sqlx.Session, newData *Query) (sql.Result, error) { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return nil, err + } + qncQueryIdKey := fmt.Sprintf("%s%v", cacheQncQueryIdPrefix, data.Id) + qncQueryOrderIdKey := fmt.Sprintf("%s%v", cacheQncQueryOrderIdPrefix, data.OrderId) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, queryRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.OrderId, newData.UserId, newData.ProductId, newData.QueryParams, newData.QueryData, newData.QueryState, newData.DelState, newData.Version, newData.DeleteTime, newData.Id) + } + return conn.ExecCtx(ctx, query, newData.OrderId, newData.UserId, newData.ProductId, newData.QueryParams, newData.QueryData, newData.QueryState, newData.DelState, newData.Version, newData.DeleteTime, newData.Id) + }, qncQueryIdKey, qncQueryOrderIdKey) +} + +func (m *defaultQueryModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *Query) error { + + oldVersion := newData.Version + newData.Version += 1 + + var sqlResult sql.Result + var err error + + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + qncQueryIdKey := fmt.Sprintf("%s%v", cacheQncQueryIdPrefix, data.Id) + qncQueryOrderIdKey := fmt.Sprintf("%s%v", cacheQncQueryOrderIdPrefix, data.OrderId) + sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ? AND version = ? ", m.table, queryRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.OrderId, newData.UserId, newData.ProductId, newData.QueryParams, newData.QueryData, newData.QueryState, newData.DelState, newData.Version, newData.DeleteTime, newData.Id, oldVersion) + } + return conn.ExecCtx(ctx, query, newData.OrderId, newData.UserId, newData.ProductId, newData.QueryParams, newData.QueryData, newData.QueryState, newData.DelState, newData.Version, newData.DeleteTime, newData.Id, oldVersion) + }, qncQueryIdKey, qncQueryOrderIdKey) + if err != nil { + return err + } + updateCount, err := sqlResult.RowsAffected() + if err != nil { + return err + } + if updateCount == 0 { + return model.ErrNoRowsUpdate + } + + return nil +} + +func (m *defaultQueryModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *Query) error { + data.DelState = globalkey.DelStateYes + data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true} + if err := m.UpdateWithVersion(ctx, session, data); err != nil { + return errors.Wrapf(errors.New("delete soft failed "), "QueryModel delete err : %+v", err) + } + return nil +} + +func (m *defaultQueryModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field") + } + + builder = builder.Columns("IFNULL(SUM(" + field + "),0)") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp float64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultQueryModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field") + } + + builder = builder.Columns("COUNT(" + field + ")") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp int64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultQueryModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*Query, error) { + + builder = builder.Columns(queryRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return nil, err + } + + var resp []*Query + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultQueryModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Query, error) { + + builder = builder.Columns(queryRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Query + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultQueryModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Query, int64, error) { + + total, err := m.FindCount(ctx, builder, "id") + if err != nil { + return nil, 0, err + } + + builder = builder.Columns(queryRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, total, err + } + + var resp []*Query + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, total, nil + default: + return nil, total, err + } +} + +func (m *defaultQueryModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*Query, error) { + + builder = builder.Columns(queryRows) + + if preMinId > 0 { + builder = builder.Where(" id < ? ", preMinId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Query + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultQueryModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*Query, error) { + + builder = builder.Columns(queryRows) + + if preMaxId > 0 { + builder = builder.Where(" id > ? ", preMaxId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Query + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultQueryModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error { + + return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { + return fn(ctx, session) + }) + +} + +func (m *defaultQueryModel) SelectBuilder() squirrel.SelectBuilder { + return squirrel.Select().From(m.table) +} +func (m *defaultQueryModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + qncQueryIdKey := fmt.Sprintf("%s%v", cacheQncQueryIdPrefix, id) + qncQueryOrderIdKey := fmt.Sprintf("%s%v", cacheQncQueryOrderIdPrefix, data.OrderId) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("DELETE FROM %s WHERE `id` = ?", m.table) + if session != nil { + return session.ExecCtx(ctx, query, id) + } + return conn.ExecCtx(ctx, query, id) + }, qncQueryIdKey, qncQueryOrderIdKey) + return err +} +func (m *defaultQueryModel) formatPrimary(primary interface{}) string { + return fmt.Sprintf("%s%v", cacheQncQueryIdPrefix, primary) +} +func (m *defaultQueryModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", queryRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo) +} + +func (m *defaultQueryModel) tableName() string { + return m.table +} diff --git a/app/user/model/userAuthModel.go b/app/user/model/userAuthModel.go new file mode 100644 index 0000000..0812e1d --- /dev/null +++ b/app/user/model/userAuthModel.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ UserAuthModel = (*customUserAuthModel)(nil) + +type ( + // UserAuthModel is an interface to be customized, add more methods here, + // and implement the added methods in customUserAuthModel. + UserAuthModel interface { + userAuthModel + } + + customUserAuthModel struct { + *defaultUserAuthModel + } +) + +// NewUserAuthModel returns a model for the database table. +func NewUserAuthModel(conn sqlx.SqlConn, c cache.CacheConf) UserAuthModel { + return &customUserAuthModel{ + defaultUserAuthModel: newUserAuthModel(conn, c), + } +} diff --git a/app/user/model/userAuthModel_gen.go b/app/user/model/userAuthModel_gen.go new file mode 100644 index 0000000..3b2bc18 --- /dev/null +++ b/app/user/model/userAuthModel_gen.go @@ -0,0 +1,434 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "time" + + "github.com/Masterminds/squirrel" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" + "qnc-server/common/globalkey" +) + +var ( + userAuthFieldNames = builder.RawFieldNames(&UserAuth{}) + userAuthRows = strings.Join(userAuthFieldNames, ",") + userAuthRowsExpectAutoSet = strings.Join(stringx.Remove(userAuthFieldNames, "`id`", "`create_time`", "`update_time`"), ",") + userAuthRowsWithPlaceHolder = strings.Join(stringx.Remove(userAuthFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + + cacheQncUserAuthIdPrefix = "cache:qnc:userAuth:id:" + cacheQncUserAuthAuthTypeAuthKeyPrefix = "cache:qnc:userAuth:authType:authKey:" + cacheQncUserAuthUserIdAuthTypePrefix = "cache:qnc:userAuth:userId:authType:" +) + +type ( + userAuthModel interface { + Insert(ctx context.Context, session sqlx.Session, data *UserAuth) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*UserAuth, error) + FindOneByAuthTypeAuthKey(ctx context.Context, authType string, authKey string) (*UserAuth, error) + FindOneByUserIdAuthType(ctx context.Context, userId int64, authType string) (*UserAuth, error) + Update(ctx context.Context, session sqlx.Session, data *UserAuth) (sql.Result, error) + UpdateWithVersion(ctx context.Context, session sqlx.Session, data *UserAuth) error + Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error + SelectBuilder() squirrel.SelectBuilder + DeleteSoft(ctx context.Context, session sqlx.Session, data *UserAuth) error + FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error) + FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error) + FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*UserAuth, error) + FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*UserAuth, error) + FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*UserAuth, int64, error) + FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*UserAuth, error) + FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*UserAuth, error) + Delete(ctx context.Context, session sqlx.Session, id int64) error + } + + defaultUserAuthModel struct { + sqlc.CachedConn + table string + } + + UserAuth struct { + Id int64 `db:"id"` + CreateTime time.Time `db:"create_time"` + UpdateTime time.Time `db:"update_time"` + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + DelState int64 `db:"del_state"` + Version int64 `db:"version"` // 版本号 + UserId int64 `db:"user_id"` + AuthKey string `db:"auth_key"` // 平台唯一id + AuthType string `db:"auth_type"` // 平台类型 + } +) + +func newUserAuthModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultUserAuthModel { + return &defaultUserAuthModel{ + CachedConn: sqlc.NewConn(conn, c), + table: "`user_auth`", + } +} + +func (m *defaultUserAuthModel) Insert(ctx context.Context, session sqlx.Session, data *UserAuth) (sql.Result, error) { + data.DelState = globalkey.DelStateNo + qncUserAuthAuthTypeAuthKeyKey := fmt.Sprintf("%s%v:%v", cacheQncUserAuthAuthTypeAuthKeyPrefix, data.AuthType, data.AuthKey) + qncUserAuthIdKey := fmt.Sprintf("%s%v", cacheQncUserAuthIdPrefix, data.Id) + qncUserAuthUserIdAuthTypeKey := fmt.Sprintf("%s%v:%v", cacheQncUserAuthUserIdAuthTypePrefix, data.UserId, data.AuthType) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, userAuthRowsExpectAutoSet) + if session != nil { + return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.UserId, data.AuthKey, data.AuthType) + } + return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.UserId, data.AuthKey, data.AuthType) + }, qncUserAuthAuthTypeAuthKeyKey, qncUserAuthIdKey, qncUserAuthUserIdAuthTypeKey) +} + +func (m *defaultUserAuthModel) FindOne(ctx context.Context, id int64) (*UserAuth, error) { + qncUserAuthIdKey := fmt.Sprintf("%s%v", cacheQncUserAuthIdPrefix, id) + var resp UserAuth + err := m.QueryRowCtx(ctx, &resp, qncUserAuthIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { + query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", userAuthRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserAuthModel) FindOneByAuthTypeAuthKey(ctx context.Context, authType string, authKey string) (*UserAuth, error) { + qncUserAuthAuthTypeAuthKeyKey := fmt.Sprintf("%s%v:%v", cacheQncUserAuthAuthTypeAuthKeyPrefix, authType, authKey) + var resp UserAuth + err := m.QueryRowIndexCtx(ctx, &resp, qncUserAuthAuthTypeAuthKeyKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("select %s from %s where `auth_type` = ? and `auth_key` = ? and del_state = ? limit 1", userAuthRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, authType, authKey, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserAuthModel) FindOneByUserIdAuthType(ctx context.Context, userId int64, authType string) (*UserAuth, error) { + qncUserAuthUserIdAuthTypeKey := fmt.Sprintf("%s%v:%v", cacheQncUserAuthUserIdAuthTypePrefix, userId, authType) + var resp UserAuth + err := m.QueryRowIndexCtx(ctx, &resp, qncUserAuthUserIdAuthTypeKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("select %s from %s where `user_id` = ? and `auth_type` = ? and del_state = ? limit 1", userAuthRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, userId, authType, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserAuthModel) Update(ctx context.Context, session sqlx.Session, newData *UserAuth) (sql.Result, error) { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return nil, err + } + qncUserAuthAuthTypeAuthKeyKey := fmt.Sprintf("%s%v:%v", cacheQncUserAuthAuthTypeAuthKeyPrefix, data.AuthType, data.AuthKey) + qncUserAuthIdKey := fmt.Sprintf("%s%v", cacheQncUserAuthIdPrefix, data.Id) + qncUserAuthUserIdAuthTypeKey := fmt.Sprintf("%s%v:%v", cacheQncUserAuthUserIdAuthTypePrefix, data.UserId, data.AuthType) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, userAuthRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.UserId, newData.AuthKey, newData.AuthType, newData.Id) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.UserId, newData.AuthKey, newData.AuthType, newData.Id) + }, qncUserAuthAuthTypeAuthKeyKey, qncUserAuthIdKey, qncUserAuthUserIdAuthTypeKey) +} + +func (m *defaultUserAuthModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *UserAuth) error { + + oldVersion := newData.Version + newData.Version += 1 + + var sqlResult sql.Result + var err error + + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + qncUserAuthAuthTypeAuthKeyKey := fmt.Sprintf("%s%v:%v", cacheQncUserAuthAuthTypeAuthKeyPrefix, data.AuthType, data.AuthKey) + qncUserAuthIdKey := fmt.Sprintf("%s%v", cacheQncUserAuthIdPrefix, data.Id) + qncUserAuthUserIdAuthTypeKey := fmt.Sprintf("%s%v:%v", cacheQncUserAuthUserIdAuthTypePrefix, data.UserId, data.AuthType) + sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, userAuthRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.UserId, newData.AuthKey, newData.AuthType, newData.Id, oldVersion) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.UserId, newData.AuthKey, newData.AuthType, newData.Id, oldVersion) + }, qncUserAuthAuthTypeAuthKeyKey, qncUserAuthIdKey, qncUserAuthUserIdAuthTypeKey) + if err != nil { + return err + } + updateCount, err := sqlResult.RowsAffected() + if err != nil { + return err + } + if updateCount == 0 { + return ErrNoRowsUpdate + } + + return nil +} + +func (m *defaultUserAuthModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *UserAuth) error { + data.DelState = globalkey.DelStateYes + data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true} + if err := m.UpdateWithVersion(ctx, session, data); err != nil { + return errors.Wrapf(errors.New("delete soft failed "), "UserAuthModel delete err : %+v", err) + } + return nil +} + +func (m *defaultUserAuthModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field") + } + + builder = builder.Columns("IFNULL(SUM(" + field + "),0)") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp float64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultUserAuthModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field") + } + + builder = builder.Columns("COUNT(" + field + ")") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp int64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultUserAuthModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*UserAuth, error) { + + builder = builder.Columns(userAuthRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return nil, err + } + + var resp []*UserAuth + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserAuthModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*UserAuth, error) { + + builder = builder.Columns(userAuthRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*UserAuth + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserAuthModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*UserAuth, int64, error) { + + total, err := m.FindCount(ctx, builder, "id") + if err != nil { + return nil, 0, err + } + + builder = builder.Columns(userAuthRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, total, err + } + + var resp []*UserAuth + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, total, nil + default: + return nil, total, err + } +} + +func (m *defaultUserAuthModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*UserAuth, error) { + + builder = builder.Columns(userAuthRows) + + if preMinId > 0 { + builder = builder.Where(" id < ? ", preMinId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*UserAuth + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserAuthModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*UserAuth, error) { + + builder = builder.Columns(userAuthRows) + + if preMaxId > 0 { + builder = builder.Where(" id > ? ", preMaxId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*UserAuth + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserAuthModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error { + + return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { + return fn(ctx, session) + }) + +} + +func (m *defaultUserAuthModel) SelectBuilder() squirrel.SelectBuilder { + return squirrel.Select().From(m.table) +} +func (m *defaultUserAuthModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + qncUserAuthAuthTypeAuthKeyKey := fmt.Sprintf("%s%v:%v", cacheQncUserAuthAuthTypeAuthKeyPrefix, data.AuthType, data.AuthKey) + qncUserAuthIdKey := fmt.Sprintf("%s%v", cacheQncUserAuthIdPrefix, id) + qncUserAuthUserIdAuthTypeKey := fmt.Sprintf("%s%v:%v", cacheQncUserAuthUserIdAuthTypePrefix, data.UserId, data.AuthType) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + if session != nil { + return session.ExecCtx(ctx, query, id) + } + return conn.ExecCtx(ctx, query, id) + }, qncUserAuthAuthTypeAuthKeyKey, qncUserAuthIdKey, qncUserAuthUserIdAuthTypeKey) + return err +} +func (m *defaultUserAuthModel) formatPrimary(primary interface{}) string { + return fmt.Sprintf("%s%v", cacheQncUserAuthIdPrefix, primary) +} +func (m *defaultUserAuthModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { + query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", userAuthRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo) +} + +func (m *defaultUserAuthModel) tableName() string { + return m.table +} diff --git a/app/user/model/userModel.go b/app/user/model/userModel.go new file mode 100644 index 0000000..8123712 --- /dev/null +++ b/app/user/model/userModel.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ UserModel = (*customUserModel)(nil) + +type ( + // UserModel is an interface to be customized, add more methods here, + // and implement the added methods in customUserModel. + UserModel interface { + userModel + } + + customUserModel struct { + *defaultUserModel + } +) + +// NewUserModel returns a model for the database table. +func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) UserModel { + return &customUserModel{ + defaultUserModel: newUserModel(conn, c), + } +} diff --git a/app/user/model/userModel_gen.go b/app/user/model/userModel_gen.go new file mode 100644 index 0000000..ec3d97d --- /dev/null +++ b/app/user/model/userModel_gen.go @@ -0,0 +1,410 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "database/sql" + "fmt" + "qnc-server/deploy/script/model" + "strings" + + "time" + + "github.com/Masterminds/squirrel" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" + "qnc-server/common/globalkey" +) + +var ( + userFieldNames = builder.RawFieldNames(&User{}) + userRows = strings.Join(userFieldNames, ",") + userRowsExpectAutoSet = strings.Join(stringx.Remove(userFieldNames, "`id`", "`create_time`", "`update_time`"), ",") + userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + + cacheQncUserIdPrefix = "cache:qnc:user:id:" + cacheQncUserMobilePrefix = "cache:qnc:user:mobile:" +) + +type ( + userModel interface { + Insert(ctx context.Context, session sqlx.Session, data *User) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*User, error) + FindOneByMobile(ctx context.Context, mobile string) (*User, error) + Update(ctx context.Context, session sqlx.Session, data *User) (sql.Result, error) + UpdateWithVersion(ctx context.Context, session sqlx.Session, data *User) error + Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error + SelectBuilder() squirrel.SelectBuilder + DeleteSoft(ctx context.Context, session sqlx.Session, data *User) error + FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error) + FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error) + FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*User, error) + FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*User, error) + FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*User, int64, error) + FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*User, error) + FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*User, error) + Delete(ctx context.Context, session sqlx.Session, id int64) error + } + + defaultUserModel struct { + sqlc.CachedConn + table string + } + + User struct { + Id int64 `db:"id"` + CreateTime time.Time `db:"create_time"` + UpdateTime time.Time `db:"update_time"` + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + DelState int64 `db:"del_state"` + Version int64 `db:"version"` // 版本号 + Mobile string `db:"mobile"` + Password sql.NullString `db:"password"` + Nickname string `db:"nickname"` + Info string `db:"info"` + } +) + +func newUserModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultUserModel { + return &defaultUserModel{ + CachedConn: sqlc.NewConn(conn, c), + table: "`user`", + } +} + +func (m *defaultUserModel) Insert(ctx context.Context, session sqlx.Session, data *User) (sql.Result, error) { + data.DelState = globalkey.DelStateNo + qncUserIdKey := fmt.Sprintf("%s%v", cacheQncUserIdPrefix, data.Id) + qncUserMobileKey := fmt.Sprintf("%s%v", cacheQncUserMobilePrefix, data.Mobile) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?, ?)", m.table, userRowsExpectAutoSet) + if session != nil { + return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.Mobile, data.Password, data.Nickname, data.Info) + } + return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.Mobile, data.Password, data.Nickname, data.Info) + }, qncUserIdKey, qncUserMobileKey) +} + +func (m *defaultUserModel) FindOne(ctx context.Context, id int64) (*User, error) { + qncUserIdKey := fmt.Sprintf("%s%v", cacheQncUserIdPrefix, id) + var resp User + err := m.QueryRowCtx(ctx, &resp, qncUserIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", userRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserModel) FindOneByMobile(ctx context.Context, mobile string) (*User, error) { + qncUserMobileKey := fmt.Sprintf("%s%v", cacheQncUserMobilePrefix, mobile) + var resp User + err := m.QueryRowIndexCtx(ctx, &resp, qncUserMobileKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `mobile` = ? AND del_state = ? limit 1", userRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, mobile, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, model.ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserModel) Update(ctx context.Context, session sqlx.Session, newData *User) (sql.Result, error) { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return nil, err + } + qncUserIdKey := fmt.Sprintf("%s%v", cacheQncUserIdPrefix, data.Id) + qncUserMobileKey := fmt.Sprintf("%s%v", cacheQncUserMobilePrefix, data.Mobile) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, userRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.Mobile, newData.Password, newData.Nickname, newData.Info, newData.Id) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.Mobile, newData.Password, newData.Nickname, newData.Info, newData.Id) + }, qncUserIdKey, qncUserMobileKey) +} + +func (m *defaultUserModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *User) error { + + oldVersion := newData.Version + newData.Version += 1 + + var sqlResult sql.Result + var err error + + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + qncUserIdKey := fmt.Sprintf("%s%v", cacheQncUserIdPrefix, data.Id) + qncUserMobileKey := fmt.Sprintf("%s%v", cacheQncUserMobilePrefix, data.Mobile) + sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ? AND version = ? ", m.table, userRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.Mobile, newData.Password, newData.Nickname, newData.Info, newData.Id, oldVersion) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.Mobile, newData.Password, newData.Nickname, newData.Info, newData.Id, oldVersion) + }, qncUserIdKey, qncUserMobileKey) + if err != nil { + return err + } + updateCount, err := sqlResult.RowsAffected() + if err != nil { + return err + } + if updateCount == 0 { + return model.ErrNoRowsUpdate + } + + return nil +} + +func (m *defaultUserModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *User) error { + data.DelState = globalkey.DelStateYes + data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true} + if err := m.UpdateWithVersion(ctx, session, data); err != nil { + return errors.Wrapf(errors.New("delete soft failed "), "UserModel delete err : %+v", err) + } + return nil +} + +func (m *defaultUserModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field") + } + + builder = builder.Columns("IFNULL(SUM(" + field + "),0)") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp float64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultUserModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field") + } + + builder = builder.Columns("COUNT(" + field + ")") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp int64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultUserModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*User, error) { + + builder = builder.Columns(userRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return nil, err + } + + var resp []*User + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*User, error) { + + builder = builder.Columns(userRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*User + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*User, int64, error) { + + total, err := m.FindCount(ctx, builder, "id") + if err != nil { + return nil, 0, err + } + + builder = builder.Columns(userRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, total, err + } + + var resp []*User + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, total, nil + default: + return nil, total, err + } +} + +func (m *defaultUserModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*User, error) { + + builder = builder.Columns(userRows) + + if preMinId > 0 { + builder = builder.Where(" id < ? ", preMinId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*User + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*User, error) { + + builder = builder.Columns(userRows) + + if preMaxId > 0 { + builder = builder.Where(" id > ? ", preMaxId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*User + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error { + + return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { + return fn(ctx, session) + }) + +} + +func (m *defaultUserModel) SelectBuilder() squirrel.SelectBuilder { + return squirrel.Select().From(m.table) +} +func (m *defaultUserModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + qncUserIdKey := fmt.Sprintf("%s%v", cacheQncUserIdPrefix, id) + qncUserMobileKey := fmt.Sprintf("%s%v", cacheQncUserMobilePrefix, data.Mobile) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("DELETE FROM %s WHERE `id` = ?", m.table) + if session != nil { + return session.ExecCtx(ctx, query, id) + } + return conn.ExecCtx(ctx, query, id) + }, qncUserIdKey, qncUserMobileKey) + return err +} +func (m *defaultUserModel) formatPrimary(primary interface{}) string { + return fmt.Sprintf("%s%v", cacheQncUserIdPrefix, primary) +} +func (m *defaultUserModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? AND del_state = ? limit 1", userRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo) +} + +func (m *defaultUserModel) tableName() string { + return m.table +} diff --git a/app/user/model/vars.go b/app/user/model/vars.go new file mode 100644 index 0000000..4723f1b --- /dev/null +++ b/app/user/model/vars.go @@ -0,0 +1,15 @@ +package model + +import ( + "errors" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var ErrNotFound = sqlx.ErrNotFound +var ErrNoRowsUpdate = errors.New("update db no rows change") + +var UserAuthTypeAppMobile string = "app_mobile" //平台内部 +var UserAuthTypeAppWechat string = "app_wechat" //微信小程序 +var UserAuthTypeH5Mobile string = "h5_mobile" +var UserAuthTypeWxMini string = "wx_mini" +var UserAuthTypeWxOfficialAccount string = "wx_official_account" diff --git a/deploy/script/model/vars.go b/deploy/script/model/vars.go new file mode 100644 index 0000000..9267571 --- /dev/null +++ b/deploy/script/model/vars.go @@ -0,0 +1,9 @@ +package model + +import ( + "errors" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var ErrNotFound = sqlx.ErrNotFound +var ErrNoRowsUpdate = errors.New("update db no rows change")