diff --git a/api/auth/auth.go b/api/auth/auth.go index f84dedd..a7bd84e 100644 --- a/api/auth/auth.go +++ b/api/auth/auth.go @@ -13,5 +13,7 @@ import ( type IAuthV1 interface { AdminLogin(ctx context.Context, req *v1.AdminLoginReq) (res *v1.AdminLoginRes, err error) MerchantLogin(ctx context.Context, req *v1.MerchantLoginReq) (res *v1.MerchantLoginRes, err error) + MerchantCode(ctx context.Context, req *v1.MerchantCodeReq) (res *v1.MerchantCodeRes, err error) + MerchantRegister(ctx context.Context, req *v1.MerchantRegisterReq) (res *v1.MerchantRegisterRes, err error) StoreLogin(ctx context.Context, req *v1.StoreLoginReq) (res *v1.StoreLoginRes, err error) } diff --git a/api/auth/v1/auth.go b/api/auth/v1/auth.go index dbe274b..3ca1e96 100644 --- a/api/auth/v1/auth.go +++ b/api/auth/v1/auth.go @@ -7,6 +7,7 @@ type AdminLoginReq struct { Username string `json:"username" v:"required" dc:"用户名"` Password string `json:"password" v:"required" dc:"密码"` } + type AdminLoginRes struct { g.Meta `mime:"application/json"` Token string `json:"token"` @@ -14,16 +15,37 @@ type AdminLoginRes struct { type MerchantLoginReq struct { g.Meta `path:"/merchant/login" method:"post" tags:"Merchant" summary:"(商户管理员)商户登录"` - Usernaem string `json:"username" v:"required" dc:"用户名"` + Username string `json:"username" dc:"用户名"` + Phone string `json:"phone" v:"regex:^1[3-9]\\d{9}$" dc:"手机号"` + Code string `json:"code" dc:"验证码"` Password string `json:"password" v:"required" dc:"密码"` } + type MerchantLoginRes struct { g.Meta `mime:"application/json"` Token string `json:"token"` } -type MerchantRegisterReq struct { + +type MerchantCodeReq struct { + g.Meta `path:"/merchant/code" method:"get" tags:"Merchant" summary:"(商户管理员)商户获取短信验证码"` + Phone string `json:"phone" v:"required" dc:"手机号"` } + +type MerchantCodeRes struct{} + +type MerchantRegisterReq struct { + g.Meta `path:"/merchant/register" method:"post" tags:"Merchant" summary:"(商户管理员)商户注册"` + Username string `json:"username" v:"required" dc:"用户名"` + Phone string `json:"phone" v:"required|regex:^1[3-9]\\d{9}$" dc:"手机号"` + Code string `json:"code" v:"required" dc:"验证码"` + Password string `json:"password" v:"required|length:6,20" dc:"密码(6-20位)"` + Password2 string `json:"password2" v:"required|same:password" dc:"确认密码"` + ApplicationReason string `json:"applicationReason" v:"required|length:5,200" dc:"申请理由(5~200字)"` +} + type MerchantRegisterRes struct { + Success bool `json:"success" dc:"是否成功"` + Msg string `json:"msg" dc:"提示信息"` } type StoreLoginReq struct { @@ -31,6 +53,7 @@ type StoreLoginReq struct { Username string `json:"username" v:"required" dc:"用户名"` Password string `json:"password" v:"required" dc:"密码"` } + type StoreLoginRes struct { g.Meta `mime:"application/json"` Token string `json:"token"` diff --git a/api/roleMenu/roleMenu.go b/api/merchant/merchant.go similarity index 52% rename from api/roleMenu/roleMenu.go rename to api/merchant/merchant.go index 7d5ff1f..a60d275 100644 --- a/api/roleMenu/roleMenu.go +++ b/api/merchant/merchant.go @@ -2,15 +2,17 @@ // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. // ================================================================================= -package roleMenu +package merchant import ( "context" - "server/api/roleMenu/v1" + "server/api/merchant/v1" ) -type IRoleMenuV1 interface { +type IMerchantV1 interface { List(ctx context.Context, req *v1.ListReq) (res *v1.ListRes, err error) - SaveRoleMenu(ctx context.Context, req *v1.SaveRoleMenuReq) (res *v1.SaveRoleMenuRes, err error) + Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) + Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) + Audit(ctx context.Context, req *v1.AuditReq) (res *v1.AuditRes, err error) } diff --git a/api/merchant/v1/merchant.go b/api/merchant/v1/merchant.go new file mode 100644 index 0000000..3eba5b6 --- /dev/null +++ b/api/merchant/v1/merchant.go @@ -0,0 +1,39 @@ +package v1 + +import "github.com/gogf/gf/v2/frame/g" + +type ListReq struct { + g.Meta `path:"/merchant" method:"get" tags:"Merchant" summary:"(系统管理员)获取商户列表"` + Page int `json:"page" dc:"页数"` + Size int `json:"size" dc:"每页数量"` + Status int `json:"status" dc:"状态:1=启用,2=禁用"` + AuditStatus int `json:"auditStatus" dc:"审核状态:0=待审核,1=审核通过,2=审核拒绝"` +} +type ListRes struct { + List interface{} `json:"list" dc:"商户列表"` + Total int `json:"total" dc:"总数"` +} + +type CreateReq struct { + g.Meta `path:"/merchant" method:"post" tags:"Merchant" summary:"(系统管理员)创建商户"` +} +type CreateRes struct { + Id int64 `json:"id" dc:"商户ID"` +} + +type UpdateReq struct { + g.Meta `path:"/merchant" method:"put" tags:"Merchant" summary:"(系统管理员、商户管理员)更新商户"` +} +type UpdateRes struct { + Success bool `json:"success" dc:"是否成功"` +} + +type AuditReq struct { + g.Meta `path:"/merchant/audit" method:"post" tags:"Merchant" summary:"(系统管理员)商户审核"` + Id int64 `json:"id" v:"required" dc:"商户ID"` + AuditStatus int `json:"auditStatus" v:"required" dc:"审核状态:1=审核通过,2=审核拒绝" ` + AuditRemark string `json:"auditRemark" dc:"审核备注"` + RejectReason string `json:"rejectReason" dc:"拒绝原因"` +} +type AuditRes struct { +} diff --git a/api/merchantAdmin/merchantAdmin.go b/api/merchantAdmin/merchantAdmin.go new file mode 100644 index 0000000..2e77d32 --- /dev/null +++ b/api/merchantAdmin/merchantAdmin.go @@ -0,0 +1,15 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package merchantAdmin + +import ( + "context" + + "server/api/merchantAdmin/v1" +) + +type IMerchantAdminV1 interface { + MerchantAdminInfo(ctx context.Context, req *v1.MerchantAdminInfoReq) (res *v1.MerchantAdminInfoRes, err error) +} diff --git a/api/merchantAdmin/v1/merchantAdmin.go b/api/merchantAdmin/v1/merchantAdmin.go new file mode 100644 index 0000000..3a24027 --- /dev/null +++ b/api/merchantAdmin/v1/merchantAdmin.go @@ -0,0 +1,11 @@ +package v1 + +import ( + "github.com/gogf/gf/v2/frame/g" +) + +type MerchantAdminInfoReq struct { + g.Meta `path:"/merchant/info" method:"get" tags:"MerchantAdmin" summary:"(商户管理员)获取商户管理员信息"` +} +type MerchantAdminInfoRes struct { +} diff --git a/api/roleMenu/v1/roleMenu.go b/api/roleMenu/v1/roleMenu.go deleted file mode 100644 index 262f092..0000000 --- a/api/roleMenu/v1/roleMenu.go +++ /dev/null @@ -1,27 +0,0 @@ -package v1 - -import ( - "github.com/gogf/gf/v2/frame/g" -) - -// ListReq 角色菜单列表请求 -type ListReq struct { - g.Meta `path:"/role-menu" method:"get" tags:"角色菜单" summary:"获取角色菜单列表"` - RoleId int64 `json:"roleId" v:"required#角色ID不能为空" dc:"角色ID"` -} - -// ListRes 角色菜单列表响应 -type ListRes struct { - List interface{} `json:"list" dc:"角色菜单列表"` - Total int `json:"total" dc:"总条数"` -} - -type SaveRoleMenuReq struct { - g.Meta `path:"/role-menu" method:"post" tags:"角色菜单" summary:"保存角色菜单"` - RoleId int `json:"roleId" v:"required#角色ID不能为空" dc:"角色ID"` - MenuIds []int `json:"menuIds" v:"required#菜单ID列表不能为空" dc:"菜单ID列表"` -} - -type SaveRoleMenuRes struct { - Success bool `json:"success" dc:"是否成功"` -} diff --git a/api/store/v1/store.go b/api/store/v1/store.go new file mode 100644 index 0000000..f303695 --- /dev/null +++ b/api/store/v1/store.go @@ -0,0 +1,37 @@ +package v1 + +import ( + "github.com/gogf/gf/v2/frame/g" +) + +type ListReq struct { + g.Meta `path:"/store" method:"get" tags:"Store" summary:"(系统管理员、商户管理员)获取门店列表"` + Page int `json:"page" dc:"页数"` + Size int `json:"size" dc:"每页数量"` + MerchantId int `json:"merchantId" dc:"商户ID"` +} +type ListRes struct { + List interface{} `json:"list" dc:"商户列表"` + Total int `json:"total" dc:"总数"` +} +type CreateReq struct { + g.Meta `path:"/store" method:"post" tags:"Store" summary:"(商户管理员)创建门店"` + Name string `json:"name" v:"required" dc:"门店名称"` + ContactName string `json:"contactName" v:"required" dc:"联系人"` + ContactPhone string `json:"contactPhone" v:"required" dc:"联系人电话"` +} +type CreateRes struct { + Id int64 `json:"id" dc:"门店ID"` +} +type UpdateReq struct { + g.Meta `path:"/store" method:"put" tags:"Store" summary:"(商户管理员)更新门店"` + Id int64 `json:"id" v:"required" dc:"门店ID"` + Name string `json:"name" v:"required" dc:"门店名称"` + Address string `json:"address" v:"required" dc:"门店地址"` + ContactName string `json:"contactName" v:"required" dc:"联系人"` + ContactPhone string `json:"contactPhone" v:"required" dc:"联系人电话"` +} + +type UpdateRes struct { + Success bool `json:"success" dc:"是否成功"` +} diff --git a/go.mod b/go.mod index ab5d5ca..d295aa3 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module server go 1.24.2 require ( + github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible github.com/casbin/casbin/v2 v2.105.0 github.com/go-resty/resty/v2 v2.16.5 github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0 @@ -12,7 +13,6 @@ require ( github.com/google/uuid v1.6.0 github.com/hailaz/gf-casbin-adapter/v2 v2.8.1 golang.org/x/crypto v0.38.0 - golang.org/x/sync v0.14.0 ) require ( @@ -44,5 +44,6 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/text v0.25.0 // indirect + golang.org/x/time v0.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 11d8cac..8cc4620 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= +github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= @@ -95,8 +97,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index f9da4f9..df94f4a 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -8,6 +8,7 @@ import ( "server/internal/controller/admin" "server/internal/controller/auth" "server/internal/controller/menu" + "server/internal/controller/merchant" "server/internal/controller/role" "server/internal/controller/wx" "server/internal/middleware" @@ -34,6 +35,7 @@ var ( admin.NewV1(), role.NewV1(), menu.NewV1(), + merchant.NewV1(), ) }) }) diff --git a/internal/consts/consts.go b/internal/consts/consts.go index 961d35a..d709a2b 100644 --- a/internal/consts/consts.go +++ b/internal/consts/consts.go @@ -1,8 +1 @@ package consts - -const ( - UserRoleCode = "user" - AdminRoleCode = "admin" - MerchantRoleCode = "merchant" - StoreRoleCode = "store" -) diff --git a/internal/consts/merchant.go b/internal/consts/merchant.go new file mode 100644 index 0000000..c7dac4e --- /dev/null +++ b/internal/consts/merchant.go @@ -0,0 +1,20 @@ +package consts + +// 商户状态 +const ( + MerchantNormalStatus = iota + 1 + MerchantDisabledStatus +) + +// 商户审核状态 +const ( + MerchantPendingReview = iota + MerchantReviewPassed + MerchantReviewRejected +) + +// 商户注册类型 +const ( + MerchantRegisterByAdmin = iota + 1 + MerchantRegisterBySelf +) diff --git a/internal/consts/merchant_admin.go b/internal/consts/merchant_admin.go new file mode 100644 index 0000000..354b9ef --- /dev/null +++ b/internal/consts/merchant_admin.go @@ -0,0 +1,7 @@ +package consts + +// 商户管理员状态 +const ( + MerchantAdministratorEnable = iota + 1 + MerchantAdministratorDisable +) diff --git a/internal/consts/role.go b/internal/consts/role.go new file mode 100644 index 0000000..f3ef3f1 --- /dev/null +++ b/internal/consts/role.go @@ -0,0 +1,14 @@ +package consts + +const ( + GuestRoleCode = "guest" + UserRoleCode = "user" + AdminRoleCode = "admin" + MerchantRoleCode = "merchant" + StoreRoleCode = "store" +) + +const ( + RoleEnable = iota + 1 + RoleDisable +) diff --git a/internal/controller/admin/admin_v1_admin_info.go b/internal/controller/admin/admin_v1_admin_info.go index 8ca6ff5..3c61443 100644 --- a/internal/controller/admin/admin_v1_admin_info.go +++ b/internal/controller/admin/admin_v1_admin_info.go @@ -11,7 +11,7 @@ import ( ) func (c *ControllerV1) AdminInfo(ctx context.Context, req *v1.AdminInfoReq) (res *v1.AdminInfoRes, err error) { - userId := g.RequestFromCtx(ctx).GetCtxVar("userId").Int() + userId := g.RequestFromCtx(ctx).GetCtxVar("userId").Int64() out, err := service.Admin().Info(ctx, &model.AdminInfoIn{Id: userId}) if err != nil { return nil, err diff --git a/internal/controller/auth/auth_v1_merchant_code.go b/internal/controller/auth/auth_v1_merchant_code.go new file mode 100644 index 0000000..f0fc85b --- /dev/null +++ b/internal/controller/auth/auth_v1_merchant_code.go @@ -0,0 +1,16 @@ +package auth + +import ( + "context" + "server/internal/model" + "server/internal/service" + + "server/api/auth/v1" +) + +func (c *ControllerV1) MerchantCode(ctx context.Context, req *v1.MerchantCodeReq) (res *v1.MerchantCodeRes, err error) { + if _, err = service.MerchantAdmin().Code(ctx, &model.MerchantAdminCodeIn{Phone: req.Phone}); err != nil { + return nil, err + } + return &v1.MerchantCodeRes{}, nil +} diff --git a/internal/controller/auth/auth_v1_merchant_login.go b/internal/controller/auth/auth_v1_merchant_login.go index f3d2e5a..e0e0375 100644 --- a/internal/controller/auth/auth_v1_merchant_login.go +++ b/internal/controller/auth/auth_v1_merchant_login.go @@ -2,13 +2,16 @@ package auth import ( "context" - - "github.com/gogf/gf/v2/errors/gcode" - "github.com/gogf/gf/v2/errors/gerror" + "server/internal/model" + "server/internal/service" "server/api/auth/v1" ) func (c *ControllerV1) MerchantLogin(ctx context.Context, req *v1.MerchantLoginReq) (res *v1.MerchantLoginRes, err error) { - return nil, gerror.NewCode(gcode.CodeNotImplemented) + out, err := service.MerchantAdmin().Login(ctx, &model.MerchantLoginIn{Password: req.Password, Username: req.Username}) + if err != nil { + return nil, err + } + return &v1.MerchantLoginRes{Token: out.Token}, nil } diff --git a/internal/controller/auth/auth_v1_merchant_register.go b/internal/controller/auth/auth_v1_merchant_register.go new file mode 100644 index 0000000..ff33ce2 --- /dev/null +++ b/internal/controller/auth/auth_v1_merchant_register.go @@ -0,0 +1,20 @@ +package auth + +import ( + "context" + "server/internal/model" + "server/internal/service" + + "server/api/auth/v1" +) + +func (c *ControllerV1) MerchantRegister(ctx context.Context, req *v1.MerchantRegisterReq) (res *v1.MerchantRegisterRes, err error) { + out, err := service.MerchantAdmin().Register(ctx, &model.MerchantAdminRegisterIn{Username: req.Username, Password: req.Password, Phone: req.Phone, ApplicationReason: req.ApplicationReason, Code: req.Code}) + if err != nil { + return nil, err + } + return &v1.MerchantRegisterRes{ + Msg: "申请成功, 等待系统管理员审核申请", + Success: out.Success, + }, nil +} diff --git a/internal/controller/roleMenu/roleMenu.go b/internal/controller/merchant/merchant.go similarity index 93% rename from internal/controller/roleMenu/roleMenu.go rename to internal/controller/merchant/merchant.go index f7374a6..031daa8 100644 --- a/internal/controller/roleMenu/roleMenu.go +++ b/internal/controller/merchant/merchant.go @@ -2,4 +2,4 @@ // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. // ================================================================================= -package roleMenu +package merchant diff --git a/internal/controller/roleMenu/roleMenu_new.go b/internal/controller/merchant/merchant_new.go similarity index 80% rename from internal/controller/roleMenu/roleMenu_new.go rename to internal/controller/merchant/merchant_new.go index d650b03..d6126dd 100644 --- a/internal/controller/roleMenu/roleMenu_new.go +++ b/internal/controller/merchant/merchant_new.go @@ -2,14 +2,14 @@ // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. // ================================================================================= -package roleMenu +package merchant import ( - "server/api/roleMenu" + "server/api/merchant" ) type ControllerV1 struct{} -func NewV1() roleMenu.IRoleMenuV1 { +func NewV1() merchant.IMerchantV1 { return &ControllerV1{} } diff --git a/internal/controller/merchant/merchant_v1_audit.go b/internal/controller/merchant/merchant_v1_audit.go new file mode 100644 index 0000000..18f6b92 --- /dev/null +++ b/internal/controller/merchant/merchant_v1_audit.go @@ -0,0 +1,19 @@ +package merchant + +import ( + "context" + "github.com/gogf/gf/v2/frame/g" + "server/internal/model" + "server/internal/service" + + "server/api/merchant/v1" +) + +func (c *ControllerV1) Audit(ctx context.Context, req *v1.AuditReq) (res *v1.AuditRes, err error) { + adminId := g.RequestFromCtx(ctx).GetCtxVar("adminId").Int64() + _, err = service.Merchant().Audit(ctx, &model.MerchantAuditIn{Id: req.Id, AuditStatus: req.AuditStatus, AuditRemark: req.AuditRemark, AdminId: adminId, RejectReason: req.RejectReason}) + if err != nil { + return nil, err + } + return &v1.AuditRes{}, nil +} diff --git a/internal/controller/merchant/merchant_v1_create.go b/internal/controller/merchant/merchant_v1_create.go new file mode 100644 index 0000000..ed52cd0 --- /dev/null +++ b/internal/controller/merchant/merchant_v1_create.go @@ -0,0 +1,14 @@ +package merchant + +import ( + "context" + + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" + + "server/api/merchant/v1" +) + +func (c *ControllerV1) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) { + return nil, gerror.NewCode(gcode.CodeNotImplemented) +} diff --git a/internal/controller/roleMenu/roleMenu_v1_list.go b/internal/controller/merchant/merchant_v1_list.go similarity index 51% rename from internal/controller/roleMenu/roleMenu_v1_list.go rename to internal/controller/merchant/merchant_v1_list.go index 558ee2d..1abfc8a 100644 --- a/internal/controller/roleMenu/roleMenu_v1_list.go +++ b/internal/controller/merchant/merchant_v1_list.go @@ -1,20 +1,20 @@ -package roleMenu +package merchant import ( "context" "server/internal/model" "server/internal/service" - "server/api/roleMenu/v1" + "server/api/merchant/v1" ) func (c *ControllerV1) List(ctx context.Context, req *v1.ListReq) (res *v1.ListRes, err error) { - list, err := service.RoleMenu().List(ctx, &model.RoleMenuListInput{RoleId: req.RoleId}) + out, err := service.Merchant().List(ctx, &model.MerchantListIn{Page: req.Page, Size: req.Size, AuditStatus: req.AuditStatus, Status: req.Status}) if err != nil { return nil, err } return &v1.ListRes{ - List: list.List, - Total: list.Total, + List: out.List, + Total: out.Total, }, nil } diff --git a/internal/controller/merchant/merchant_v1_update.go b/internal/controller/merchant/merchant_v1_update.go new file mode 100644 index 0000000..5265c58 --- /dev/null +++ b/internal/controller/merchant/merchant_v1_update.go @@ -0,0 +1,14 @@ +package merchant + +import ( + "context" + + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" + + "server/api/merchant/v1" +) + +func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) { + return nil, gerror.NewCode(gcode.CodeNotImplemented) +} diff --git a/internal/controller/merchantAdmin/merchantAdmin.go b/internal/controller/merchantAdmin/merchantAdmin.go new file mode 100644 index 0000000..c17204b --- /dev/null +++ b/internal/controller/merchantAdmin/merchantAdmin.go @@ -0,0 +1,5 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package merchantAdmin diff --git a/internal/controller/merchantAdmin/merchantAdmin_new.go b/internal/controller/merchantAdmin/merchantAdmin_new.go new file mode 100644 index 0000000..8d4766d --- /dev/null +++ b/internal/controller/merchantAdmin/merchantAdmin_new.go @@ -0,0 +1,15 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package merchantAdmin + +import ( + "server/api/merchantAdmin" +) + +type ControllerV1 struct{} + +func NewV1() merchantAdmin.IMerchantAdminV1 { + return &ControllerV1{} +} diff --git a/internal/controller/merchantAdmin/merchantAdmin_v1_merchant_admin_info.go b/internal/controller/merchantAdmin/merchantAdmin_v1_merchant_admin_info.go new file mode 100644 index 0000000..9874cf7 --- /dev/null +++ b/internal/controller/merchantAdmin/merchantAdmin_v1_merchant_admin_info.go @@ -0,0 +1,14 @@ +package merchantAdmin + +import ( + "context" + + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" + + "server/api/merchantAdmin/v1" +) + +func (c *ControllerV1) MerchantAdminInfo(ctx context.Context, req *v1.MerchantAdminInfoReq) (res *v1.MerchantAdminInfoRes, err error) { + return nil, gerror.NewCode(gcode.CodeNotImplemented) +} diff --git a/internal/controller/roleMenu/roleMenu_v1_save_role_menu.go b/internal/controller/roleMenu/roleMenu_v1_save_role_menu.go deleted file mode 100644 index 62e4b32..0000000 --- a/internal/controller/roleMenu/roleMenu_v1_save_role_menu.go +++ /dev/null @@ -1,20 +0,0 @@ -package roleMenu - -import ( - "context" - "server/internal/model" - "server/internal/service" - - "server/api/roleMenu/v1" -) - -func (c *ControllerV1) SaveRoleMenu(ctx context.Context, req *v1.SaveRoleMenuReq) (res *v1.SaveRoleMenuRes, err error) { - out, err := service.RoleMenu().Save(ctx, &model.RoleMenuSaveInput{RoleId: req.RoleId, MenuIds: req.MenuIds}) - if err != nil { - return nil, err - } - return &v1.SaveRoleMenuRes{ - Success: out.Success, - }, nil - -} diff --git a/internal/dao/internal/merchant_admins.go b/internal/dao/internal/merchant_admins.go index 69594e4..706ef30 100644 --- a/internal/dao/internal/merchant_admins.go +++ b/internal/dao/internal/merchant_admins.go @@ -33,6 +33,9 @@ type MerchantAdminsColumns struct { CreatedAt string // 创建时间 UpdatedAt string // 更新时间 DeletedAt string // 软删除时间戳 + IsPrimary string // 是否主账号:0=否,1=是 + LastLoginIp string // 最后登录IP + RoleId string // 角色ID } // merchantAdminsColumns holds the columns for the table merchant_admins. @@ -50,6 +53,9 @@ var merchantAdminsColumns = MerchantAdminsColumns{ CreatedAt: "created_at", UpdatedAt: "updated_at", DeletedAt: "deleted_at", + IsPrimary: "is_primary", + LastLoginIp: "last_login_ip", + RoleId: "role_id", } // NewMerchantAdminsDao creates and returns a new DAO object for table data access. diff --git a/internal/dao/internal/merchants.go b/internal/dao/internal/merchants.go index 2d89a9d..4b47491 100644 --- a/internal/dao/internal/merchants.go +++ b/internal/dao/internal/merchants.go @@ -20,36 +20,52 @@ type MerchantsDao struct { // MerchantsColumns defines and stores column names for the table merchants. type MerchantsColumns struct { - Id string // 商户ID - Name string // 商户名称 - BusinessLicense string // 营业执照号 - LegalPerson string // 法人姓名 - ContactName string // 联系人姓名 - ContactPhone string // 联系人电话 - ContactEmail string // 联系人邮箱 - Address string // 商户地址 - Status string // 状态:1=正常,2=禁用,3=待审核 - ExpireAt string // 服务到期时间 - CreatedAt string // 创建时间 - UpdatedAt string // 更新时间 - DeletedAt string // 软删除时间戳 + Id string // 商户ID + Name string // 商户名称 + BusinessLicense string // 营业执照号 + LegalPerson string // 法人姓名 + ContactName string // 联系人姓名 + ContactPhone string // 联系人电话 + ContactEmail string // 联系人邮箱 + Address string // 商户地址 + Status string // 状态:1=正常,2=禁用 + ExpireAt string // 服务到期时间 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + DeletedAt string // 软删除时间戳 + ApplicationReason string // 申请理由 + CreatedBy string // 创建人ID + CreatedByType string // 创建人类型:1=系统管理员,2=商户注册 + AuditStatus string // 审核状态:0=待审核,1=审核通过,2=审核拒绝 + AuditBy string // 审核人ID + AuditAt string // 审核时间 + AuditRemark string // 审核备注 + RejectReason string // 拒绝原因 } // merchantsColumns holds the columns for the table merchants. var merchantsColumns = MerchantsColumns{ - Id: "id", - Name: "name", - BusinessLicense: "business_license", - LegalPerson: "legal_person", - ContactName: "contact_name", - ContactPhone: "contact_phone", - ContactEmail: "contact_email", - Address: "address", - Status: "status", - ExpireAt: "expire_at", - CreatedAt: "created_at", - UpdatedAt: "updated_at", - DeletedAt: "deleted_at", + Id: "id", + Name: "name", + BusinessLicense: "business_license", + LegalPerson: "legal_person", + ContactName: "contact_name", + ContactPhone: "contact_phone", + ContactEmail: "contact_email", + Address: "address", + Status: "status", + ExpireAt: "expire_at", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", + ApplicationReason: "application_reason", + CreatedBy: "created_by", + CreatedByType: "created_by_type", + AuditStatus: "audit_status", + AuditBy: "audit_by", + AuditAt: "audit_at", + AuditRemark: "audit_remark", + RejectReason: "reject_reason", } // NewMerchantsDao creates and returns a new DAO object for table data access. diff --git a/internal/dao/internal/store_admins.go b/internal/dao/internal/store_admins.go index f88a28f..730a2a5 100644 --- a/internal/dao/internal/store_admins.go +++ b/internal/dao/internal/store_admins.go @@ -33,6 +33,7 @@ type StoreAdminsColumns struct { CreatedAt string // 创建时间 UpdatedAt string // 更新时间 DeletedAt string // 软删除时间戳 + RoleId string // 角色ID } // storeAdminsColumns holds the columns for the table store_admins. @@ -50,6 +51,7 @@ var storeAdminsColumns = StoreAdminsColumns{ CreatedAt: "created_at", UpdatedAt: "updated_at", DeletedAt: "deleted_at", + RoleId: "role_id", } // NewStoreAdminsDao creates and returns a new DAO object for table data access. diff --git a/internal/dao/internal/stores.go b/internal/dao/internal/stores.go index 0f1f706..d64c8d8 100644 --- a/internal/dao/internal/stores.go +++ b/internal/dao/internal/stores.go @@ -20,34 +20,32 @@ type StoresDao struct { // StoresColumns defines and stores column names for the table stores. type StoresColumns struct { - Id string // 门店ID - MerchantId string // 所属商户ID - Name string // 门店名称 - StoreCode string // 门店编号 - Address string // 门店地址 - ContactName string // 联系人姓名 - ContactPhone string // 联系人电话 - BusinessHours string // 营业时间 - Status string // 状态:1=正常营业,2=暂停营业,3=已关闭 - CreatedAt string // 创建时间 - UpdatedAt string // 更新时间 - DeletedAt string // 软删除时间戳 + Id string // 门店ID + MerchantId string // 所属商户ID + Name string // 门店名称 + StoreCode string // 门店编号 + Address string // 门店地址 + ContactName string // 联系人姓名 + ContactPhone string // 联系人电话 + Status string // 状态:1=正常营业,2=暂停营业,3=已关闭 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + DeletedAt string // 软删除时间戳 } // storesColumns holds the columns for the table stores. var storesColumns = StoresColumns{ - Id: "id", - MerchantId: "merchant_id", - Name: "name", - StoreCode: "store_code", - Address: "address", - ContactName: "contact_name", - ContactPhone: "contact_phone", - BusinessHours: "business_hours", - Status: "status", - CreatedAt: "created_at", - UpdatedAt: "updated_at", - DeletedAt: "deleted_at", + Id: "id", + MerchantId: "merchant_id", + Name: "name", + StoreCode: "store_code", + Address: "address", + ContactName: "contact_name", + ContactPhone: "contact_phone", + Status: "status", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", } // NewStoresDao creates and returns a new DAO object for table data access. diff --git a/internal/logic/admin/admin.go b/internal/logic/admin/admin.go index 48c4378..59eafeb 100644 --- a/internal/logic/admin/admin.go +++ b/internal/logic/admin/admin.go @@ -37,7 +37,7 @@ func checkAdmin() { Name: "系统管理员", Code: consts.AdminRoleCode, Description: "管理员角色", - Status: 1, + Status: consts.RoleEnable, IsDeletable: false, }) } else { diff --git a/internal/logic/logic.go b/internal/logic/logic.go index 2d252b0..4785ed4 100644 --- a/internal/logic/logic.go +++ b/internal/logic/logic.go @@ -7,9 +7,8 @@ package logic import ( _ "server/internal/logic/admin" _ "server/internal/logic/menu" + _ "server/internal/logic/merchant" _ "server/internal/logic/merchantAdmin" _ "server/internal/logic/role" - _ "server/internal/logic/roleMenu" - _ "server/internal/logic/storeAdmin" _ "server/internal/logic/user" ) diff --git a/internal/logic/merchant/merchant.go b/internal/logic/merchant/merchant.go new file mode 100644 index 0000000..6e334a1 --- /dev/null +++ b/internal/logic/merchant/merchant.go @@ -0,0 +1,83 @@ +package merchant + +import ( + "context" + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/os/gtime" + "server/internal/consts" + "server/internal/dao" + "server/internal/model" + "server/internal/model/do" + "server/internal/service" + "server/utility/ecode" +) + +type sMerchant struct { +} + +func New() service.IMerchant { + return &sMerchant{} +} + +func init() { + service.RegisterMerchant(New()) +} + +func (s *sMerchant) List(ctx context.Context, in *model.MerchantListIn) (out *model.MerchantListOut, err error) { + list := make([]model.Merchant, 0) + var total int + orm := dao.Merchants.Ctx(ctx) + if in.Status != 0 { + orm = orm.Where(dao.Merchants.Columns().Status, in.Status) + } + if in.AuditStatus != 0 { + orm = orm.Where(dao.Merchants.Columns().AuditStatus, in.AuditStatus) + } + if err = orm.Page(in.Page, in.Size).ScanAndCount(&list, &total, false); err != nil { + return nil, ecode.Fail.Sub("查询商户列表失败") + } + return &model.MerchantListOut{ + List: list, + Total: total, + }, nil +} +func (s *sMerchant) Audit(ctx context.Context, in *model.MerchantAuditIn) (out *model.MerchantAuditOut, err error) { + merchant, err := dao.Merchants.Ctx(ctx).WherePri(in.Id).One() + if err != nil { + return nil, ecode.Fail.Sub("查询商户失败") + } + if merchant.IsEmpty() { + return nil, ecode.Params.Sub("商户不存在") + } + if merchant[dao.Merchants.Columns().AuditStatus].Int() != 0 { + return nil, ecode.Params.Sub("商户已审核") + } + if err = dao.Merchants.Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) { + if _, err = tx.Model(dao.Merchants.Table()).WherePri(in.Id).Data(do.Merchants{ + AuditBy: in.AdminId, + AuditRemark: in.AuditRemark, + AuditStatus: in.AuditStatus, + AuditAt: gtime.Now(), + Status: in.AuditStatus, // 暂定审核通过商户即可使用 + RejectReason: in.RejectReason, + }).OmitEmptyData().Update(); err != nil { + + return ecode.Fail.Sub("审核商户失败") + } + if _, err = tx.Model(dao.MerchantAdmins.Table()).Where(do.MerchantAdmins{MerchantId: in.Id, IsPrimary: true}).Data(do.MerchantAdmins{ + Status: consts.MerchantAdministratorEnable, + }).Update(); err != nil { + return ecode.Fail.Sub("审核商户失败") + } + return nil + }); err != nil { + return nil, err + } + + return +} + +func (s *sMerchant) Create(ctx context.Context, in *model.MerchantCreateIn) (out *model.CreateOut, err error) { + + return +} diff --git a/internal/logic/merchantAdmin/merchantAdmin.go b/internal/logic/merchantAdmin/merchantAdmin.go index 8ae480a..16a9794 100644 --- a/internal/logic/merchantAdmin/merchantAdmin.go +++ b/internal/logic/merchantAdmin/merchantAdmin.go @@ -1 +1,168 @@ package merchantAdmin + +import ( + "context" + "fmt" + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/grand" + "server/internal/consts" + "server/internal/dao" + "server/internal/model" + "server/internal/model/do" + "server/internal/service" + "server/utility/ecode" + utility "server/utility/encrypt" + "server/utility/jwt" +) + +type sMerchantAdmin struct { +} + +func New() service.IMerchantAdmin { + return &sMerchantAdmin{} +} +func init() { + service.RegisterMerchantAdmin(New()) + go checkMerchantRole() +} + +func checkMerchantRole() { + ctx := context.Background() + exist, err := dao.Roles.Ctx(ctx).Where(do.Roles{Code: consts.MerchantRoleCode}).Exist() + if err != nil { + return + } + if !exist { + _, err = dao.Roles.Ctx(ctx).Insert(do.Roles{ + Name: "商户管理员", + Code: consts.MerchantRoleCode, + Description: "商户管理员角色", + Status: consts.RoleEnable, + IsDeletable: false, + }) + if err != nil { + return + } + } + +} + +func (s *sMerchantAdmin) Login(ctx context.Context, in *model.MerchantLoginIn) (out *model.MerchantLoginOut, err error) { + mAdmin, err := dao.MerchantAdmins.Ctx(ctx).Where(do.MerchantAdmins{Username: in.Username}).One() + if err != nil { + return nil, ecode.Fail.Sub("查询商户管理员失败") + } + + if mAdmin.IsEmpty() { + return nil, ecode.Params.Sub("该用户不存在") + } + + if mAdmin[dao.MerchantAdmins.Columns().Status].Int() == consts.MerchantAdministratorDisable { + return nil, ecode.Params.Sub("该用户已被禁用") + } + if !utility.ComparePassword(mAdmin[dao.MerchantAdmins.Columns().PasswordHash].String(), in.Password) { + return nil, ecode.Params.Sub("密码错误") + } + value, err := dao.Roles.Ctx(ctx).WherePri(mAdmin[dao.MerchantAdmins.Columns().RoleId].Int()).Fields(dao.Roles.Columns().Code).Value() + if err != nil { + return nil, ecode.Fail.Sub("查询角色失败") + } + mAdminId := mAdmin[dao.MerchantAdmins.Columns().Id].Int64() + token, err := jwt.GenerateToken(&jwt.TokenIn{UserId: mAdminId, Role: value.String()}) + if err != nil { + return nil, ecode.Fail.Sub("生成token失败") + } + out = &model.MerchantLoginOut{ + Token: token, + } + go func(ctx context.Context, merchantAdminId int64) { + // 更新商户管理员登录时间 + dao.MerchantAdmins.Ctx(ctx).WherePri(merchantAdminId).Update(do.MerchantAdmins{ + LastLoginAt: gtime.Now(), + LastLoginIp: ghttp.RequestFromCtx(ctx).RemoteAddr, + }) + }(ctx, mAdminId) + return +} +func (s *sMerchantAdmin) Info(ctx context.Context, in *model.MerchantAdminInfoIn) (out *model.MerchantAdminInfoOut, err error) { + return +} +func (s *sMerchantAdmin) Code(ctx context.Context, in *model.MerchantAdminCodeIn) (out *model.MerchantAdminCodeOut, err error) { + exist, err := dao.MerchantAdmins.Ctx(ctx).Where(do.MerchantAdmins{Phone: in.Phone}).Exist() + if err != nil { + return nil, ecode.Fail.Sub("查询商户管理员失败") + } + if exist { + return nil, ecode.Fail.Sub("该手机号已被注册") + } + // TODO 调用验证码服务发送验证码 + // 插入缓存,过期时间为 5 分钟 + if err = g.Redis().SetEX(ctx, "merchant_admin_code:"+in.Phone, grand.Digits(6), 5*60); err != nil { + return nil, ecode.Fail.Sub("插入验证码缓存失败") + } + + return &model.MerchantAdminCodeOut{}, nil +} + +func (s *sMerchantAdmin) VertifyPhone(ctx context.Context, in *model.MerchantAdminVertifyPhoneIn) (out *model.MerchantAdminVertifyPhoneOut, err error) { + return +} + +func (s *sMerchantAdmin) Register(ctx context.Context, in *model.MerchantAdminRegisterIn) (out *model.MerchantAdminRegisterOut, err error) { + exist, err := dao.MerchantAdmins.Ctx(ctx).Where(do.MerchantAdmins{Username: in.Username}).Exist() + if err != nil { + return nil, ecode.Fail.Sub("查询商户管理员失败") + } + if exist { + return nil, ecode.Fail.Sub("该用户名已被注册") + } + // 验证码校验 + code, err := g.Redis().Get(ctx, "merchant_admin_code:"+in.Phone) + if err != nil { + return nil, ecode.Fail.Sub("获取验证码缓存失败") + } + if code.IsEmpty() { + return nil, ecode.Fail.Sub("验证码已过期") + } + if code.String() != in.Code { + return nil, ecode.Fail.Sub("验证码错误") + } + hashPass, err := utility.EncryptPassword(in.Password) + if err != nil { + return nil, ecode.Fail.Sub("密码加密失败") + } + if err = dao.MerchantAdmins.Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) { + // 插入商户数据 + id, err := tx.Model(dao.Merchants.Table()).Data(do.Merchants{ + Name: fmt.Sprintf("%s的商铺", in.Username), + CreatedByType: consts.MerchantRegisterByAdmin, + Status: consts.MerchantDisabledStatus, + AuditStatus: consts.MerchantPendingReview, + ContactPhone: in.Phone, + ApplicationReason: in.ApplicationReason, + }).InsertAndGetId() + if err != nil { + return ecode.Fail.Sub("插入商户数据失败") + } + + // 插入商户管理员数据 + if _, err = tx.Model(dao.MerchantAdmins.Table()).Data(do.MerchantAdmins{ + MerchantId: id, + PasswordHash: hashPass, + Phone: in.Phone, + IsPrimary: true, + Username: in.Username, + Status: consts.MerchantAdministratorEnable, + }).Insert(); err != nil { + return ecode.Fail.Sub("插入商户管理员数据失败") + } + return + }); err != nil { + return nil, err + } + g.Redis().Del(ctx, "merchant_admin_code:"+in.Phone) + return &model.MerchantAdminRegisterOut{Success: true}, nil +} diff --git a/internal/logic/roleMenu/roleMenu.go b/internal/logic/roleMenu/roleMenu.go deleted file mode 100644 index 9548d30..0000000 --- a/internal/logic/roleMenu/roleMenu.go +++ /dev/null @@ -1,28 +0,0 @@ -package roleMenu - -import ( - "context" - "server/internal/model" - "server/internal/service" -) - -type sRoleMenu struct { -} - -func New() service.IRoleMenu { - return &sRoleMenu{} -} -func init() { - service.RegisterRoleMenu(New()) -} - -func init() { - -} -func (s *sRoleMenu) List(ctx context.Context, in *model.RoleMenuListInput) (out *model.MenuListOutput, err error) { - return -} - -func (s *sRoleMenu) Save(ctx context.Context, in *model.RoleMenuSaveInput) (out *model.UpdateOut, err error) { - return -} diff --git a/internal/logic/storeAdmin/storeAdmin.go b/internal/logic/storeAdmin/storeAdmin.go deleted file mode 100644 index b50226e..0000000 --- a/internal/logic/storeAdmin/storeAdmin.go +++ /dev/null @@ -1 +0,0 @@ -package storeAdmin diff --git a/internal/logic/user/user.go b/internal/logic/user/user.go index 0399a18..5dad05e 100644 --- a/internal/logic/user/user.go +++ b/internal/logic/user/user.go @@ -33,7 +33,7 @@ func checkUserRole() { Name: "用户", Code: consts.UserRoleCode, Description: "用户角色", - Status: 1, + Status: consts.RoleEnable, IsDeletable: false, }).Insert() if err != nil { diff --git a/internal/model/admin.go b/internal/model/admin.go index b47ac75..95836af 100644 --- a/internal/model/admin.go +++ b/internal/model/admin.go @@ -1,16 +1,55 @@ package model -type ( - AdminLoginIn struct { - Username string - Password string - } +// Admin 管理员信息 +type Admin struct { + Id int64 `json:"id" orm:"id,primary"` // 管理员ID + RoleId int64 `json:"roleId" orm:"role_id,not null"` // 角色ID + Username string `json:"username" orm:"username,not null"` // 管理员用户名 + PasswordHash string `json:"passwordHash" orm:"password_hash,not null"` // 密码哈希 + RealName string `json:"realName" orm:"real_name"` // 真实姓名 + Phone string `json:"phone" orm:"phone"` // 手机号 + Email string `json:"email" orm:"email"` // 邮箱 + Status int `json:"status" orm:"status,default:1"` // 状态:1=正常,2=禁用 +} - AdminInfoIn struct { - Id int - } - AdminInfoOut struct { - Id int64 - Username string - } -) +// AdminCreateIn 创建管理员请求 +type AdminCreateIn struct { + RoleId int64 + Username string + Password string + RealName string + Phone string + Email string + Status int +} + +// AdminUpdateIn 更新管理员请求 +type AdminUpdateIn struct { + Id int64 + RoleId int64 + RealName string + Phone string + Email string + Status int +} + +// AdminOut 管理员响应 +type AdminOut struct { + *Admin +} + +type AdminLoginIn struct { + Username string + Password string +} +type AdminInfoIn struct { + Id int64 +} +type AdminInfoOut struct { + Id int64 + Username string + PasswordHash string + RealName string + Phone string + Email string +} diff --git a/internal/model/do/merchant_admins.go b/internal/model/do/merchant_admins.go index 9c14284..d39cade 100644 --- a/internal/model/do/merchant_admins.go +++ b/internal/model/do/merchant_admins.go @@ -25,4 +25,7 @@ type MerchantAdmins struct { CreatedAt *gtime.Time // 创建时间 UpdatedAt *gtime.Time // 更新时间 DeletedAt *gtime.Time // 软删除时间戳 + IsPrimary interface{} // 是否主账号:0=否,1=是 + LastLoginIp interface{} // 最后登录IP + RoleId interface{} // 角色ID } diff --git a/internal/model/do/merchants.go b/internal/model/do/merchants.go index e4904ba..a444cd2 100644 --- a/internal/model/do/merchants.go +++ b/internal/model/do/merchants.go @@ -11,18 +11,26 @@ import ( // Merchants is the golang structure of table merchants for DAO operations like Where/Data. type Merchants struct { - g.Meta `orm:"table:merchants, do:true"` - Id interface{} // 商户ID - Name interface{} // 商户名称 - BusinessLicense interface{} // 营业执照号 - LegalPerson interface{} // 法人姓名 - ContactName interface{} // 联系人姓名 - ContactPhone interface{} // 联系人电话 - ContactEmail interface{} // 联系人邮箱 - Address interface{} // 商户地址 - Status interface{} // 状态:1=正常,2=禁用,3=待审核 - ExpireAt *gtime.Time // 服务到期时间 - CreatedAt *gtime.Time // 创建时间 - UpdatedAt *gtime.Time // 更新时间 - DeletedAt *gtime.Time // 软删除时间戳 + g.Meta `orm:"table:merchants, do:true"` + Id interface{} // 商户ID + Name interface{} // 商户名称 + BusinessLicense interface{} // 营业执照号 + LegalPerson interface{} // 法人姓名 + ContactName interface{} // 联系人姓名 + ContactPhone interface{} // 联系人电话 + ContactEmail interface{} // 联系人邮箱 + Address interface{} // 商户地址 + Status interface{} // 状态:1=正常,2=禁用 + ExpireAt *gtime.Time // 服务到期时间 + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 + DeletedAt *gtime.Time // 软删除时间戳 + ApplicationReason interface{} // 申请理由 + CreatedBy interface{} // 创建人ID + CreatedByType interface{} // 创建人类型:1=系统管理员,2=商户注册 + AuditStatus interface{} // 审核状态:0=待审核,1=审核通过,2=审核拒绝 + AuditBy interface{} // 审核人ID + AuditAt *gtime.Time // 审核时间 + AuditRemark interface{} // 审核备注 + RejectReason interface{} // 拒绝原因 } diff --git a/internal/model/do/store_admins.go b/internal/model/do/store_admins.go index 2468d58..6de570a 100644 --- a/internal/model/do/store_admins.go +++ b/internal/model/do/store_admins.go @@ -25,4 +25,5 @@ type StoreAdmins struct { CreatedAt *gtime.Time // 创建时间 UpdatedAt *gtime.Time // 更新时间 DeletedAt *gtime.Time // 软删除时间戳 + RoleId interface{} // 角色ID } diff --git a/internal/model/do/stores.go b/internal/model/do/stores.go index ee62e32..654ef99 100644 --- a/internal/model/do/stores.go +++ b/internal/model/do/stores.go @@ -11,17 +11,16 @@ import ( // Stores is the golang structure of table stores for DAO operations like Where/Data. type Stores struct { - g.Meta `orm:"table:stores, do:true"` - Id interface{} // 门店ID - MerchantId interface{} // 所属商户ID - Name interface{} // 门店名称 - StoreCode interface{} // 门店编号 - Address interface{} // 门店地址 - ContactName interface{} // 联系人姓名 - ContactPhone interface{} // 联系人电话 - BusinessHours interface{} // 营业时间 - Status interface{} // 状态:1=正常营业,2=暂停营业,3=已关闭 - CreatedAt *gtime.Time // 创建时间 - UpdatedAt *gtime.Time // 更新时间 - DeletedAt *gtime.Time // 软删除时间戳 + g.Meta `orm:"table:stores, do:true"` + Id interface{} // 门店ID + MerchantId interface{} // 所属商户ID + Name interface{} // 门店名称 + StoreCode interface{} // 门店编号 + Address interface{} // 门店地址 + ContactName interface{} // 联系人姓名 + ContactPhone interface{} // 联系人电话 + Status interface{} // 状态:1=正常营业,2=暂停营业,3=已关闭 + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 + DeletedAt *gtime.Time // 软删除时间戳 } diff --git a/internal/model/entity/merchant_admins.go b/internal/model/entity/merchant_admins.go index 1107715..b3c8f07 100644 --- a/internal/model/entity/merchant_admins.go +++ b/internal/model/entity/merchant_admins.go @@ -23,4 +23,7 @@ type MerchantAdmins struct { CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 + IsPrimary bool `json:"isPrimary" orm:"is_primary" description:"是否主账号:0=否,1=是"` // 是否主账号:0=否,1=是 + LastLoginIp string `json:"lastLoginIp" orm:"last_login_ip" description:"最后登录IP"` // 最后登录IP + RoleId int64 `json:"roleId" orm:"role_id" description:"角色ID"` // 角色ID } diff --git a/internal/model/entity/merchants.go b/internal/model/entity/merchants.go index 4b6ac90..7c9dafd 100644 --- a/internal/model/entity/merchants.go +++ b/internal/model/entity/merchants.go @@ -10,17 +10,25 @@ import ( // Merchants is the golang structure for table merchants. type Merchants struct { - Id int64 `json:"id" orm:"id" description:"商户ID"` // 商户ID - Name string `json:"name" orm:"name" description:"商户名称"` // 商户名称 - BusinessLicense string `json:"businessLicense" orm:"business_license" description:"营业执照号"` // 营业执照号 - LegalPerson string `json:"legalPerson" orm:"legal_person" description:"法人姓名"` // 法人姓名 - ContactName string `json:"contactName" orm:"contact_name" description:"联系人姓名"` // 联系人姓名 - ContactPhone string `json:"contactPhone" orm:"contact_phone" description:"联系人电话"` // 联系人电话 - ContactEmail string `json:"contactEmail" orm:"contact_email" description:"联系人邮箱"` // 联系人邮箱 - Address string `json:"address" orm:"address" description:"商户地址"` // 商户地址 - Status int `json:"status" orm:"status" description:"状态:1=正常,2=禁用,3=待审核"` // 状态:1=正常,2=禁用,3=待审核 - ExpireAt *gtime.Time `json:"expireAt" orm:"expire_at" description:"服务到期时间"` // 服务到期时间 - CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 - UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 - DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 + Id int64 `json:"id" orm:"id" description:"商户ID"` // 商户ID + Name string `json:"name" orm:"name" description:"商户名称"` // 商户名称 + BusinessLicense string `json:"businessLicense" orm:"business_license" description:"营业执照号"` // 营业执照号 + LegalPerson string `json:"legalPerson" orm:"legal_person" description:"法人姓名"` // 法人姓名 + ContactName string `json:"contactName" orm:"contact_name" description:"联系人姓名"` // 联系人姓名 + ContactPhone string `json:"contactPhone" orm:"contact_phone" description:"联系人电话"` // 联系人电话 + ContactEmail string `json:"contactEmail" orm:"contact_email" description:"联系人邮箱"` // 联系人邮箱 + Address string `json:"address" orm:"address" description:"商户地址"` // 商户地址 + Status int `json:"status" orm:"status" description:"状态:1=正常,2=禁用"` // 状态:1=正常,2=禁用 + ExpireAt *gtime.Time `json:"expireAt" orm:"expire_at" description:"服务到期时间"` // 服务到期时间 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 + DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 + ApplicationReason string `json:"applicationReason" orm:"application_reason" description:"申请理由"` // 申请理由 + CreatedBy int64 `json:"createdBy" orm:"created_by" description:"创建人ID"` // 创建人ID + CreatedByType int `json:"createdByType" orm:"created_by_type" description:"创建人类型:1=系统管理员,2=商户注册"` // 创建人类型:1=系统管理员,2=商户注册 + AuditStatus int `json:"auditStatus" orm:"audit_status" description:"审核状态:0=待审核,1=审核通过,2=审核拒绝"` // 审核状态:0=待审核,1=审核通过,2=审核拒绝 + AuditBy int64 `json:"auditBy" orm:"audit_by" description:"审核人ID"` // 审核人ID + AuditAt *gtime.Time `json:"auditAt" orm:"audit_at" description:"审核时间"` // 审核时间 + AuditRemark string `json:"auditRemark" orm:"audit_remark" description:"审核备注"` // 审核备注 + RejectReason string `json:"rejectReason" orm:"reject_reason" description:"拒绝原因"` // 拒绝原因 } diff --git a/internal/model/entity/store_admins.go b/internal/model/entity/store_admins.go index a9c55d1..80edc92 100644 --- a/internal/model/entity/store_admins.go +++ b/internal/model/entity/store_admins.go @@ -23,4 +23,5 @@ type StoreAdmins struct { CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 + RoleId int64 `json:"roleId" orm:"role_id" description:"角色ID"` // 角色ID } diff --git a/internal/model/entity/stores.go b/internal/model/entity/stores.go index d368123..fa0bbf8 100644 --- a/internal/model/entity/stores.go +++ b/internal/model/entity/stores.go @@ -10,16 +10,15 @@ import ( // Stores is the golang structure for table stores. type Stores struct { - Id int64 `json:"id" orm:"id" description:"门店ID"` // 门店ID - MerchantId int64 `json:"merchantId" orm:"merchant_id" description:"所属商户ID"` // 所属商户ID - Name string `json:"name" orm:"name" description:"门店名称"` // 门店名称 - StoreCode string `json:"storeCode" orm:"store_code" description:"门店编号"` // 门店编号 - Address string `json:"address" orm:"address" description:"门店地址"` // 门店地址 - ContactName string `json:"contactName" orm:"contact_name" description:"联系人姓名"` // 联系人姓名 - ContactPhone string `json:"contactPhone" orm:"contact_phone" description:"联系人电话"` // 联系人电话 - BusinessHours string `json:"businessHours" orm:"business_hours" description:"营业时间"` // 营业时间 - Status int `json:"status" orm:"status" description:"状态:1=正常营业,2=暂停营业,3=已关闭"` // 状态:1=正常营业,2=暂停营业,3=已关闭 - CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 - UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 - DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 + Id int64 `json:"id" orm:"id" description:"门店ID"` // 门店ID + MerchantId int64 `json:"merchantId" orm:"merchant_id" description:"所属商户ID"` // 所属商户ID + Name string `json:"name" orm:"name" description:"门店名称"` // 门店名称 + StoreCode string `json:"storeCode" orm:"store_code" description:"门店编号"` // 门店编号 + Address string `json:"address" orm:"address" description:"门店地址"` // 门店地址 + ContactName string `json:"contactName" orm:"contact_name" description:"联系人姓名"` // 联系人姓名 + ContactPhone string `json:"contactPhone" orm:"contact_phone" description:"联系人电话"` // 联系人电话 + Status int `json:"status" orm:"status" description:"状态:1=正常营业,2=暂停营业,3=已关闭"` // 状态:1=正常营业,2=暂停营业,3=已关闭 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 + DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 } diff --git a/internal/model/merchant.go b/internal/model/merchant.go new file mode 100644 index 0000000..787a154 --- /dev/null +++ b/internal/model/merchant.go @@ -0,0 +1,80 @@ +package model + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Merchant 商户信息 +type Merchant struct { + Id int64 `json:"id" orm:"id,primary"` // 商户ID + Name string `json:"name" orm:"name,not null"` // 商户名称 + BusinessLicense string `json:"businessLicense" orm:"business_license"` // 营业执照号 + LegalPerson string `json:"legalPerson" orm:"legal_person"` // 法人姓名 + ContactName string `json:"contactName" orm:"contact_name"` // 联系人姓名 + ContactPhone string `json:"contactPhone" orm:"contact_phone"` // 联系人电话 + ContactEmail string `json:"contactEmail" orm:"contact_email"` // 联系人邮箱 + Address string `json:"address" orm:"address"` // 商户地址 + Status int `json:"status" orm:"status,default:1"` // 状态:1=正常,2=禁用 + ExpireAt *gtime.Time `json:"expireAt" orm:"expire_at"` // 服务到期时间 + ApplicationReason int64 `json:"applicationReason" orm:"application_reason"` // 申请理由 + CreatedBy int64 `json:"createdBy" orm:"created_by"` // 创建人ID + CreatedByType int `json:"createdByType" orm:"created_by_type"` // 创建人类型:1=系统管理员,2=商户注册 + AuditStatus int `json:"auditStatus" orm:"audit_status,default:0"` // 审核状态:0=待审核,1=审核通过,2=审核拒绝 + AuditBy int64 `json:"auditBy" orm:"audit_by"` // 审核人ID + AuditAt *gtime.Time `json:"auditAt" orm:"audit_at"` // 审核时间 + AuditRemark string `json:"auditRemark" orm:"audit_remark"` // 审核备注 + RejectReason string `json:"rejectReason" orm:"reject_reason"` // 拒绝原因 +} + +// MerchantCreateIn 创建商户请求 +type MerchantCreateIn struct { + Name string + BusinessLicense string + LegalPerson string + ContactName string + ContactPhone string + ContactEmail string + Address string + ApplicationReason int64 +} + +// MerchantUpdateIn 更新商户请求 +type MerchantUpdateIn struct { + Id int64 + Name string + BusinessLicense string + LegalPerson string + ContactName string + ContactPhone string + ContactEmail string + Address string + Status int + ExpireAt *gtime.Time +} + +// MerchantAuditIn 审核商户请求 +type MerchantAuditIn struct { + AdminId int64 + Id int64 + AuditStatus int + AuditRemark string + RejectReason string +} +type MerchantAuditOut struct { +} + +// MerchantOut 商户响应 +type MerchantOut struct { + *Merchant +} + +type MerchantListIn struct { + Page int + Size int + Status int + AuditStatus int +} +type MerchantListOut struct { + List []Merchant + Total int +} diff --git a/internal/model/merchant_admin.go b/internal/model/merchant_admin.go new file mode 100644 index 0000000..6dca47a --- /dev/null +++ b/internal/model/merchant_admin.go @@ -0,0 +1,46 @@ +package model + +// MerchantAdmin 商户管理员信息 +type MerchantAdmin struct { +} + +// MerchantLoginIn 商户登录入参 +type MerchantLoginIn struct { + Phone string + Username string + Password string + Code string +} + +type MerchantLoginOut struct { + Token string +} +type MerchantAdminInfoIn struct { + MerchantAdminId int64 +} +type MerchantAdminInfoOut struct { + *MerchantAdmin +} +type MerchantAdminCodeIn struct { + Phone string +} +type MerchantAdminCodeOut struct { +} +type MerchantAdminVertifyPhoneIn struct { + MerchantAdminId int64 + Phone string + Code string +} +type MerchantAdminVertifyPhoneOut struct { +} +type MerchantAdminRegisterIn struct { + Username string + Phone string + Password string + Password2 string + Code string + ApplicationReason string +} +type MerchantAdminRegisterOut struct { + Success bool +} diff --git a/internal/model/roleMenu.go b/internal/model/roleMenu.go deleted file mode 100644 index 98711d2..0000000 --- a/internal/model/roleMenu.go +++ /dev/null @@ -1,24 +0,0 @@ -package model - -import "github.com/gogf/gf/v2/frame/g" - -type RoleMenu struct { - g.Meta `orm:"table:role_menus"` - Id int64 `json:"id" orm:"id" dc:"角色菜单ID"` - RoleId int64 `json:"roleId" orm:"role_id" dc:"角色ID"` - MenuId int64 `json:"menuId" orm:"menu_id" dc:"菜单ID"` -} -type RoleMenuListInput struct { - Page int - Size int - RoleId int64 -} -type RoleMenuListOutput struct { - List []RoleMenu - Total int -} - -type RoleMenuSaveInput struct { - RoleId int - MenuIds []int -} diff --git a/internal/model/upload.go b/internal/model/upload.go new file mode 100644 index 0000000..c0bdb78 --- /dev/null +++ b/internal/model/upload.go @@ -0,0 +1,29 @@ +package model + +import "github.com/gogf/gf/v2/net/ghttp" + +type UploadIn struct { + File *ghttp.UploadFile +} + +type UploadOut struct { + Url string +} +type OssOutput struct { + Url string +} + +type OssBytesInput struct { + Bytes []byte + Name string +} + +type OssGetFileInput struct { + FilePath string + Name string +} + +type OssUploadFileInput struct { + Filename string + File *ghttp.UploadFile +} diff --git a/internal/model/user.go b/internal/model/user.go index 1f43a43..184b757 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -1,6 +1,58 @@ package model -import "time" +import ( + "time" + + "github.com/gogf/gf/v2/os/gtime" +) + +// User 用户信息 +type User struct { + Id int64 `json:"id" orm:"id,primary"` // 用户ID + Username string `json:"username" orm:"username,not null"` // 用户名 + PasswordHash string `json:"passwordHash" orm:"password_hash,not null"` // 密码哈希 + Nickname string `json:"nickname" orm:"nickname"` // 昵称 + Avatar string `json:"avatar" orm:"avatar"` // 头像 + Phone string `json:"phone" orm:"phone"` // 手机号 + Email string `json:"email" orm:"email"` // 邮箱 + Gender int `json:"gender" orm:"gender,default:0"` // 性别:0=未知,1=男,2=女 + Birthday *gtime.Time `json:"birthday" orm:"birthday"` // 生日 + Status int `json:"status" orm:"status,default:1"` // 状态:1=正常,2=禁用 + LastLoginAt *gtime.Time `json:"lastLoginAt" orm:"last_login_at"` // 最后登录时间 + LastLoginIp string `json:"lastLoginIp" orm:"last_login_ip"` // 最后登录IP + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at"` // 更新时间 + DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at"` // 软删除时间戳 +} + +// UserCreateIn 创建用户请求 +type UserCreateIn struct { + Username string + Password string + Nickname string + Avatar string + Phone string + Email string + Gender int + Birthday *gtime.Time +} + +// UserUpdateIn 更新用户请求 +type UserUpdateIn struct { + Id int64 + Nickname string + Avatar string + Phone string + Email string + Gender int + Birthday *gtime.Time + Status int +} + +// UserOut 用户响应 +type UserOut struct { + *User +} type LoginCache struct { Token string `json:"token"` @@ -23,7 +75,5 @@ type UserInfoOut struct { Id int64 } -type UserUpdateIn struct { -} type UserBindPhoneIn struct { } diff --git a/internal/service/merchant.go b/internal/service/merchant.go new file mode 100644 index 0000000..f3a20e9 --- /dev/null +++ b/internal/service/merchant.go @@ -0,0 +1,34 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + "server/internal/model" +) + +type ( + IMerchant interface { + List(ctx context.Context, in *model.MerchantListIn) (out *model.MerchantListOut, err error) + Audit(ctx context.Context, in *model.MerchantAuditIn) (out *model.MerchantAuditOut, err error) + Create(ctx context.Context, in *model.MerchantCreateIn) (out *model.CreateOut, err error) + } +) + +var ( + localMerchant IMerchant +) + +func Merchant() IMerchant { + if localMerchant == nil { + panic("implement not found for interface IMerchant, forgot register?") + } + return localMerchant +} + +func RegisterMerchant(i IMerchant) { + localMerchant = i +} diff --git a/internal/service/merchant_admin.go b/internal/service/merchant_admin.go index 3d70438..85f8575 100644 --- a/internal/service/merchant_admin.go +++ b/internal/service/merchant_admin.go @@ -5,4 +5,32 @@ package service -type () +import ( + "context" + "server/internal/model" +) + +type ( + IMerchantAdmin interface { + Login(ctx context.Context, in *model.MerchantLoginIn) (out *model.MerchantLoginOut, err error) + Info(ctx context.Context, in *model.MerchantAdminInfoIn) (out *model.MerchantAdminInfoOut, err error) + Code(ctx context.Context, in *model.MerchantAdminCodeIn) (out *model.MerchantAdminCodeOut, err error) + VertifyPhone(ctx context.Context, in *model.MerchantAdminVertifyPhoneIn) (out *model.MerchantAdminVertifyPhoneOut, err error) + Register(ctx context.Context, in *model.MerchantAdminRegisterIn) (out *model.MerchantAdminRegisterOut, err error) + } +) + +var ( + localMerchantAdmin IMerchantAdmin +) + +func MerchantAdmin() IMerchantAdmin { + if localMerchantAdmin == nil { + panic("implement not found for interface IMerchantAdmin, forgot register?") + } + return localMerchantAdmin +} + +func RegisterMerchantAdmin(i IMerchantAdmin) { + localMerchantAdmin = i +} diff --git a/internal/service/role_menu.go b/internal/service/role_menu.go deleted file mode 100644 index 5430a80..0000000 --- a/internal/service/role_menu.go +++ /dev/null @@ -1,33 +0,0 @@ -// ================================================================================ -// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. -// You can delete these comments if you wish manually maintain this interface file. -// ================================================================================ - -package service - -import ( - "context" - "server/internal/model" -) - -type ( - IRoleMenu interface { - List(ctx context.Context, in *model.RoleMenuListInput) (out *model.MenuListOutput, err error) - Save(ctx context.Context, in *model.RoleMenuSaveInput) (out *model.UpdateOut, err error) - } -) - -var ( - localRoleMenu IRoleMenu -) - -func RoleMenu() IRoleMenu { - if localRoleMenu == nil { - panic("implement not found for interface IRoleMenu, forgot register?") - } - return localRoleMenu -} - -func RegisterRoleMenu(i IRoleMenu) { - localRoleMenu = i -} diff --git a/internal/service/store_admin.go b/internal/service/store_admin.go deleted file mode 100644 index 3d70438..0000000 --- a/internal/service/store_admin.go +++ /dev/null @@ -1,8 +0,0 @@ -// ================================================================================ -// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. -// You can delete these comments if you wish manually maintain this interface file. -// ================================================================================ - -package service - -type () diff --git a/utility/myCasbin/casbin.go b/utility/myCasbin/casbin.go index 7124f7a..bc07771 100644 --- a/utility/myCasbin/casbin.go +++ b/utility/myCasbin/casbin.go @@ -6,6 +6,7 @@ import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/glog" "github.com/hailaz/gf-casbin-adapter/v2" + "server/internal/consts" "sync" ) @@ -33,6 +34,10 @@ func init() { } enforcer.LoadPolicy() + enforcer.AddGroupingPolicy(consts.UserRoleCode, consts.GuestRoleCode) // 用户继承游客角色权限 + + enforcer.AddGroupingPolicy(consts.MerchantRoleCode, consts.StoreRoleCode) // 商户继承门店角色权限 + enforcer.AddGroupingPolicy(consts.AdminRoleCode, consts.MerchantRoleCode) // 管理员继承商户角色权限 // 管理员 { // admin @@ -45,6 +50,10 @@ func init() { enforcer.AddPolicy("admin", "/x/role", "DELETE", "管理员给角色分配权限") enforcer.AddPolicy("admin", "/x/role/*", "DELETE", "管理员删除单个角色") + // merchant + enforcer.AddPolicy("admin", "/x/merchant", "GET", "管理员获取商户列表") + enforcer.AddPolicy("admin", "/x/merchant/audit", "POST", "管理员审核商户申请") + } instance = &myCasbin{Enforcer: enforcer} diff --git a/utility/oss/aliyun/aliyun.go b/utility/oss/aliyun/aliyun.go new file mode 100644 index 0000000..b62f5a2 --- /dev/null +++ b/utility/oss/aliyun/aliyun.go @@ -0,0 +1,97 @@ +package aliyun + +import ( + "bytes" + "context" + "fmt" + "github.com/aliyun/aliyun-oss-go-sdk/oss" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/util/grand" + "server/internal/model" + ioss "server/utility/oss" +) + +type aliyunClient struct { + bucketName string + key string + secret string + endpoint string +} + +// 初始化并注册 +func init() { + ctx := context.Background() + client := &aliyunClient{ + endpoint: g.Config().MustGet(ctx, "oss.aliyun.endpoint").String(), + key: g.Config().MustGet(ctx, "oss.aliyun.key").String(), + secret: g.Config().MustGet(ctx, "oss.aliyun.secret").String(), + bucketName: g.Config().MustGet(ctx, "oss.aliyun.bucket").String(), + } + ioss.Register("aliyun", client) +} + +func (a *aliyunClient) client(ctx context.Context, endpoint, key, sercret string) (*oss.Client, error) { + client, err := oss.New(endpoint, key, sercret) + return client, err +} + +func (a *aliyunClient) bucket(ctx context.Context, client *oss.Client) (*oss.Bucket, error) { + bucket, err := client.Bucket(a.bucketName) + return bucket, err +} +func (a *aliyunClient) bytes(ctx context.Context, in *model.OssBytesInput) (*model.OssOutput, error) { + client, err := a.client(ctx, a.endpoint, a.key, a.secret) + if err != nil { + return nil, err + } + bucket, err := a.bucket(ctx, client) + if err != nil { + return nil, err + } + if in.Name == "" { + in.Name = grand.Digits(32) + } + err = bucket.PutObject(in.Name, bytes.NewReader(in.Bytes)) + if err != nil { + return nil, err + } + return &model.OssOutput{ + Url: fmt.Sprintf("https://%s.%s/%s", a.bucketName, a.endpoint, in.Name), + }, nil +} +func (a *aliyunClient) UploadFile(ctx context.Context, in *model.OssUploadFileInput) (out *model.OssOutput, err error) { + f, err := in.File.Open() + if err != nil { + return nil, err + } + defer f.Close() + body := make([]byte, in.File.Size) + _, err = f.Read(body) + if err != nil { + return nil, err + } + return a.bytes(ctx, &model.OssBytesInput{ + Name: in.Filename, + Bytes: body, + }) +} +func (a *aliyunClient) GetFileURL(ctx context.Context, in *model.OssGetFileInput) (out *model.OssOutput, err error) { + client, err := a.client(ctx, a.endpoint, a.key, a.secret) + if err != nil { + return nil, err + } + bucket, err := a.bucket(ctx, client) + if err != nil { + return nil, err + } + if in.Name == "" { + in.Name = grand.Digits(32) + } + err = bucket.PutObjectFromFile(in.Name, in.FilePath) + if err != nil { + return nil, err + } + return &model.OssOutput{ + Url: fmt.Sprintf("https://%s.%s/%s", a.bucketName, a.endpoint, in.Name), + }, nil +} diff --git a/utility/oss/oss.go b/utility/oss/oss.go new file mode 100644 index 0000000..33dc1ff --- /dev/null +++ b/utility/oss/oss.go @@ -0,0 +1,26 @@ +package oss + +import ( + "context" + "server/internal/model" +) + +// OssClient 是所有云存储平台要实现的统一接口 +type OssClient interface { + UploadFile(ctx context.Context, in *model.OssUploadFileInput) (out *model.OssOutput, err error) + GetFileURL(ctx context.Context, in *model.OssGetFileInput) (out *model.OssOutput, err error) +} + +// registry 存储各个平台的实现 +var clients = make(map[string]OssClient) + +// Register 用于注册平台实现 +func Register(name string, client OssClient) { + clients[name] = client +} + +// GetClient 获取指定平台的实现 +func GetClient(name string) (OssClient, bool) { + client, ok := clients[name] + return client, ok +} diff --git a/utility/sms/aliyun/aliyun.go b/utility/sms/aliyun/aliyun.go new file mode 100644 index 0000000..d699401 --- /dev/null +++ b/utility/sms/aliyun/aliyun.go @@ -0,0 +1,4 @@ +package aliyun + +type aliyunClient struct { +} diff --git a/utility/sms/sms.go b/utility/sms/sms.go new file mode 100644 index 0000000..f1eb947 --- /dev/null +++ b/utility/sms/sms.go @@ -0,0 +1,21 @@ +package sms + +import ( + "context" + "server/internal/model" +) + +type SMSClient interface { + UploadFile(ctx context.Context, in *model.OssUploadFileInput) (out *model.OssOutput, err error) + GetFileURL(ctx context.Context, in *model.OssGetFileInput) (out *model.OssOutput, err error) +} + +var clients = make(map[string]SMSClient) + +func Register(name string, client SMSClient) { + clients[name] = client +} +func GetClient(name string) (SMSClient, bool) { + client, ok := clients[name] + return client, ok +}